From f2964dc02a6a8796b45346f8060e1c2d3837125b Mon Sep 17 00:00:00 2001 From: hupo-odoo Date: Fri, 28 Jul 2023 12:53:43 +0000 Subject: [PATCH] [FIX] account{,_edi,_ubl_cii}: mass export edi documents When selecting several invoices from the list view, it is possible to trigger an action to export all edi documents in a zip file. This commit fixes 2 different issues: a) We want to be able to export edi documents that have not been sent. Therefore, we no longer filter for 'sent' and 'cancelled' edi documents. b) We want to also export edi documents that have ubl format. These documents are, from 16.2, in another field on account.move and no longer part of edi_document_ids. This is the reason why we had to move the logic from account_edi to account to make it overridable to other modules. This new way of overriding the function will also enable other formats to be included in the export function. task-3441449 (issue 1) task-3439427 (issue 2) closes odoo/odoo#131242 X-original-commit: f8654b3501aca6e5d77ced5f73cb351c61684cd2 Related: odoo/enterprise#45529 Related: odoo/upgrade#5032 Signed-off-by: Laurent Smet (las) --- addons/account/controllers/__init__.py | 1 + .../account/controllers/download_edi_docs.py | 36 +++++++++++++++++++ addons/account/models/account_move.py | 23 ++++++++++++ addons/account/views/account_move_views.xml | 12 +++++++ addons/account_edi/__init__.py | 1 - addons/account_edi/controller/__init__.py | 1 - addons/account_edi/controller/main.py | 18 ---------- addons/account_edi/models/account_move.py | 24 ++----------- .../account_edi/views/account_move_views.xml | 11 ------ .../models/account_move.py | 4 +++ 10 files changed, 79 insertions(+), 52 deletions(-) create mode 100644 addons/account/controllers/download_edi_docs.py delete mode 100644 addons/account_edi/controller/__init__.py delete mode 100644 addons/account_edi/controller/main.py diff --git a/addons/account/controllers/__init__.py b/addons/account/controllers/__init__.py index 44eea6b8e43..ffbfd584f8f 100644 --- a/addons/account/controllers/__init__.py +++ b/addons/account/controllers/__init__.py @@ -3,3 +3,4 @@ from . import portal from . import terms +from . import download_edi_docs diff --git a/addons/account/controllers/download_edi_docs.py b/addons/account/controllers/download_edi_docs.py new file mode 100644 index 00000000000..e8d0cbfb1ba --- /dev/null +++ b/addons/account/controllers/download_edi_docs.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +import io +import zipfile + +from odoo import http, _ +from odoo.http import request, content_disposition + +class AccountEdiDocumentDownloadController(http.Controller): + @http.route('/account/export_edi_documents', type='http', auth='user') + def export_edi_documents(self, **args): + ids = list(map(int, request.httprequest.args.getlist('ids'))) + + moves = request.env['account.move'].browse(ids) + moves.check_access_rights('read') + moves.check_access_rule('read') + + attachments = moves._get_edi_doc_attachments_to_export() + if not attachments: + error_msg = _("No EDI documents found for export.") + return request.not_found(error_msg) + + # Create zip file + buffer = io.BytesIO() + with zipfile.ZipFile(buffer, 'w', compression=zipfile.ZIP_DEFLATED) as zipfile_obj: + for attachment in attachments: + zipfile_obj.writestr(attachment.display_name, attachment.raw) + content = buffer.getvalue() + + headers = [ + ('Content-Type', 'zip'), + ('X-Content-Type-Options', 'nosniff'), + ('Content-Length', len(content)), + ('Content-Disposition', content_disposition('edi_documents.zip')), + ] + return request.make_response(content, headers) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index f895ca159c1..d727c4c0d5a 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +from werkzeug.urls import url_encode + from collections import defaultdict from contextlib import ExitStack, contextmanager from datetime import date, timedelta @@ -3101,6 +3103,27 @@ class AccountMove(models.Model): return success + #################################################### + # Export Electronic Document + #################################################### + + def _action_download_electronic_invoice(self): + if not self: + return False + return { + 'type': 'ir.actions.act_url', + 'url': '/account/export_edi_documents?%s' % url_encode({'ids': self.ids}), + 'target': 'new', + } + + def _get_edi_doc_attachments_to_export(self): + """ + To override + :return a recordset of ir.attachment to export + """ + return self.env['ir.attachment'] + + # ------------------------------------------------------------------------- # BUSINESS METHODS # ------------------------------------------------------------------------- diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml index 8b9ecf80280..da699d5bb3e 100644 --- a/addons/account/views/account_move_views.xml +++ b/addons/account/views/account_move_views.xml @@ -1644,5 +1644,17 @@ if records: + + Download Electronic Invoices + + + list + code + + if records: + action = records._action_download_electronic_invoice() + + + diff --git a/addons/account_edi/__init__.py b/addons/account_edi/__init__.py index 3a7dfde6acb..7749576f92c 100644 --- a/addons/account_edi/__init__.py +++ b/addons/account_edi/__init__.py @@ -1,5 +1,4 @@ # -*- encoding: utf-8 -*- from . import models -from . import controller from . import wizard diff --git a/addons/account_edi/controller/__init__.py b/addons/account_edi/controller/__init__.py deleted file mode 100644 index 12a7e529b67..00000000000 --- a/addons/account_edi/controller/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import main diff --git a/addons/account_edi/controller/main.py b/addons/account_edi/controller/main.py deleted file mode 100644 index 065b7dff157..00000000000 --- a/addons/account_edi/controller/main.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import http -from odoo.http import request, content_disposition - - -class EdiDocumentDownloadController(http.Controller): - @http.route('/account_edi/download_edi_documents', type='http', auth='user') - def download_edi_documents(self, **args): - ids = list(map(int, request.httprequest.args.getlist('ids'))) - content = request.env['account.move'].browse(ids)._create_zipped() - headers = [ - ('Content-Type', 'zip'), - ('X-Content-Type-Options', 'nosniff'), - ('Content-Length', len(content)), - ('Content-Disposition', content_disposition('edi_documents.zip')), - ] - return request.make_response(content, headers) diff --git a/addons/account_edi/models/account_move.py b/addons/account_edi/models/account_move.py index 45463090be9..90dbbdba7b3 100644 --- a/addons/account_edi/models/account_move.py +++ b/addons/account_edi/models/account_move.py @@ -379,24 +379,6 @@ class AccountMove(models.Model): move_result.setdefault('attachments', []).extend(edi_attachments.get('attachments', [])) return result - #################################################### - # Export Electronic Document - #################################################### - - def _action_download_electronic_invoice(self): - if not self: - return False - return { - 'type': 'ir.actions.act_url', - 'url': '/account_edi/download_edi_documents?%s' % url_encode({'ids': self.filtered('edi_document_ids').ids}), - 'target': 'new', - } - - def _create_zipped(self): - buffer = io.BytesIO() - with zipfile.ZipFile(buffer, 'w', compression=zipfile.ZIP_DEFLATED) as zipfile_obj: - for invoice in self: - for document in invoice.edi_document_ids: - if document.state in {'sent', 'cancelled'}: - zipfile_obj.writestr(document.display_name, document.attachment_id.raw) - return buffer.getvalue() + def _get_edi_doc_attachments_to_export(self): + # EXTENDS 'account' + return super()._get_edi_doc_attachments_to_export() + self.edi_document_ids.attachment_id diff --git a/addons/account_edi/views/account_move_views.xml b/addons/account_edi/views/account_move_views.xml index d7ae9a03f2b..03127f54772 100644 --- a/addons/account_edi/views/account_move_views.xml +++ b/addons/account_edi/views/account_move_views.xml @@ -142,16 +142,5 @@ - - Download Electronic Invoices - - - list - code - - if records: - action = records._action_download_electronic_invoice() - - diff --git a/addons/account_edi_ubl_cii/models/account_move.py b/addons/account_edi_ubl_cii/models/account_move.py index 13f2803181c..0006d9ba495 100644 --- a/addons/account_edi_ubl_cii/models/account_move.py +++ b/addons/account_edi_ubl_cii/models/account_move.py @@ -52,3 +52,7 @@ class AccountMove(models.Model): return ubl_cii_xml_builder._import_invoice_ubl_cii return super()._get_edi_decoder(file_data, new=new) + + def _get_edi_doc_attachments_to_export(self): + # EXTENDS 'account' + return super()._get_edi_doc_attachments_to_export() + self.ubl_cii_xml_id