diff --git a/report_xlsx/models/ir_report.py b/report_xlsx/models/ir_report.py index f96c6b4a4..9d07d9559 100644 --- a/report_xlsx/models/ir_report.py +++ b/report_xlsx/models/ir_report.py @@ -1,7 +1,12 @@ # Copyright 2015 ACSONE SA/NV () # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +import logging + +from odoo import api, exceptions, fields, models +from odoo.tools.safe_eval import safe_eval, time + +_logger = logging.getLogger(__name__) class ReportAction(models.Model): @@ -16,11 +21,14 @@ class ReportAction(models.Model): report_sudo = self._get_report(report_ref) report_model_name = "report.%s" % report_sudo.report_name report_model = self.env[report_model_name] - return ( + ret = ( report_model.with_context(active_model=report_sudo.model) .sudo(False) .create_xlsx_report(docids, data) # noqa ) + if ret and isinstance(ret, (tuple, list)): # data, "xlsx" + report_sudo.save_xlsx_report_attachment(docids, ret[0]) + return ret @api.model def _get_report_from_name(self, report_name): @@ -35,3 +43,37 @@ class ReportAction(models.Model): ] context = self.env["res.users"].context_get() return report_obj.with_context(**context).search(conditions, limit=1) + + def save_xlsx_report_attachment(self, docids, report_contents): + """Save as attachment when the report is set up as such.""" + # Similar to ir.actions.report::_render_qweb_pdf in the base module. + if not self.attachment: + return + if len(docids) != 1: # unlike PDFs, here we don't have multiple streams + _logger.warning(f"{self.name}: No records to save attachments onto.") + return + record = self.env[self.model].browse(docids) + attachment_name = safe_eval(self.attachment, {"object": record, "time": time}) + if not attachment_name: + return # same as for PDFs, get out silently when name fails + attachment_values = { + "name": attachment_name, + "raw": report_contents, + "res_id": record.id, + "res_model": self.model, + "type": "binary", + } + try: + attachment = self.env["ir.attachment"].create(attachment_values) + except exceptions.AccessError: + _logger.info( + "Cannot save XLSX report %r attachment for user %r", + attachment_values["name"], + self.env.user.display_name, + ) + else: + _logger.info( + "The XLSX document %r is now saved in the database", + attachment_values["name"], + ) + return attachment, record diff --git a/report_xlsx/readme/CONTRIBUTORS.rst b/report_xlsx/readme/CONTRIBUTORS.rst index de4de00b7..f9e7f1c59 100644 --- a/report_xlsx/readme/CONTRIBUTORS.rst +++ b/report_xlsx/readme/CONTRIBUTORS.rst @@ -7,3 +7,4 @@ * Rod Schouteden * Eugene Molotov * Christopher Ormaza +* Houz??fa Abbasbhay diff --git a/report_xlsx/tests/test_report.py b/report_xlsx/tests/test_report.py index 28fd6efb7..6bfb836b5 100644 --- a/report_xlsx/tests/test_report.py +++ b/report_xlsx/tests/test_report.py @@ -32,6 +32,15 @@ class TestReport(common.TransactionCase): sheet = wb.sheet_by_index(0) self.assertEqual(sheet.cell(0, 0).value, self.docs.name) + def test_save_attachment(self): + self.report.attachment = 'object.name + ".xlsx"' + self.report_object._render(self.report_name, self.docs.ids, {}) + attachment = self.env["ir.attachment"].search( + [("res_id", "=", self.docs.id), ("res_model", "=", self.docs._name)] + ) + self.assertEqual(len(attachment), 1) + self.assertEqual(attachment.name, f"{self.docs.name}.xlsx") + def test_id_retrieval(self): # Typical call from WebUI with wizard