From 812e21d589e65397f7e135481c8c70b146450e03 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 29 Jul 2020 13:32:54 +0200 Subject: [PATCH] [IMP] report_csv: Add support to save the result as attachment --- report_csv/controllers/main.py | 4 ++-- report_csv/models/report.py | 39 +++++++++++++++++++++++++++++++++ report_csv/tests/test_report.py | 25 ++++++++++++++++++--- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/report_csv/controllers/main.py b/report_csv/controllers/main.py index 2b44a376f..eab0b9914 100644 --- a/report_csv/controllers/main.py +++ b/report_csv/controllers/main.py @@ -37,8 +37,8 @@ class ReportController(report.ReportController): del data['context']['lang'] context.update(data['context']) - csv = report.with_context(context).render_csv( - docids, data=data + csv = request.env["report"].with_context(context).get_csv( + docids, reportname, data=data )[0] filename = "%s.%s" % (report.name, "csv") if docids: diff --git a/report_csv/models/report.py b/report_csv/models/report.py index fc8832875..7c4bb20a0 100644 --- a/report_csv/models/report.py +++ b/report_csv/models/report.py @@ -2,7 +2,13 @@ # Copyright 2017 Akretion (http://www.akretion.com/) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import base64 +import logging + from odoo import api, models +from odoo.exceptions import AccessError + +_logger = logging.getLogger(__name__) class Report(models.Model): @@ -23,3 +29,36 @@ class Report(models.Model): ('report_name', '=', report_name)] context = self.env['res.users'].context_get() return report_obj.with_context(context).search(conditions, limit=1) + + @api.model + def get_csv(self, docids, report_name, data=None): + # Get the ir.actions.report.xml record we are working on. + report = self._get_report_from_name(report_name) + # Check if we have to save the report or if we have to get one from the db. + save_in_attachment = self._check_attachment_use(docids, report) + res_id = len(docids) == 1 and docids[0] + if res_id: + loaded_doc = save_in_attachment['loaded_documents'].get(res_id) + if loaded_doc: + return loaded_doc, 'csv' + + data, ext = report.render_csv(docids, data) + + if res_id and data and save_in_attachment.get(res_id): + attachment = { + 'name': save_in_attachment.get(res_id), + 'datas': base64.encodestring(data), + 'datas_fname': save_in_attachment.get(res_id), + 'res_model': save_in_attachment.get('model'), + 'res_id': res_id, + } + try: + self.env['ir.attachment'].create(attachment) + except AccessError: + _logger.info("Cannot save csv report %r as attachment", + attachment['name']) + else: + _logger.info( + 'The csv document %s is now saved in the database', + attachment['name']) + return data, ext diff --git a/report_csv/tests/test_report.py b/report_csv/tests/test_report.py index b510b69ed..fe16eec85 100644 --- a/report_csv/tests/test_report.py +++ b/report_csv/tests/test_report.py @@ -9,24 +9,43 @@ from odoo.tests import common class TestReport(common.TransactionCase): def setUp(self): super(TestReport, self,).setUp() - report_object = self.env['report'] + self.Report = self.env['report'] + self.IrAttachment = self.env["ir.attachment"] self.csv_report = ( self.env['report.report_csv.abstract'] .with_context(active_model='res.partner') ) self.report_name = 'report_csv.partner_csv' - self.report = report_object._get_report_from_name(self.report_name) + self.report = self.Report._get_report_from_name(self.report_name) self.docs = self.env['res.company'].search([], limit=1).partner_id + def _get_doc_attachments(self, docs): + return self.IrAttachment.search( + [("res_id", "in", docs.ids), + ("res_model", "=", docs._name)] + ) + def test_report(self): report = self.report self.assertEqual(report.report_type, 'csv') - rep = report.render_csv(self.docs.ids, {}) + rep = self.Report.get_csv(self.docs.ids, self.report_name, {}) str_io = StringIO(rep[0]) dict_report = list(csv.DictReader(str_io, delimiter=';', quoting=csv.QUOTE_ALL)) self.assertEqual(self.docs.name, dict(dict_report[0])['name']) + def test_report_save_in_attachment(self): + attachment = self._get_doc_attachments(self.docs) + self.report.attachment = "'test.csv'" + self.report.attachment_use = True + rep = self.Report.get_csv(self.docs.ids, self.report_name, {}) + attachment = self._get_doc_attachments(self.docs) - attachment + self.assertTrue(attachment) + self.assertEqual(attachment.datas.decode("base64"), rep[0]) + attachment.datas = "test".encode("base64") + rep = self.Report.get_csv(self.docs.ids, self.report_name, {}) + self.assertEqual(rep[0], "test") + def test_id_retrieval(self): # Typical call from WebUI with wizard