From a2b41824df0b792d6f80b9a6461dfae0e7a68d09 Mon Sep 17 00:00:00 2001 From: Mohit Beniwal Date: Thu, 20 Jul 2023 08:57:03 +0000 Subject: [PATCH] [FIX] l10n_es_edi_facturae: handle ZeroDivisionError when discount value is 100 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This traceback raises when user tries to 'Send & Print' the invoice of sale order having a discount of 100%. Steps to reproduce: 1) Install "l10n_es_edi_facturae" & "sale_management" and switch to "ES Company". 2) Open "Sales" > "Configuration" > "Settings" and click on "Discounts" checkbox > "Save" button to activate it. 3) Now click on "Orders" > "Quotations" button and then "New" button . 4) Select any "Customer" and in "Order Lines" select a "product" with "Invoicing Policy" as 'Ordered quantities' (ex. 'Chair floor protection'). 5) Now, in that 'Sale order line' enter the value of 'Disc.%' as '100' . 6) Click on "Confirm" button and then "Create Invoice" button. 7) In "Create Invoice" Wizard, select "Regular Invoice" if not > "Create Draft Invoice" button. 8) In "Customer Invoice", click on "Confirm" button > "Send & Print" button. 9) In "Configure your document layout" wizard, click on "Save" > "Send & Print". Error: ZeroDivisionError: float division by zero, is generated from "_l10n_es_edi_facturae_inv_lines_to_items" method. See: https://github.com/odoo/odoo/blob/b5c19d368339f9d2b7af6e61e88a918d6ba318ee/addons/l10n_es_edi_facturae/models/account_move.py#L195 It gets the value of "line.discount" as 100, so the overall value of "(1 - line.discount / 100.0)" becomes Zero and it tries to divide "line.price_subtotal" by 'Zero', that's why this error is coming. sentry-4325625223 closes odoo/odoo#131029 X-original-commit: 363e679601920f1a5a1fd6e1021521dae2a76714 Signed-off-by: de Wouters de Bouchout Jean-BenoƮt (jbw) Signed-off-by: Mohit Beniwal (mobe) --- .../l10n_es_edi_facturae/models/account_move.py | 12 ++++++++++-- .../l10n_es_edi_facturae/tests/test_edi_xml.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/addons/l10n_es_edi_facturae/models/account_move.py b/addons/l10n_es_edi_facturae/models/account_move.py index 82cc8cea038..2fc9c206bfb 100644 --- a/addons/l10n_es_edi_facturae/models/account_move.py +++ b/addons/l10n_es_edi_facturae/models/account_move.py @@ -192,10 +192,18 @@ class AccountMove(models.Model): continue invoice_line_values = {} - price_before_discount = line.currency_id.round(line.price_subtotal / (1 - line.discount / 100.0)) + tax_base_before_discount = self.env['account.tax']._convert_to_tax_base_line_dict( + base_line=line, + currency=line.currency_id, + taxes=line.tax_ids, + price_unit=line.price_unit, + quantity=line.quantity, + ) + tax_before_discount = self.env['account.tax']._compute_taxes([tax_base_before_discount]) + price_before_discount = sum(to_update['price_subtotal'] for _dummy, to_update in tax_before_discount['base_lines_to_update']) discount = max(0., (price_before_discount - line.price_subtotal)) surcharge = abs(min(0., (price_before_discount - line.price_subtotal))) - totals['total_gross_amount'] += line.price_subtotal + totals['total_gross_amount'] += price_before_discount totals['total_general_discounts'] += discount totals['total_general_surcharges'] += surcharge base_line = self.env['account.tax']._convert_to_tax_base_line_dict( diff --git a/addons/l10n_es_edi_facturae/tests/test_edi_xml.py b/addons/l10n_es_edi_facturae/tests/test_edi_xml.py index f79f7bff684..3f8dc943f81 100644 --- a/addons/l10n_es_edi_facturae/tests/test_edi_xml.py +++ b/addons/l10n_es_edi_facturae/tests/test_edi_xml.py @@ -234,3 +234,20 @@ class TestEdiFacturaeXmls(AccountEdiTestCommon): with file_open("l10n_es_edi_facturae/tests/data/expected_refund_document.xml", "rt") as f: expected_xml = lxml.etree.fromstring(f.read().encode()) self.assertXmlTreeEqual(lxml.etree.fromstring(generated_file), expected_xml) + + def test_discount_100_percent(self): + """ Create an invoice with a 100% discount """ + with freeze_time(self.frozen_today), \ + patch(f"{self.certificate_module}.fields.datetime.now", lambda x=None: self.frozen_today), \ + patch(f"{self.certificate_module}.sha1", lambda x: sha1()): + invoice = self.create_invoice( + partner_id=self.partner_a.id, + move_type='out_invoice', + invoice_line_ids=[{'product_id': self.product_a.id, 'price_unit': 1000.0, 'discount': 100.0, 'quantity': 2}], + ) + invoice.action_post() + wizard = self.create_send_and_print(invoice) + result = wizard.action_send_and_print() + + self.assertEqual(result['type'], 'ir.actions.act_url') + self.assertEqual(invoice.invoice_line_ids[0].price_subtotal, 0.0)