From 22eb8e7b6aede0635087fd427b338319d420ed06 Mon Sep 17 00:00:00 2001 From: Sven Fuehr Date: Wed, 4 Oct 2023 18:40:25 +0200 Subject: [PATCH] [IMP] account_edi_ubl_cii: improve import of XML invoice with errors Sometimes the user needs to import XML invoices (e.g. factur-x) containing lines with the following problem: The billed quantity of the line is set to 0 but the total of the line (plus/minus allowances) is not 0. The imported version (in odoo) of this line will have quantity 0 and thus a total of 0 (since the total will be computed in odoo and not stored directly in the database). After this commit the quantity of these line will be calculated such that the total computation yields the correct total. To do this an already existing similar "exception" in the parsing logic was extended to deal with this problem. closes odoo/odoo#137833 Signed-off-by: Laurent Smet (las) --- .../models/account_edi_common.py | 15 +- .../tests/common.py | 3 + ...nvoice_quantity_and_or_unit_price_zero.xml | 179 ++++++++++++++++++ .../tests/test_xml_ubl_be.py | 12 ++ 4 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_quantity_and_or_unit_price_zero.xml diff --git a/addons/account_edi_ubl_cii/models/account_edi_common.py b/addons/account_edi_ubl_cii/models/account_edi_common.py index 846c227ef04..55d6d066840 100644 --- a/addons/account_edi_ubl_cii/models/account_edi_common.py +++ b/addons/account_edi_ubl_cii/models/account_edi_common.py @@ -609,11 +609,20 @@ class AccountEdiCommon(models.AbstractModel): if billed_qty * price_unit != 0 and price_subtotal is not None: discount = 100 * (1 - (price_subtotal - amount_fixed_taxes) / (billed_qty * price_unit)) - # Sometimes, the xml received is very bad: unit price = 0, qty = 1, but price_subtotal = -200 + # Sometimes, the xml received is very bad; e.g.: + # * unit price = 0, qty = 0, but price_subtotal = -200 + # * unit price = 0, qty = 1, but price_subtotal = -200 + # * unit price = 1, qty = 0, but price_subtotal = -200 # for instance, when filling a down payment as an invoice line. The equation in the docstring is not # respected, and the result will not be correct, so we just follow the simple rule below: - if net_price_unit == 0 and price_subtotal != net_price_unit * (billed_qty / basis_qty) - allow_charge_amount: - price_unit = price_subtotal / (billed_qty or 1) + if net_price_unit is not None and price_subtotal != net_price_unit * (billed_qty / basis_qty) - allow_charge_amount: + if net_price_unit == 0 and billed_qty == 0: + quantity = 1 + price_unit = price_subtotal + elif net_price_unit == 0: + price_unit = price_subtotal / billed_qty + elif billed_qty == 0: + quantity = price_subtotal / price_unit return { 'quantity': quantity, diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/common.py b/addons/l10n_account_edi_ubl_cii_tests/tests/common.py index 045ba3f243b..bff480c938f 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/common.py +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/common.py @@ -129,6 +129,7 @@ class TestUBLCommon(AccountTestInvoicingCommon): def _assert_imported_invoice_from_file(self, subfolder, filename, amount_total, amount_tax, list_line_subtotals, list_line_price_unit=None, list_line_discount=None, list_line_taxes=None, + list_line_quantity=None, move_type='in_invoice', currency_id=None): """ Create an empty account.move, update the file to fill its fields, asserts the currency, total and tax amounts @@ -178,6 +179,8 @@ class TestUBLCommon(AccountTestInvoicingCommon): if list_line_taxes: for line, taxes in zip(invoice.invoice_line_ids, list_line_taxes): self.assertEqual(line.tax_ids, taxes) + if list_line_quantity: + self.assertEqual(invoice.invoice_line_ids.mapped('quantity'), list_line_quantity) # ------------------------------------------------------------------------- # EXPORT HELPERS diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_quantity_and_or_unit_price_zero.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_quantity_and_or_unit_price_zero.xml new file mode 100644 index 00000000000..ef5891b70a5 --- /dev/null +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_quantity_and_or_unit_price_zero.xml @@ -0,0 +1,179 @@ + + + urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + INV/2017/01/0002 + 2017-01-01 + 2017-02-28 + 380 + test narration + USD + ref_partner_2 + + ___ignore___ + + + ___ignore___ + + ___ignore___ + + + + + 0202239951 + + partner_1 + + + Chaussée de Namur 40 + Ramillies + 1367 + + BE + + + + BE0202239951 + + VAT + + + + partner_1 + BE0202239951 + + + partner_1 + + + + + + 0477472701 + + partner_2 + + + Rue des Bourlottes 9 + Ramillies + 1367 + + BE + + + + BE0477472701 + + VAT + + + + partner_2 + BE0477472701 + + + partner_2 + + + + + + + Rue des Bourlottes 9 + Ramillies + 1367 + + BE + + + + + + 30 + +++000/0000/26268+++ + + BE15001559627230 + + + + Payment terms: 30% Advance End of Following Month + + + 630.00 + + 3000.00 + 630 + + S + 21.0 + + VAT + + + + + + 3000.00 + 3000.00 + 3630.00 + 0.00 + 3630.00 + + + 901 + 0 + 1000.00 + + product_b + product_b + + S + 21.0 + + VAT + + + + + 0 + + + + 902 + 0 + 1000.00 + + product_b + product_b + + S + 21.0 + + VAT + + + + + 100.00 + + + + 903 + 100 + 1000.00 + + product_b + product_b + + S + 21.0 + + VAT + + + + + 0 + + + diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_xml_ubl_be.py b/addons/l10n_account_edi_ubl_cii_tests/tests/test_xml_ubl_be.py index e0a4e41d782..8607f879f50 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_xml_ubl_be.py +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_xml_ubl_be.py @@ -687,3 +687,15 @@ class TestUBLBE(TestUBLCommon, TestAccountMoveSendCommon): ('res_field', 'in', ('invoice_pdf_report_file', 'ubl_cii_xml_file')), ]) self.assertEqual(len(invoice_attachments), 2) + + def test_import_quantity_and_or_unit_price_zero(self): + """ Tests some special handling cases in which the quantity or unit_price are missing. + """ + subfolder = "tests/test_files/from_odoo" + # The tax 21% from l10n_be is retrieved since it's a duplicate of self.tax_21 + tax_21 = self.env.ref(f'account.{self.env.company.id}_attn_VAT-OUT-21-L') + self._assert_imported_invoice_from_file( + subfolder=subfolder, filename='bis3_out_invoice_quantity_and_or_unit_price_zero.xml', amount_total=3630.00, amount_tax=630.00, + list_line_subtotals=[1000, 1000, 1000], currency_id=self.currency_data['currency'].id, list_line_price_unit=[1000, 100, 10], + list_line_discount=[0, 0, 0], list_line_taxes=[tax_21, tax_21, tax_21], list_line_quantity=[1, 10, 100], move_type='out_invoice', + )