From 4a73cbbe2b977eecb588f2891feb1f383a588832 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 2dafab3fc..9de1b60ae 100644 --- a/contract/tests/__init__.py +++ b/contract/tests/__init__.py @@ -1,4 +1,5 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import test_contract +from . import test_contract_manually_create_invoice from . import test_portal diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index f65caae97..37eea84f6 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -1743,37 +1743,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 4bdf684f5..d22c7c086 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), + ) + ) from oe + return { "type": "ir.actions.act_window", "name": _("Invoices"),