From 86a84afc697dc5abe1512942f11e0a62d99e1127 Mon Sep 17 00:00:00 2001 From: Julien Van Roy Date: Wed, 20 Sep 2023 07:19:10 +0000 Subject: [PATCH] [IMP] account_edi_ubl_cii: handle payment terms Handle payment terms for UBL as described by the Belgian Peppol Authority and documented by VBO-FEB. In case of early payment discount (for instance 2% if payment within 7 days): * add one document level allowance per VAT rate (this allows to reduce the tax base amount to take the discount into account) * add one document level charge exempt from VAT (the amount of this charge is the amount of the discount the customer can get by paying early) * Recompute the document level TaxTotal accordingly Hence, nothing changes for the invoice lines. Importing the xml is then convenient since each document level AllowanceCharge will create an invoice line on top of the existing invoice lines. The total amount of the invoice will be the amount to pay in case of no early payment discount. To get the total amount to pay in case of early payment discount, simply remove the document level charge. References: https://openpeppol.atlassian.net/wiki/spaces/Belgium/overview https://efactuur.belgium.be/sites/default/files/3.%20Cash%20discount.docx opw-3235769 task-3326963 closes odoo/odoo#136635 X-original-commit: 80bb997d7ecab208e6ca9719114cf9ae3c31f505 Signed-off-by: Laurent Smet (las) Signed-off-by: Julien Van Roy (juvr) --- .../data/ubl_20_templates.xml | 3 + .../i18n/account_edi_ubl_cii.pot | 8 + .../models/account_edi_common.py | 5 +- .../models/account_edi_xml_ubl_20.py | 92 +++++++- .../test_files/from_odoo/a_nz_out_invoice.xml | 2 +- .../test_files/from_odoo/a_nz_out_refund.xml | 2 +- .../from_odoo/bis3_ecotaxes_case1.xml | 2 +- .../from_odoo/bis3_ecotaxes_case2.xml | 2 +- .../from_odoo/bis3_ecotaxes_case3.xml | 2 +- .../test_files/from_odoo/bis3_out_invoice.xml | 2 +- .../from_odoo/bis3_out_invoice_no_prices.xml | 2 +- .../bis3_out_invoice_public_admin.xml | 2 +- .../from_odoo/bis3_out_invoice_rounding.xml | 2 +- .../test_files/from_odoo/bis3_out_refund.xml | 2 +- .../test_files/from_odoo/bis3_pay_term.xml | 218 ++++++++++++++++++ .../from_odoo/bis3_pay_term_ecotax.xml | 181 +++++++++++++++ .../from_odoo/nlcius_out_invoice.xml | 2 +- .../from_odoo/nlcius_out_refund.xml | 2 +- .../from_odoo/ubl_test_import_partner.xml | 2 +- .../from_odoo/xrechnung_ubl_out_invoice.xml | 2 +- .../from_odoo/xrechnung_ubl_out_refund.xml | 2 +- .../tests/test_xml_ubl_be.py | 96 ++++++++ .../models/account_edi_xml_oioubl_201.py | 4 +- .../from_odoo/ciusro_out_invoice.xml | 2 +- .../ciusro_out_invoice_different_currency.xml | 2 +- .../from_odoo/ciusro_out_refund.xml | 2 +- 26 files changed, 611 insertions(+), 32 deletions(-) create mode 100644 addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term.xml create mode 100644 addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term_ecotax.xml diff --git a/addons/account_edi_ubl_cii/data/ubl_20_templates.xml b/addons/account_edi_ubl_cii/data/ubl_20_templates.xml index a33aec6c937..c32743de56b 100644 --- a/addons/account_edi_ubl_cii/data/ubl_20_templates.xml +++ b/addons/account_edi_ubl_cii/data/ubl_20_templates.xml @@ -386,6 +386,9 @@ + diff --git a/addons/account_edi_ubl_cii/i18n/account_edi_ubl_cii.pot b/addons/account_edi_ubl_cii/i18n/account_edi_ubl_cii.pot index 6d9c1565513..89604145bf6 100644 --- a/addons/account_edi_ubl_cii/i18n/account_edi_ubl_cii.pot +++ b/addons/account_edi_ubl_cii/i18n/account_edi_ubl_cii.pot @@ -528,6 +528,14 @@ msgstr "" msgid "Contact" msgstr "" +#. module: account_edi_ubl_cii +#. odoo-python +#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0 +#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0 +#, python-format +msgid "Conditional cash/payment discount" +msgstr "" + #. module: account_edi_ubl_cii #. odoo-python #: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0 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 e0bbb9d895b..790e51bceb6 100644 --- a/addons/account_edi_ubl_cii/models/account_edi_common.py +++ b/addons/account_edi_ubl_cii/models/account_edi_common.py @@ -390,12 +390,9 @@ class AccountEdiCommon(models.AbstractModel): # get the name name = "" - reason_code_node = allow_el.find('./{*}AllowanceChargeReasonCode' if is_ubl else './{*}ReasonCode') - if reason_code_node is not None: - name += reason_code_node.text + " " reason_node = allow_el.find('./{*}AllowanceChargeReason' if is_ubl else './{*}Reason') if reason_node is not None: - name += reason_node.text + name = reason_node.text # get quantity and price unit quantity = 1 diff --git a/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py b/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py index c64ad57265f..e8ebfed1a2d 100644 --- a/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py +++ b/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from collections import defaultdict from lxml import etree from odoo import models, _ @@ -162,7 +163,8 @@ class AccountEdiXmlUBL20(models.AbstractModel): def _get_invoice_payment_terms_vals_list(self, invoice): payment_term = invoice.invoice_payment_term_id if payment_term: - return [{'note_vals': [payment_term.name]}] + # The payment term's note is automatically embedded in a

tag in Odoo + return [{'note_vals': [html2plaintext(payment_term.note)]}] else: return [] @@ -173,16 +175,30 @@ class AccountEdiXmlUBL20(models.AbstractModel): 'tax_amount': taxes_vals['tax_amount_currency'], 'tax_subtotal_vals': [], } + epd_tax_to_discount = self._get_early_payment_discount_grouped_by_tax_rate(invoice) for grouping_key, vals in taxes_vals['tax_details'].items(): if grouping_key['tax_amount_type'] != 'fixed': - tax_totals_vals['tax_subtotal_vals'].append({ + subtotal = { 'currency': invoice.currency_id, 'currency_dp': self._get_currency_decimal_places(invoice.currency_id), 'taxable_amount': vals['base_amount_currency'], 'tax_amount': vals['tax_amount_currency'], 'percent': vals['_tax_category_vals_']['percent'], 'tax_category_vals': vals['_tax_category_vals_'], - }) + } + if epd_tax_to_discount: + # early payment discounts: need to recompute the tax/taxable amounts + taxable_amount_after_epd = subtotal['taxable_amount'] - epd_tax_to_discount.get(subtotal['percent'], 0) + tax_amount_after_epd = taxable_amount_after_epd * subtotal['tax_category_vals']['percent'] / 100 + subtotal.update({ + 'taxable_amount': taxable_amount_after_epd, + 'tax_amount': tax_amount_after_epd, + }) + tax_totals_vals['tax_subtotal_vals'].append(subtotal) + + if epd_tax_to_discount: + # early payment discounts: hence, need to recompute the total tax amount + tax_totals_vals['tax_amount'] = sum([subtot['tax_amount'] for subtot in tax_totals_vals['tax_subtotal_vals']]) return [tax_totals_vals] def _get_invoice_line_item_vals(self, line, taxes_vals): @@ -216,8 +232,45 @@ class AccountEdiXmlUBL20(models.AbstractModel): def _get_document_allowance_charge_vals_list(self, invoice): """ https://docs.peppol.eu/poacc/billing/3.0/bis/#_document_level_allowance_or_charge + Usage for early payment discounts: + * Add one document level Allowance per tax rate (VAT included) + * Add one document level Charge (VAT excluded) with amount = the total sum of the early payment discount + The difference between these is the cash discount in case of early payment. """ - return [] + vals_list = [] + # Early Payment Discount + epd_tax_to_discount = self._get_early_payment_discount_grouped_by_tax_rate(invoice) + if epd_tax_to_discount: + # One Allowance per tax rate (VAT included) + for tax_amount, discount_amount in epd_tax_to_discount.items(): + vals_list.append({ + 'charge_indicator': 'false', + 'allowance_charge_reason_code': '66', + 'allowance_charge_reason': _("Conditional cash/payment discount"), + 'amount': discount_amount, + 'currency_dp': 2, + 'currency_name': invoice.currency_id.name, + 'tax_category_vals': [{ + 'id': 'S', + 'percent': tax_amount, + 'tax_scheme_id': 'VAT', + }], + }) + # One global Charge (VAT exempted) + vals_list.append({ + 'charge_indicator': 'true', + 'allowance_charge_reason_code': 'ZZZ', + 'allowance_charge_reason': _("Conditional cash/payment discount"), + 'amount': sum(epd_tax_to_discount.values()), + 'currency_dp': 2, + 'currency_name': invoice.currency_id.name, + 'tax_category_vals': [{ + 'id': 'E', + 'percent': 0.0, + 'tax_scheme_id': 'VAT', + }], + }) + return vals_list def _get_invoice_line_allowance_vals_list(self, line, tax_values_list=None): """ Method used to fill the cac:InvoiceLine>cac:AllowanceCharge node. @@ -332,7 +385,7 @@ class AccountEdiXmlUBL20(models.AbstractModel): 'price_vals': self._get_invoice_line_price_vals(line), } - def _get_invoice_legal_monetary_total_vals(self, invoice, taxes_vals, line_extension_amount, allowance_total_amount): + def _get_invoice_legal_monetary_total_vals(self, invoice, taxes_vals, line_extension_amount, allowance_total_amount, charge_total_amount): """ Method used to fill the cac:LegalMonetaryTotal node""" return { 'currency': invoice.currency_id, @@ -341,6 +394,7 @@ class AccountEdiXmlUBL20(models.AbstractModel): 'tax_exclusive_amount': taxes_vals['base_amount_currency'], 'tax_inclusive_amount': invoice.amount_total, 'allowance_total_amount': allowance_total_amount or None, + 'charge_total_amount': charge_total_amount or None, 'prepaid_amount': invoice.amount_total - invoice.amount_residual, 'payable_amount': invoice.amount_residual, } @@ -357,6 +411,19 @@ class AccountEdiXmlUBL20(models.AbstractModel): """ return True + def _get_early_payment_discount_grouped_by_tax_rate(self, invoice): + """ + Get the early payment discounts grouped by the tax rate of the product it is linked to + :returns {float: float}: mapping tax amounts to early payment discount amounts + """ + if invoice.invoice_payment_term_id.early_pay_discount_computation != 'mixed': + return {} + tax_to_discount = defaultdict(lambda: 0) + for line in invoice.line_ids.filtered(lambda l: l.display_type == 'epd'): + for tax in line.tax_ids: + tax_to_discount[tax.amount] += line.amount_currency + return tax_to_discount + def _export_invoice_vals(self, invoice): def grouping_key_generator(base_line, tax_values): tax = tax_values['tax_repartition_line'].tax_id @@ -410,9 +477,12 @@ class AccountEdiXmlUBL20(models.AbstractModel): # Compute the total allowance/charge amounts. allowance_total_amount = 0.0 + charge_total_amount = 0.0 for allowance_charge_vals in document_allowance_charge_vals_list: if allowance_charge_vals['charge_indicator'] == 'false': allowance_total_amount += allowance_charge_vals['amount'] + else: + charge_total_amount += allowance_charge_vals['amount'] supplier = invoice.company_id.partner_id.commercial_partner_id customer = invoice.commercial_partner_id @@ -463,7 +533,13 @@ class AccountEdiXmlUBL20(models.AbstractModel): # allowances at the document level, the allowances on invoices (eg. discount) are on invoice_line_vals 'allowance_charge_vals': document_allowance_charge_vals_list, 'tax_total_vals': self._get_invoice_tax_totals_vals_list(invoice, taxes_vals), - 'legal_monetary_total_vals': self._get_invoice_legal_monetary_total_vals(invoice, taxes_vals, line_extension_amount, allowance_total_amount), + 'legal_monetary_total_vals': self._get_invoice_legal_monetary_total_vals( + invoice, + taxes_vals, + line_extension_amount, + allowance_total_amount, + charge_total_amount, + ), 'invoice_line_vals': invoice_line_vals_list, 'currency_dp': self._get_currency_decimal_places(invoice.currency_id), # currency decimal places }, @@ -577,11 +653,11 @@ class AccountEdiXmlUBL20(models.AbstractModel): narration = "" note_node = tree.find('./{*}Note') if note_node is not None and note_node.text: - narration += note_node.text + "\n" + narration += f"

{note_node.text}

" payment_terms_node = tree.find('./{*}PaymentTerms/{*}Note') # e.g. 'Payment within 10 days, 2% discount' if payment_terms_node is not None and payment_terms_node.text: - narration += payment_terms_node.text + "\n" + narration += f"

{payment_terms_node.text}

" invoice.narration = narration diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_invoice.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_invoice.xml index 3edfd6169e4..db44391df6c 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_invoice.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_invoice.xml @@ -99,7 +99,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 268.20 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_refund.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_refund.xml index aed038d9f57..f3b949ac14c 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_refund.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/a_nz_out_refund.xml @@ -98,7 +98,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 268.20 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case1.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case1.xml index 6cb354d9acb..6c5cacfe333 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case1.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case1.xml @@ -100,7 +100,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 21.00 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case2.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case2.xml index b770a516eb4..9e18bb96942 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case2.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case2.xml @@ -100,7 +100,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 21.00 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case3.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case3.xml index 23d394c80d7..46af1311019 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case3.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_ecotaxes_case3.xml @@ -100,7 +100,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 21.00 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice.xml index a02b9736170..a63eea5b083 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice.xml @@ -97,7 +97,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 482.22 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_no_prices.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_no_prices.xml index 6936362d26e..b1086f5c5cb 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_no_prices.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_no_prices.xml @@ -78,7 +78,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 482.22 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_public_admin.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_public_admin.xml index 62529e68b37..6c3ac92d8a2 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_public_admin.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_public_admin.xml @@ -91,7 +91,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 42.00 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_rounding.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_rounding.xml index 5584698d1f7..51bf3db15ec 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_rounding.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_invoice_rounding.xml @@ -102,7 +102,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 959.07 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_refund.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_refund.xml index dd55c43ebee..7eff2616951 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_refund.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_out_refund.xml @@ -96,7 +96,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 482.22 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term.xml new file mode 100644 index 00000000000..a95895663a0 --- /dev/null +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term.xml @@ -0,0 +1,218 @@ + + + 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-01-31 + 380 + test narration + USD + ref_partner_2 + + ref_move + + + ___ignore___ + 380 + + + ___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 + ___ignore___ + + BE15001559627230 + + + + Payment terms: 30 Days, 2% Early Payment Discount under 7 days + + + false + 66 + Conditional cash/payment discount + 4.00 + + S + 6.0 + + VAT + + + + + false + 66 + Conditional cash/payment discount + 48.00 + + S + 21.0 + + VAT + + + + + true + ZZZ + Conditional cash/payment discount + 52.00 + + E + 0.0 + + VAT + + + + + 505.68 + + 196.00 + 11.76 + + S + 6.0 + + VAT + + + + + 2352.00 + 493.92 + + S + 21.0 + + VAT + + + + + + 2600.00 + 2600.00 + 3105.68 + 52.00 + 52.00 + 0.00 + 3105.68 + + + ___ignore___ + 1.0 + 200.00 + + product_a + product_a + + S + 6.0 + + VAT + + + + + 200.00 + + + + ___ignore___ + 1.0 + 2400.00 + + product_b + product_b + + S + 21.0 + + VAT + + + + + 2400.00 + + + diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term_ecotax.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term_ecotax.xml new file mode 100644 index 00000000000..638bedf87ba --- /dev/null +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/bis3_pay_term_ecotax.xml @@ -0,0 +1,181 @@ + + + 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-01-31 + 380 + test narration + USD + ref_partner_2 + + ref_move + + + ___ignore___ + 380 + + + ___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 + ___ignore___ + + BE15001559627230 + + + + Payment terms: 30 Days, 2% Early Payment Discount under 7 days + + + false + 66 + Conditional cash/payment discount + 1.98 + + S + 21.0 + + VAT + + + + + true + ZZZ + Conditional cash/payment discount + 1.98 + + E + 0.0 + + VAT + + + + + 20.58 + + 98.02 + 20.58 + + S + 21.0 + + VAT + + + + + + 100.00 + 100.00 + 120.58 + 1.98 + 1.98 + 0.00 + 120.58 + + + ___ignore___ + 1.0 + 100.00 + + true + AEO + RECUPEL + 1.00 + + + product_a + product_a + + S + 21.0 + + VAT + + + + + 99.00 + + + diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_invoice.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_invoice.xml index 8fe985296db..1fbb5a4ec10 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_invoice.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_invoice.xml @@ -105,7 +105,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 401.58 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_refund.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_refund.xml index e15e3f4a116..0d56dba317b 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_refund.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/nlcius_out_refund.xml @@ -109,7 +109,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 401.58 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/ubl_test_import_partner.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/ubl_test_import_partner.xml index 1397395e481..db8e4e50dd9 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/ubl_test_import_partner.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/ubl_test_import_partner.xml @@ -75,7 +75,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month -0.00 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_invoice.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_invoice.xml index 93fe86989ac..8bec813aece 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_invoice.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_invoice.xml @@ -99,7 +99,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 401.58 diff --git a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_refund.xml b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_refund.xml index c3ba801b3ed..e439850bcd5 100644 --- a/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_refund.xml +++ b/addons/l10n_account_edi_ubl_cii_tests/tests/test_files/from_odoo/xrechnung_ubl_out_refund.xml @@ -98,7 +98,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 401.58 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 bf66d37ff82..7f83e6a9ef6 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 @@ -69,8 +69,26 @@ class TestUBLBE(TestUBLCommon, TestAccountMoveSendCommon): 'country_id': cls.env.ref('base.be').id, }) + cls.tax_6 = cls.env['account.tax'].create({ + 'name': 'tax_6', + 'amount_type': 'percent', + 'amount': 6, + 'type_tax_use': 'sale', + 'country_id': cls.env.ref('base.be').id, + }) + cls.env.company.invoice_is_ubl_cii = True + cls.pay_term = cls.env['account.payment.term'].create({ + 'name': "2/7 Net 30", + 'note': "Payment terms: 30 Days, 2% Early Payment Discount under 7 days", + 'early_discount': True, + 'discount_percentage': 2, + 'discount_days': 7, + 'line_ids': [ + Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 30})], + }) + @classmethod def setup_company_data(cls, company_name, chart_template): # OVERRIDE @@ -341,6 +359,72 @@ class TestUBLBE(TestUBLCommon, TestAccountMoveSendCommon): self.assertEqual(invoice.amount_total, 121) self._assert_invoice_attachment(invoice.ubl_cii_xml_id, None, 'from_odoo/bis3_ecotaxes_case3.xml') + def test_export_payment_terms(self): + """ + Tests the early payment discount using the example case from the VBO/FEB. + + ------------- + Price + Tax + Cash Discount (2%) + Taxable Amount + VAT -- + Product A | 200 | 6% | -4 | 196 | 11.76 + Product B | 2400 | 21% | -48 | 2352 | 493.92 + --------------+-------+-----+--------------------+----------------+------- + + Subtotal (Taxable amount incl. payment discount): 2548 + VAT: 505.68 + Payable amount (excl. payment discount): 3105.68 + Payable amount (incl. payment discount): 3053.68 + """ + invoice = self._generate_move( + self.partner_1, + self.partner_2, + move_type='out_invoice', + invoice_payment_term_id=self.pay_term.id, + invoice_line_ids=[ + { + 'product_id': self.product_a.id, + 'quantity': 1, + 'price_unit': 200, + 'tax_ids': [(6, 0, [self.tax_6.id])], + }, + { + 'product_id': self.product_b.id, + 'quantity': 1, + 'price_unit': 2400, + 'tax_ids': [(6, 0, [self.tax_21.id])], + } + ], + ) + self._assert_invoice_attachment(invoice.ubl_cii_xml_id, None, 'from_odoo/bis3_pay_term.xml') + + def test_export_payment_terms_fixed_tax(self): + """ + Tests the early payment discount combined with a fixed tax. + + ------------- + Price + Tax + Cash Discount (2%) + ------- Taxable Amount + VAT ---- + Product A | 99 | 21% | -1.98 | 97.02 + 1 (fixed tax) | 20.5842 + --------------+-------+-----+--------------------+------------------------+--------- + NB: The fixed taxes (recupel, auvibel, etc) are excluded from the early payment discount ! + + Subtotal (Taxable amount incl. payment discount): 97.02 + 1 + VAT: (97.02 + 1) * 0.21 = 20.58 + Payable amount (excl. payment discount): 99 + 1 + 20.58 = 120.58 + Payable amount (incl. payment discount): 97.02 + 1 + 20.58 = 118.60 + """ + invoice = self._generate_move( + self.partner_1, + self.partner_2, + move_type='out_invoice', + invoice_payment_term_id=self.pay_term.id, + invoice_line_ids=[ + { + 'product_id': self.product_a.id, + 'quantity': 1, + 'price_unit': 99, + 'tax_ids': [(6, 0, [self.tax_21.id, self.recupel.id])], + }, + ], + ) + self._assert_invoice_attachment(invoice.ubl_cii_xml_id, None, 'from_odoo/bis3_pay_term_ecotax.xml') + #################################################### # Test import #################################################### @@ -511,6 +595,18 @@ class TestUBLBE(TestUBLCommon, TestAccountMoveSendCommon): list_line_discount=[0], list_line_taxes=[tax_21+self.recupel], move_type='out_invoice', ) + def test_import_payment_terms(self): + # 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') + tax_0 = self.env.ref(f'account.{self.env.company.id}_attn_VAT-OUT-00-L') + self._assert_imported_invoice_from_file( + subfolder='tests/test_files/from_odoo', filename='bis3_pay_term.xml', amount_total=3105.68, + amount_tax=505.68, list_line_subtotals=[-4, -48, 52, 200, 2400], + currency_id=self.currency_data['currency'].id, list_line_price_unit=[-4, -48, 52, 200, 2400], + list_line_discount=[0, 0, 0, 0, 0], list_line_taxes=[self.tax_6, tax_21, tax_0, self.tax_6, tax_21], + move_type='out_invoice', + ) + #################################################### # Test Send & print #################################################### diff --git a/addons/l10n_dk_oioubl/models/account_edi_xml_oioubl_201.py b/addons/l10n_dk_oioubl/models/account_edi_xml_oioubl_201.py index 9ab2f33072f..6d10336e928 100644 --- a/addons/l10n_dk_oioubl/models/account_edi_xml_oioubl_201.py +++ b/addons/l10n_dk_oioubl/models/account_edi_xml_oioubl_201.py @@ -199,9 +199,9 @@ class AccountEdiXmlOIOUBL201(models.AbstractModel): return vals_list - def _get_invoice_legal_monetary_total_vals(self, invoice, taxes_vals, line_extension_amount, allowance_total_amount): + def _get_invoice_legal_monetary_total_vals(self, invoice, taxes_vals, line_extension_amount, allowance_total_amount, charge_total_amount): # EXTENDS account.edi.xml.ubl_20 - vals = super()._get_invoice_legal_monetary_total_vals(invoice, taxes_vals, line_extension_amount, allowance_total_amount) + vals = super()._get_invoice_legal_monetary_total_vals(invoice, taxes_vals, line_extension_amount, allowance_total_amount, charge_total_amount) # In OIOUBL context, tax_exclusive_amount means "tax only" vals['tax_exclusive_amount'] = taxes_vals['tax_amount_currency'] if invoice.currency_id.is_zero(vals['prepaid_amount']): diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml index 5abd2c5f1f6..b58ff2130ee 100644 --- a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml +++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml @@ -103,7 +103,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 285.00 diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml index bf541a8c1c9..87e8961e6ac 100644 --- a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml +++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml @@ -103,7 +103,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 285.00 diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml index a23ea4deb81..3bbe12d8e3a 100644 --- a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml +++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml @@ -102,7 +102,7 @@ - 30% Advance End of Following Month + Payment terms: 30% Advance End of Following Month 285.00