From a8b01fc0b70a62bf4bc82b336c5610fe56930f8e Mon Sep 17 00:00:00 2001 From: Jean-Charles Drubay Date: Fri, 11 Feb 2022 19:21:16 +0100 Subject: [PATCH] ADJ: When generating invoices from the Wizard to create invoices manually, reraise any UserError with information about which contract triggered the exception to facilitate the investigation by accountants in case invoices are not generated automatically. --- contract/tests/__init__.py | 1 + contract/tests/test_contract.py | 31 -------- .../test_contract_manually_create_invoice.py | 70 +++++++++++++++++++ .../contract_manually_create_invoice.py | 26 ++++++- 4 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 contract/tests/test_contract_manually_create_invoice.py diff --git a/contract/tests/__init__.py b/contract/tests/__init__.py index 562940edc..9a3586ace 100644 --- a/contract/tests/__init__.py +++ b/contract/tests/__init__.py @@ -1,3 +1,4 @@ from . import test_contract +from . import test_contract_manually_create_invoice from . import test_portal from . import test_multicompany diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index dce80ea27..ef77dc159 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -1754,37 +1754,6 @@ class TestContract(TestContractBase): len(invoice_lines), ) - def test_contract_manually_create_invoice(self): - self.acct_line.date_start = "2018-01-01" - self.acct_line.recurring_invoicing_type = "post-paid" - self.acct_line.date_end = "2018-03-15" - self.contract2.unlink() - contracts = self.contract - for _i in range(10): - contracts |= self.contract.copy() - wizard = self.env["contract.manually.create.invoice"].create( - {"invoice_date": self.today} - ) - wizard.action_show_contract_to_invoice() - contract_to_invoice_count = wizard.contract_to_invoice_count - self.assertFalse( - contracts - - self.env["contract.contract"].search( - wizard.action_show_contract_to_invoice()["domain"] - ), - ) - action = wizard.create_invoice() - invoice_lines = self.env["account.move.line"].search( - [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)] - ) - self.assertEqual( - len(contracts.mapped("contract_line_ids")), - len(invoice_lines), - ) - invoices = self.env["account.move"].search(action["domain"]) - self.assertFalse(invoice_lines.mapped("move_id") - invoices) - self.assertEqual(len(invoices), contract_to_invoice_count) - def test_get_period_to_invoice_monthlylastday_postpaid(self): self.acct_line.date_start = "2018-01-05" self.acct_line.recurring_invoicing_type = "post-paid" diff --git a/contract/tests/test_contract_manually_create_invoice.py b/contract/tests/test_contract_manually_create_invoice.py new file mode 100644 index 000000000..4eedf8c6c --- /dev/null +++ b/contract/tests/test_contract_manually_create_invoice.py @@ -0,0 +1,70 @@ +# Copyright 2018 Tecnativa - Carlos Dauden +# Copyright 2018-2020 Tecnativa - Pedro M. Baeza +# Copyright 2021 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo.exceptions import UserError + +from .test_contract import TestContractBase + + +class TestContractManuallyCreateInvoice(TestContractBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.acct_line.date_start = "2018-01-01" + cls.acct_line.recurring_invoicing_type = "post-paid" + cls.acct_line.date_end = "2018-03-15" + cls.contract2.unlink() + + def test_contract_manually_create_invoice(self): + + contracts = self.contract + for _i in range(10): + contracts |= self.contract.copy() + wizard = self.env["contract.manually.create.invoice"].create( + {"invoice_date": self.today} + ) + wizard.action_show_contract_to_invoice() + contract_to_invoice_count = wizard.contract_to_invoice_count + self.assertFalse( + contracts + - self.env["contract.contract"].search( + wizard.action_show_contract_to_invoice()["domain"] + ), + ) + action = wizard.create_invoice() + invoice_lines = self.env["account.move.line"].search( + [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)] + ) + self.assertEqual( + len(contracts.mapped("contract_line_ids")), + len(invoice_lines), + ) + invoices = self.env["account.move"].search(action["domain"]) + self.assertFalse(invoice_lines.mapped("move_id") - invoices) + self.assertEqual(len(invoices), contract_to_invoice_count) + + def test_contract_manually_create_invoice_with_usererror(self): + + contracts = self.contract + + accounts = self.product_1.product_tmpl_id.get_product_accounts() + accounts["income"].deprecated = True # To trigger a UserError + + for _i in range(3): + contracts |= self.contract.copy() + wizard = self.env["contract.manually.create.invoice"].create( + {"invoice_date": self.acct_line.date_end} + ) + + with self.assertRaises(UserError): + # The UserError re-raise a UserError + wizard.create_invoice() + + try: + wizard.create_invoice() + except Exception as e: + # The re-raised UserError message is the modified one. + self.assertTrue(str(e).startswith("Failed to process the contract")) diff --git a/contract/wizards/contract_manually_create_invoice.py b/contract/wizards/contract_manually_create_invoice.py index 316297001..8175848e1 100644 --- a/contract/wizards/contract_manually_create_invoice.py +++ b/contract/wizards/contract_manually_create_invoice.py @@ -2,6 +2,13 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models +from odoo.exceptions import ( + AccessDenied, + AccessError, + MissingError, + UserError, + ValidationError, +) class ContractManuallyCreateInvoice(models.TransientModel): @@ -52,7 +59,24 @@ class ContractManuallyCreateInvoice(models.TransientModel): self.ensure_one() invoices = self.env["account.move"] for contract in self.contract_to_invoice_ids: - invoices |= contract.recurring_create_invoice() + try: + invoices |= contract.recurring_create_invoice() + except ( + AccessDenied, + AccessError, + MissingError, + UserError, + ValidationError, + ) as oe: + raise UserError( + _( + "Failed to process the contract %(name)s [id: %(id)s]:\n%(ue)s", + name=contract.name, + id=contract.id, + ue=repr(oe), + ) + ) + return { "type": "ir.actions.act_window", "name": _("Invoices"),