Skip to content
Snippets Groups Projects
Commit d7d41991 authored by Julien Van Roy's avatar Julien Van Roy
Browse files

[FIX] account_edi_ubl_cii: unit prices should not be rounded

When unit prices have more than 2 digits, it is currently not reflected
in the UBL formats. Consequently, the line amounts are not equal to the
unit price * quantity (assume there is no discount, charges or
allowance) and it raises validation errors: "Invoice line net amount
MUST equal (Invoiced quantity * (Item net price/item price base
quantity) + Sum of invoice line charge amount - sum of invoice line
allowance amount".

To fix this, we no longer round the unit prices.

NB: the decimal accuracy should be set in the settings (otherwise, the
default is 2 digits for unit prices).

See https://docs.peppol.eu/poacc/billing/3.0/bis/#_rounding



opw-3290035
task-3302904

closes odoo/odoo#120821

Signed-off-by: default avatarLaurent Smet <las@odoo.com>
parent 8b522e5c
No related branches found
No related tags found
No related merge requests found
......@@ -248,7 +248,7 @@
<t t-set="vals" t-value="vals.get('price_vals', {})"/>
<cbc:PriceAmount
t-att-currencyID="vals['currency'].name"
t-esc="format_float(vals.get('price_amount'), vals.get('currency_dp'))"/>
t-esc="format_float(vals.get('price_amount'), vals.get('product_price_dp'))"/>
<!-- nbr of item units to which the price applies), i.e.: 1 Dozen = 12 units, not mandatory -->
<cbc:BaseQuantity
t-att="vals.get('base_quantity_attrs', {})"
......
......@@ -291,7 +291,7 @@ class AccountEdiXmlUBL20(models.AbstractModel):
else:
gross_price_subtotal = net_price_subtotal / (1.0 - (line.discount or 0.0) / 100.0)
# Price subtotal with discount / quantity:
gross_price_unit = line.currency_id.round((gross_price_subtotal / line.quantity) if line.quantity else 0.0)
gross_price_unit = gross_price_subtotal / line.quantity if line.quantity else 0.0
uom = super()._get_uom_unece_code(line)
......@@ -301,6 +301,7 @@ class AccountEdiXmlUBL20(models.AbstractModel):
# The price of an item, exclusive of VAT, after subtracting item price discount.
'price_amount': gross_price_unit,
'product_price_dp': self.env['decimal.precision'].precision_get('Product Price'),
# The number of item units to which the price applies.
# setting to None -> the xml will not comprise the BaseQuantity (it's not mandatory)
......
<?xml version='1.0' encoding='UTF-8'?>
<Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>INV/2017/01/0002</cbc:ID>
<cbc:IssueDate>2017-01-01</cbc:IssueDate>
<cbc:DueDate>2017-02-28</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:Note>test narration</cbc:Note>
<cbc:DocumentCurrencyCode>USD</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>ref_partner_2</cbc:BuyerReference>
<cac:OrderReference>
<cbc:ID>___ignore___</cbc:ID>
</cac:OrderReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="9925">BE0202239951</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>partner_1</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Chauss&#233;e de Namur 40</cbc:StreetName>
<cbc:CityName>Ramillies</cbc:CityName>
<cbc:PostalZone>1367</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>BE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>BE0202239951</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>partner_1</cbc:RegistrationName>
<cbc:CompanyID>BE0202239951</cbc:CompanyID>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>partner_1</cbc:Name>
</cac:Contact>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="9925">BE0477472701</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>partner_2</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Rue des Bourlottes 9</cbc:StreetName>
<cbc:CityName>Ramillies</cbc:CityName>
<cbc:PostalZone>1367</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>BE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>BE0477472701</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>partner_2</cbc:RegistrationName>
<cbc:CompanyID>BE0477472701</cbc:CompanyID>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>partner_2</cbc:Name>
</cac:Contact>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PaymentMeans>
<cbc:PaymentMeansCode name="credit transfer">30</cbc:PaymentMeansCode>
<cbc:PaymentID>___ignore___</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>BE15001559627230</cbc:ID>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>30% Advance End of Following Month</cbc:Note>
</cac:PaymentTerms>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="USD">959.07</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="USD">4567.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="USD">959.07</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>21.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="USD">4567.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="USD">4567.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="USD">5526.07</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount currencyID="USD">0.00</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="USD">5526.07</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>___ignore___</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">10000.0</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="USD">4567.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>product_a</cbc:Description>
<cbc:Name>product_a</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>21.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="USD">0.4567</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
......@@ -249,6 +249,33 @@ class TestUBLBE(TestUBLCommon):
expected_file='from_odoo/bis3_out_invoice_public_admin.xml',
)
def test_rounding_price_unit(self):
""" OpenPeppol states that:
* All document level amounts shall be rounded to two decimals for accounting
* Invoice line net amount shall be rounded to two decimals
See: https://docs.peppol.eu/poacc/billing/3.0/bis/#_rounding
Do not round the unit prices. It allows to obtain the correct line amounts when prices have more than 2
digits.
"""
# Set the allowed number of digits for the price_unit
decimal_precision = self.env['decimal.precision'].search([('name', '=', 'Product Price')], limit=1)
self.assertTrue(bool(decimal_precision), "The decimal precision for Product Price is required for this test")
decimal_precision.digits = 4
invoice = self._generate_move(
self.partner_1,
self.partner_2,
move_type='out_invoice',
invoice_line_ids=[
{
'product_id': self.product_a.id,
'quantity': 10000,
'price_unit': 0.4567,
'tax_ids': [(6, 0, self.tax_21.ids)],
}
],
)
self._assert_invoice_attachment(invoice, xpaths=None, expected_file='from_odoo/bis3_out_invoice_rounding.xml')
####################################################
# Test import
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment