[IMP] account_edi_ubl_cii: improve import of XML invoice with errors
Sometimes the user needs to import XML invoices (e.g. factur-x) containing lines with the following problem: The billed quantity of the line is set to 0 but the total of the line (plus/minus allowances) is not 0. The imported version (in odoo) of this line will have quantity 0 and thus a total of 0 (since the total will be computed in odoo and not stored directly in the database). After this commit the quantity of these line will be calculated such that the total computation yields the correct total. To do this an already existing similar "exception" in the parsing logic was extended to deal with this problem. closes odoo/odoo#137833 Signed-off-by: Laurent Smet (las) <las@odoo.com>
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-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:AdditionalDocumentReference>
|
||||
<cbc:ID>___ignore___</cbc:ID>
|
||||
<cbc:Attachment>
|
||||
<cbc:EmbeddedDocumentBinaryObject>___ignore___</cbc:EmbeddedDocumentBinaryObject>
|
||||
</cbc:Attachment>
|
||||
</cac:AdditionalDocumentReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cbc:EndpointID schemeID="0208">0202239951</cbc:EndpointID>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>partner_1</cbc:Name>
|
||||
</cac:PartyName>
|
||||
<cac:PostalAddress>
|
||||
<cbc:StreetName>Chaussé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="0208">0477472701</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:Delivery>
|
||||
<cac:DeliveryLocation>
|
||||
<cac:Address>
|
||||
<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:Address>
|
||||
</cac:DeliveryLocation>
|
||||
</cac:Delivery>
|
||||
<cac:PaymentMeans>
|
||||
<cbc:PaymentMeansCode name="credit transfer">30</cbc:PaymentMeansCode>
|
||||
<cbc:PaymentID>+++000/0000/26268+++</cbc:PaymentID>
|
||||
<cac:PayeeFinancialAccount>
|
||||
<cbc:ID>BE15001559627230</cbc:ID>
|
||||
</cac:PayeeFinancialAccount>
|
||||
</cac:PaymentMeans>
|
||||
<cac:PaymentTerms>
|
||||
<cbc:Note>Payment terms: 30% Advance End of Following Month</cbc:Note>
|
||||
</cac:PaymentTerms>
|
||||
<cac:TaxTotal>
|
||||
<cbc:TaxAmount currencyID="USD">630.00</cbc:TaxAmount>
|
||||
<cac:TaxSubtotal>
|
||||
<cbc:TaxableAmount currencyID="USD">3000.00</cbc:TaxableAmount>
|
||||
<cbc:TaxAmount currencyID="USD">630</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">3000.00</cbc:LineExtensionAmount>
|
||||
<cbc:TaxExclusiveAmount currencyID="USD">3000.00</cbc:TaxExclusiveAmount>
|
||||
<cbc:TaxInclusiveAmount currencyID="USD">3630.00</cbc:TaxInclusiveAmount>
|
||||
<cbc:PrepaidAmount currencyID="USD">0.00</cbc:PrepaidAmount>
|
||||
<cbc:PayableAmount currencyID="USD">3630.00</cbc:PayableAmount>
|
||||
</cac:LegalMonetaryTotal>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>901</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="C62">0</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="USD">1000.00</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>product_b</cbc:Description>
|
||||
<cbc:Name>product_b</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</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>902</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="C62">0</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="USD">1000.00</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>product_b</cbc:Description>
|
||||
<cbc:Name>product_b</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">100.00</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
<cac:InvoiceLine>
|
||||
<cbc:ID>903</cbc:ID>
|
||||
<cbc:InvoicedQuantity unitCode="C62">100</cbc:InvoicedQuantity>
|
||||
<cbc:LineExtensionAmount currencyID="USD">1000.00</cbc:LineExtensionAmount>
|
||||
<cac:Item>
|
||||
<cbc:Description>product_b</cbc:Description>
|
||||
<cbc:Name>product_b</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</cbc:PriceAmount>
|
||||
</cac:Price>
|
||||
</cac:InvoiceLine>
|
||||
</Invoice>
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user