[FIX] account_edi_ubl_cii: import customer when uploading an invoice

Previously, it was only possible to upload a bill, so the partner_id was read
from the vendor in the imported file. Now, it is also possible to upload a
file to create an invoice, so we need to be able to decode the customer in
the imported file.

opw-3072989

closes odoo/odoo#106942

X-original-commit: c52cde5405dcc5f3e48fea9b380a93d4a56467b5
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Julien Van Roy <juvr@odoo.com>
This commit is contained in:
Julien Van Roy
2022-12-15 13:40:43 +01:00
parent 9c5d7adf3d
commit 96be0eda68
6 changed files with 76 additions and 23 deletions
@@ -82,27 +82,23 @@ msgid ""
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_common.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0
#, python-format
msgid "Could not retrieve the %s."
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_common.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_common.py:0
#, python-format
msgid "Could not retrieve the tax: %s %% for line '%s'."
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_common.py:0
#, python-format
msgid ""
"Could not retrieve the unit of measure for line with label '%s'. Did you "
"install the inventory app and enabled the 'Units of Measure' option ?"
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0
#, python-format
msgid "Could not retrieve the vendor."
msgid "Could not retrieve the unit of measure for line with label '%s'."
msgstr ""
#. module: account_edi_ubl_cii
@@ -380,6 +376,13 @@ msgid ""
" code (BT-151)."
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0
#, python-format
msgid "customer"
msgstr ""
#. module: account_edi_ubl_cii
#: model_terms:ir.ui.view,arch_db:account_edi_ubl_cii.account_invoice_pdfa_3_facturx_metadata
msgid "external"
@@ -409,3 +412,10 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:account_edi_ubl_cii.account_invoice_pdfa_3_facturx_metadata
msgid "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"
msgstr ""
#. module: account_edi_ubl_cii
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_cii_facturx.py:0
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py:0
#, python-format
msgid "vendor"
msgstr ""
@@ -216,14 +216,14 @@ class AccountEdiXmlCII(models.AbstractModel):
# ==== partner_id ====
partner_type = invoice.journal_id.type == journal.type and 'SellerTradeParty' or 'BuyerTradeParty'
partner_type = invoice.journal_id.type == 'purchase' and 'SellerTradeParty' or 'BuyerTradeParty'
invoice.partner_id = self.env['account.edi.format']._retrieve_partner(
name=_find_value(f"//ram:{partner_type}/ram:Name"),
mail=_find_value(f"//ram:{partner_type}//ram:URIID[@schemeID='SMTP']"),
vat=_find_value(f"//ram:{partner_type}/ram:SpecifiedTaxRegistration/ram:ID"),
)
if not invoice.partner_id:
logs.append(_("Could not retrieve the vendor."))
logs.append(_("Could not retrieve the %s.", _("customer") if invoice.is_sale_document() else _("vendor")))
# ==== currency_id ====
@@ -465,12 +465,12 @@ class AccountEdiXmlUBL20(models.AbstractModel):
partner = self._import_retrieve_info_from_map(
tree,
self._import_retrieve_partner_map(journal),
self._import_retrieve_partner_map(self.env.company, journal.type),
)
if partner:
invoice.partner_id = partner
else:
logs.append(_("Could not retrieve the vendor."))
logs.append(_("Could not retrieve the %s.", _("customer") if invoice.is_sale_document() else _("vendor")))
# ==== currency_id ====
@@ -615,23 +615,24 @@ class AccountEdiXmlUBL20(models.AbstractModel):
return 'refund', 1
return None, None
def _import_retrieve_partner_map(self, company):
def _import_retrieve_partner_map(self, company, move_type='purchase'):
role = "Customer" if move_type == 'sale' else "Supplier"
def with_vat(tree, extra_domain):
vat_node = tree.find('.//{*}AccountingSupplierParty/{*}Party//{*}CompanyID')
vat_node = tree.find(f'.//{{*}}Accounting{role}Party/{{*}}Party//{{*}}CompanyID')
vat = None if vat_node is None else vat_node.text
return self.env['account.edi.format']._retrieve_partner_with_vat(vat, extra_domain)
def with_phone_mail(tree, extra_domain):
phone_node = tree.find('.//{*}AccountingSupplierParty/{*}Party//{*}Telephone')
mail_node = tree.find('.//{*}AccountingSupplierParty/{*}Party//{*}ElectronicMail')
phone_node = tree.find(f'.//{{*}}Accounting{role}Party/{{*}}Party//{{*}}Telephone')
mail_node = tree.find(f'.//{{*}}Accounting{role}Party/{{*}}Party//{{*}}ElectronicMail')
phone = None if phone_node is None else phone_node.text
mail = None if mail_node is None else mail_node.text
return self.env['account.edi.format']._retrieve_partner_with_phone_mail(phone, mail, extra_domain)
def with_name(tree, extra_domain):
name_node = tree.find('.//{*}AccountingSupplierParty/{*}Party//{*}Name')
name_node = tree.find(f'.//{{*}}Accounting{role}Party/{{*}}Party//{{*}}Name')
name = None if name_node is None else name_node.text
return self.env['account.edi.format']._retrieve_partner_with_name(name, extra_domain)
@@ -44,7 +44,7 @@ class TestUBLCommon(AccountEdiTestCommon):
def assert_same_invoice(self, invoice1, invoice2, **invoice_kwargs):
self.assertEqual(len(invoice1.invoice_line_ids), len(invoice2.invoice_line_ids))
self.assertRecordValues(invoice2, [{
'partner_id': invoice1.company_id.partner_id.id,
'partner_id': invoice1.partner_id.id,
'invoice_date': fields.Date.from_string(invoice1.date),
'currency_id': invoice1.currency_id.id,
'amount_untaxed': invoice1.amount_untaxed,
@@ -74,6 +74,7 @@ class TestUBLCommon(AccountEdiTestCommon):
Create an account.move directly from an xml file, asserts the invoice obtained is the same as the expected
invoice.
"""
# /!\ use the same journal as the invoice's one to import the attachment !
invoice.journal_id.create_document_from_attachment(attachment.ids)
new_invoice = self.env['account.move'].search([], order='id desc', limit=1)
@@ -194,6 +195,41 @@ class TestUBLCommon(AccountEdiTestCommon):
return attachment
def _test_import_partner(self, edi_code, filename):
"""
Given an invoice where partner_1 is the vendor and partner_2 is the customer with an EDI attachment.
* Uploading the attachment as an invoice should create an invoice with the buyer = partner_2.
* Uploading the attachment as a vendor bill should create a bill with the vendor = partner_1.
"""
invoice = self._generate_move(
seller=self.partner_1,
buyer=self.partner_2,
move_type='out_invoice',
invoice_line_ids=[{'product_id': self.product_a.id}],
)
edi_attachment = invoice.edi_document_ids.filtered(
lambda doc: doc.edi_format_id.code == edi_code).attachment_id
self.assertEqual(edi_attachment.name, filename)
edi_etree = self.get_xml_tree_from_string(edi_attachment.raw)
# Import attachment as an invoice
new_invoice = self.edi_format._create_invoice_from_xml_tree(
filename='test_filename',
tree=edi_etree,
journal=self.env['account.journal'].search(
[('type', '=', 'sale'), ('company_id', '=', self.env.company.id)], limit=1)
)
self.assertEqual(self.partner_2, new_invoice.partner_id)
# Import attachment as a vendor bill
new_invoice = self.edi_format._create_invoice_from_xml_tree(
filename='test_filename',
tree=edi_etree,
journal=self.env['account.journal'].search(
[('type', '=', 'purchase'), ('company_id', '=', self.env.company.id)], limit=1)
)
self.assertEqual(self.partner_1, new_invoice.partner_id)
def _test_encoding_in_attachment(self, edi_code, filename):
"""
Generate an invoice, assert that the tag '<?xml version='1.0' encoding='UTF-8'?>' is present in the attachment
@@ -292,6 +292,9 @@ class TestCIIFR(TestUBLCommon):
# Test import
####################################################
def test_import_partner_facturx(self):
self._test_import_partner('facturx_1_0_05', 'factur-x.xml')
def test_import_tax_included(self):
"""
Tests whether the tax included / tax excluded are correctly decoded when
@@ -220,6 +220,9 @@ class TestUBLBE(TestUBLCommon):
# Test import
####################################################
def test_import_partner_ubl(self):
self._test_import_partner('ubl_bis3', 'INV_2017_00002_ubl_bis3.xml')
def test_import_export_invoice_xml(self):
"""
Test whether the elements only specific to ubl_be are correctly exported