From c8b000a7e5414050ca5604954ce16f56a6f8c9cf Mon Sep 17 00:00:00 2001 From: fkantelberg Date: Mon, 13 May 2024 10:18:28 +0200 Subject: [PATCH] [IMP] datev_export_xml: Improve handling and download of bigger files --- datev_export_xml/__init__.py | 2 +- datev_export_xml/controllers/__init__.py | 4 ++ datev_export_xml/controllers/main.py | 40 +++++++++++++++++ datev_export_xml/models/datev_export.py | 16 +++++-- datev_export_xml/tests/test_datev_export.py | 19 +++----- datev_export_xml/views/datev_export_views.xml | 45 +++++++++---------- 6 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 datev_export_xml/controllers/__init__.py create mode 100644 datev_export_xml/controllers/main.py diff --git a/datev_export_xml/__init__.py b/datev_export_xml/__init__.py index 2d0d4cbc..3d5d4bd0 100644 --- a/datev_export_xml/__init__.py +++ b/datev_export_xml/__init__.py @@ -7,4 +7,4 @@ # @author Grzegorz Grzelak # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from . import models +from . import controllers, models diff --git a/datev_export_xml/controllers/__init__.py b/datev_export_xml/controllers/__init__.py new file mode 100644 index 00000000..701c498f --- /dev/null +++ b/datev_export_xml/controllers/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2022-2024 initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import main diff --git a/datev_export_xml/controllers/main.py b/datev_export_xml/controllers/main.py new file mode 100644 index 00000000..a8151e1e --- /dev/null +++ b/datev_export_xml/controllers/main.py @@ -0,0 +1,40 @@ +# Copyright (C) 2022-2024 initOS GmbH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import base64 +import logging + +from odoo import http +from odoo.http import request, send_file + +from odoo.addons.web.controllers.main import Home + +_logger = logging.getLogger(__name__) + + +class DatevHome(Home): + @http.route("/datev/xml/download/", type="http", auth="user") + def datev_xml_download_attachment(self, export_id): + export = request.env["datev.export.xml"].search([("id", "=", export_id)]) + + if not export.attachment_id: + return request.not_found() + + att = export.attachment_id + + if att.store_fname: + full_path = att._full_path(att.store_fname) + return send_file( + full_path, + filename=att.name, + mimetype=att.mimetype, + as_attachment=True, + ) + + return request.make_response( + base64.b64decode(att.datas), + [ + ("Content-Type", att.mimetype), + ("Content-Disposition", f'attachment; filename="{att.name}"'), + ], + ) diff --git a/datev_export_xml/models/datev_export.py b/datev_export_xml/models/datev_export.py index 14846da6..efb4a52a 100644 --- a/datev_export_xml/models/datev_export.py +++ b/datev_export_xml/models/datev_export.py @@ -13,6 +13,7 @@ from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError +from odoo.tools import human_size _logger = logging.getLogger(__name__) @@ -112,7 +113,6 @@ def name_get(self): attachment_id = fields.Many2one( comodel_name="ir.attachment", string="Attachment", required=False, readonly=True ) - datev_file = fields.Binary("ZIP file", readonly=True, related="attachment_id.datas") datev_filename = fields.Char( "ZIP filename", readonly=True, related="attachment_id.name" ) @@ -147,10 +147,10 @@ def name_get(self): tracking=True, ) - @api.depends("attachment_id", "attachment_id.datas") + @api.depends("attachment_id", "attachment_id.file_size") def _compute_datev_filesize(self): - for r in self.with_context(bin_size=True): - r.datev_filesize = r.datev_file + for r in self: + r.datev_filesize = human_size(r.attachment_id.file_size) @api.depends("invoice_ids") def _compute_problematic_invoices_count(self): @@ -180,6 +180,14 @@ def validate_types(self): ) ) + def datev_download(self): + self.ensure_one() + return { + "type": "ir.actions.act_url", + "url": f"/datev/xml/download/{self.id}", + "target": "self", + } + def get_type_list(self): list_invoice_type = [] if self.export_type: diff --git a/datev_export_xml/tests/test_datev_export.py b/datev_export_xml/tests/test_datev_export.py index 7c3c9fcf..0009172e 100644 --- a/datev_export_xml/tests/test_datev_export.py +++ b/datev_export_xml/tests/test_datev_export.py @@ -93,7 +93,7 @@ def _check_filecontent(self, export): export.check_valid_data(export.invoice_ids) invoice = export.invoice_ids[0].name invoice = invoice.replace("/", "-") - zip_data = base64.b64decode(export.datev_file) + zip_data = base64.b64decode(export.attachment_id.datas) fp = io.BytesIO() fp.write(zip_data) zipfile.is_zipfile(fp) @@ -376,7 +376,7 @@ def _run_test_out_refund_datev_export(self, refund): start_date = refund.invoice_date end_date = refund.invoice_date_due datev_export = self.create_customer_datev_export(start_date, end_date) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, @@ -401,7 +401,6 @@ def _run_test_out_refund_datev_export(self, refund): self.assertTrue(datev_export.datev_filesize) self.assertEqual(datev_export.state, "done") - self.assertTrue(datev_export.datev_file) self.assertTrue(datev_export.attachment_id) file_list = ["document.xml", inv_number + ".xml", inv_number + ".pdf"] res = self._check_filecontent(datev_export) @@ -427,7 +426,7 @@ def _run_test_in_refund_datev_export(self, refund, attachment): datev_export = self.create_vendor_datev_export(start_date, end_date) attachment = self.update_attachment(attachment, refund) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, @@ -452,7 +451,6 @@ def _run_test_in_refund_datev_export(self, refund, attachment): # self.DatevExportObj.refresh() self.assertEqual(datev_export.state, "done") - self.assertTrue(datev_export.datev_file) self.assertTrue(datev_export.attachment_id) file_list = ["document.xml", f"{inv_number}.xml", f"{inv_number}.pdf"] res = self._check_filecontent(datev_export) @@ -476,7 +474,7 @@ def _run_test_out_invoice_datev_export(self, invoice): start_date = invoice.invoice_date end_date = invoice.invoice_date_due datev_export = self.create_customer_datev_export(start_date, end_date) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, @@ -501,7 +499,6 @@ def _run_test_out_invoice_datev_export(self, invoice): # self.DatevExportObj.refresh() self.assertEqual(datev_export.state, "done") - self.assertTrue(datev_export.datev_file) self.assertTrue(datev_export.attachment_id) file_list = ["document.xml", inv_number + ".xml", inv_number + ".pdf"] res = self._check_filecontent(datev_export) @@ -527,7 +524,7 @@ def _run_test_in_invoice_datev_export(self, invoice, attachment): datev_export = self.create_vendor_datev_export(start_date, end_date) attachment = self.update_attachment(attachment, invoice) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, @@ -551,7 +548,6 @@ def _run_test_in_invoice_datev_export(self, invoice, attachment): # self.DatevExportObj.refresh() self.assertEqual(datev_export.state, "done") - self.assertTrue(datev_export.datev_file) self.assertTrue(datev_export.attachment_id) file_list = ["document.xml", f"{inv_number}.xml", f"{inv_number}.pdf"] res = self._check_filecontent(datev_export) @@ -573,7 +569,7 @@ def _run_test_out_inv_datev_export_manually(self, invoice): self.assertEqual(invoice.state, "posted") datev_export = self.create_customer_datev_export_manually(invoice) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, @@ -596,7 +592,6 @@ def _run_test_out_inv_datev_export_manually(self, invoice): {"datev_mode": "datev_export"} ).export_zip() self.assertEqual(datev_export.state, "done") - self.assertTrue(datev_export.datev_file) self.assertTrue(datev_export.attachment_id) file_list = ["document.xml", inv_number + ".xml", inv_number + ".pdf"] res = self._check_filecontent(datev_export) @@ -752,7 +747,7 @@ def test_14_datev_export_without_invoice(self): "export_type": "out", } ) - self.assertEqual(datev_export.datev_file, False) + self.assertFalse(datev_export.attachment_id) self.assertEqual( datev_export.client_number, self.env.company.datev_client_number, diff --git a/datev_export_xml/views/datev_export_views.xml b/datev_export_xml/views/datev_export_views.xml index c8b5d320..477283ec 100644 --- a/datev_export_xml/views/datev_export_views.xml +++ b/datev_export_xml/views/datev_export_views.xml @@ -118,7 +118,7 @@ name="export_zip" type="object" class="oe_highlight" - attrs="{'invisible': ['|', ('datev_file', '!=', False), ('manually_document_selection', '=', False)]}" + attrs="{'invisible': ['|', ('attachment_id', '!=', False), ('manually_document_selection', '=', False)]}" confirm="The creation of the file can take some time! Do you really want to proceed!" /> @@ -307,7 +305,7 @@ name="export_zip" type="object" class="oe_highlight" - attrs="{'invisible': ['|', ('datev_file', '!=', False), ('manually_document_selection', '=', True)]}" + attrs="{'invisible': ['|', ('attachment_id', '!=', False), ('manually_document_selection', '=', True)]}" confirm="The creation of the file will be done in background and may take some time! When the file is created or an exception occurs, an activity will be applied to you." /> @@ -316,7 +314,7 @@ name="export_zip" type="object" class="" - attrs="{'invisible': ['|', ('datev_file', '=', False), ('manually_document_selection', '=', True)]}" + attrs="{'invisible': ['|', ('attachment_id', '=', False), ('manually_document_selection', '=', True)]}" confirm="Do you really want to create the DATEV file again? The creation of the file will be done in background and may take some time! When the file is created or an exception occurs, an activity will be applied to you." /> @@ -326,7 +324,7 @@ name="export_zip" type="object" class="oe_highlight" - attrs="{'invisible': ['|', ('datev_file', '!=', False), ('manually_document_selection', '=', False)]}" + attrs="{'invisible': ['|', ('attachment_id', '!=', False), ('manually_document_selection', '=', False)]}" confirm="The creation of the file can take some time! Do you really want to proceed!" /> @@ -335,7 +333,7 @@ name="export_zip" type="object" class="" - attrs="{'invisible': ['|', ('datev_file', '=', False), ('manually_document_selection', '=', False)]}" + attrs="{'invisible': ['|', ('attachment_id', '=', False), ('manually_document_selection', '=', False)]}" confirm="The creation of the file can take some time! Do you really want to create the DATEV file again?" /> @@ -373,9 +371,6 @@ - - -