From 45a0fb28566355c1dffeac63bd70c275939cec09 Mon Sep 17 00:00:00 2001 From: "Dylan Kiss (dyki)" Date: Tue, 7 May 2024 14:36:14 +0200 Subject: [PATCH] [FIX] account_edi_ubl_cii: invert negative unit price with quantity Currently, when we use eCommerce with automatic invoicing enabled, and we have the Peppol format enabled in the invoicing settings, there is an issue when coupons or discount codes are applied. These discounts create a sale order line (and afterwards a move line) with a negative unit price. Since UBL BIS3 does not allow negative unit prices, the automatic generation of the e-invoice is not executed and the customer receives a "proforma invoice" PDF instead (which has no official value). A message is logged in the chatter, but the user has no notification or anything. We can do better, and instead invert both the unit price and quantity fields (since UBL BIS3 does allow negative quantities), to have the same result when generating the e-invoice. task-3916181 --- .../models/account_edi_xml_ubl_bis3.py | 6 + .../bis3_out_invoice_negative_unit_price.xml | 145 ++++++++++++++++++ .../tests/test_xml_ubl_be.py | 29 ++++ 3 files changed, 180 insertions(+) create mode 100644 addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_negative_unit_price.xml diff --git a/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_bis3.py b/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_bis3.py index 3a2e3b24283e7..8c78471122796 100644 --- a/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_bis3.py +++ b/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_bis3.py @@ -267,6 +267,12 @@ def _get_invoice_line_vals(self, line, taxes_vals): vals['currency_dp'] = 2 vals['price_vals']['currency_dp'] = 2 + if line.currency_id.compare_amounts(vals['price_vals']['price_amount'], 0) == -1: + # We can't have negative unit prices, so we invert the signs of + # the unit price and quantity, resulting in the same amount in the end + vals['price_vals']['price_amount'] *= -1 + vals['invoiced_quantity'] *= -1 + return vals def _export_invoice_vals(self, invoice): diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_negative_unit_price.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_negative_unit_price.xml new file mode 100644 index 0000000000000..fd3d775317a46 --- /dev/null +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_negative_unit_price.xml @@ -0,0 +1,145 @@ + + + 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 + ___ignore___ + 2017-01-01 + 2017-02-28 + 380 + test narration + USD + ref_partner_2 + + ___ignore___ + + + + BE0202239951 + + partner_1 + + + Chaussée de Namur 40 + Ramillies + 1367 + + BE + + + + BE0202239951 + + VAT + + + + partner_1 + BE0202239951 + + + partner_1 + + + + + + BE0477472701 + + partner_2 + + + Rue des Bourlottes 9 + Ramillies + 1367 + + BE + + + + BE0477472701 + + VAT + + + + partner_2 + BE0477472701 + + + partner_2 + + + + + 30 + ___ignore___ + + BE15001559627230 + + + + 30% Advance End of Following Month + + + 15.75 + + 75.00 + 15.75 + + S + 21.0 + + VAT + + + + + + 75.00 + 75.00 + 90.75 + 0.00 + 90.75 + + + ___ignore___ + 1.0 + 100.00 + + product_a + product_a + + S + 21.0 + + VAT + + + + + 100.0 + + + + ___ignore___ + -1.0 + -25.00 + + product_a + product_a + + S + 21.0 + + VAT + + + + + 25.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 f95dd9cc1a3b1..9f68fee30ce04 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 @@ -504,3 +504,32 @@ def test_import_fixed_taxes(self): list_line_subtotals=[99], currency_id=self.currency_data['currency'].id, list_line_price_unit=[99], list_line_discount=[0], list_line_taxes=[tax_21+self.recupel], move_type='out_invoice', ) + self._assert_imported_invoice_from_file( + subfolder=subfolder, filename='bis3_ecotaxes_case4.xml', amount_total=218.042, amount_tax=39.842, + list_line_subtotals=[178.2], currency_id=self.currency_data['currency'].id, list_line_price_unit=[99], + list_line_discount=[10], list_line_taxes=[tax_21+self.recupel], move_type='out_invoice', + ) + + def test_inverting_negative_price_unit(self): + """ We can not have negative unit prices, so we try to invert the unit price and quantity. + """ + invoice = self._generate_move( + self.partner_1, + self.partner_2, + move_type='out_invoice', + invoice_line_ids=[ + { + 'product_id': self.product_a.id, + 'quantity': 1, + 'price_unit': 100.0, + 'tax_ids': [(6, 0, self.tax_21.ids)], + }, + { + 'product_id': self.product_a.id, + 'quantity': 1, + 'price_unit': -25.0, + 'tax_ids': [(6, 0, self.tax_21.ids)], + } + ], + ) + self._assert_invoice_attachment(invoice, None, 'from_odoo/bis3_out_invoice_negative_unit_price.xml')