Cara Download Odoo Report PDF dari Flutter, Kustomisasi Odoo dengan Flutter

Dalam era digital yang berkembang sangat pesat ini, diperlukan integrasi antar platform untuk memberikan hasil maksimal dalam implementasi ERP. Flutter dan Odoo merupakan platform open source yang sangat handal untuk membangun sistem ERP terintegrasi yang sangat kuat.

Kali ini saya akan membagikan pengalaman bagimana kustomisasi Odoo dengan front end Flutter yang bisa dijadikan teman-teman untuk referensi dalam membangun sistem ERP yang lebih maksimal.

Dalam hal ini sesuai permintaan customer, aplikasi mobile yang dibangun dimunculkan tombol untuk langsung mendownload file PDF dari Odoo, hasilnya seperti ini

Dalam hal ini jika diklik ‘Download Laporan Cepat’ maka aplikasi akan langsung mengambil file PDF yang ada di server Odoo

Untuk melakukannya pertama kali yang dilakukan adalah membuat Controller dengan autentikasi publik sehingga tidak memerlukan XML-RPC dari Flutter ke Odoo

class DownloadInsidenRLCeportController(http.Controller):

    @http.route('/download_report/<docids>', type='http', auth='public', website=True)
    def download_insiden_lc_report(self, docids=None, **data):
        report = request.env['ir.actions.report']
        context = dict(request.env.context)
        reportname = 'superapp.insiden_lc_report'

        if docids:
            docids = [int(i) for i in docids.split(',') if i.isdigit()]
            docids_str = '_'.join(map(str, docids))  # Menggabungkan docids menjadi satu string
        else:
            docids_str = 'no_docids'

        if data.get('options'):
            data.update(json.loads(data.pop('options')))
        if data.get('context'):
            data['context'] = json.loads(data['context'])
            context.update(data['context'])

        pdf = report.with_context(context).sudo()._render_qweb_pdf(reportname, docids, data=data)[0]
        pdfhttpheaders = [
            ('Content-Type', 'application/pdf'),
            ('Content-Length', len(pdf)),
            ('Content-Disposition', f'attachment; filename="insiden_lc_report_{docids_str}.pdf"')
        ]
        return request.make_response(pdf, headers=pdfhttpheaders)

Jika kontroller tersebut diakses anonim maka akan langsung mendownload PDF yang diinginkan, teman-teman bisa mengimprove dengan menambahkan autentikasi jika diperlukan. Namun di dalam case ini kami tidak memerlukan autentikasi

Selanjutnya tambahkan fungsi di Flutter untuk mengakses file tersebut

Future<void> bukaUrl(String url) async {
  final Uri s = Uri.parse(url);
  if (!await launchUrl(s)) {
    throw Exception('Could not launch $url');
  }
}

Selanjutnya bisa memanggil fungsi tersebut dari tombol yang ada di Flutter

TextButton.icon(
  onPressed: () async {
	await bukaUrl(url);
  },
  icon:
	  Icon(Icons.download, color: const Color.fromARGB(255, 207, 33, 40)),
  label: Text('Download Laporan Cepat'),
  style: TextButton.styleFrom(
	foregroundColor: const Color.fromARGB(255, 207, 33, 40),
	padding: EdgeInsets.zero, // Warna teks
  ),
), 

Fungsi di atas jika dieksekusi akan membuka broser, jika Anda tidak ingin membuka browser tetapi menyimpan file di folder aplikasi maka gunakan fungsi seperti ini

Future<void> downloadAndOpenFile(String url, String fileName) async {
  Dio dio = Dio();

  try {
    // Mengganti spasi dengan underscore di fileName
    String sanitizedFileName = fileName.replaceAll(' ', '_');

    // Mendapatkan direktori unduhan
    Directory appDocDir = await getApplicationDocumentsDirectory();
    String savePath = "${appDocDir.path}/$sanitizedFileName";

    // Mengunduh file
    await dio.download(url, savePath, onReceiveProgress: (received, total) {
      if (total != -1) {
        print("Download progress: ${(received / total * 100).toStringAsFixed(0)}%");
      }
    });

    print("File disimpan di: $savePath");

    // Membuka file setelah diunduh
    final result = await OpenFile.open(savePath);
    print("Hasil membuka file: ${result.message}");
  } catch (e) {
    print("Error: $e");
  }
}

Semoga bermanfaat

Leave a Comment

Your email address will not be published. Required fields are marked *

1