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', + )