Skip to content

Commit

Permalink
[IMP] account_edi_ubl_cii: handles UBL files with namespaces per line
Browse files Browse the repository at this point in the history
When importing a UBL file Odoo expects the UBL specific namespaces to be in the root element of the file. This is not always the case as these namespaces could exist in every element in the file. When a file is formatted this way, Odoo cannot extract the necessary data from it because it is missing the necessary namespaces. To cover this case we use the lxml.etree.Element.find function instead, and pass in the UBL specific namespaces to successfully extract the data.

closes odoo#151548

Task: 3657563
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
  • Loading branch information
AllePilli committed Apr 5, 2024
1 parent c51870f commit 1e24b15
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 7 deletions.
4 changes: 2 additions & 2 deletions addons/account_edi_ubl_cii/models/account_edi_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ def _get_uom_unece_code(self, line):
return UOM_TO_UNECE_CODE.get(xmlid[line.product_uom_id.id], 'C62')
return 'C62'

def _find_value(self, xpath, tree):
def _find_value(self, xpath, tree, nsmap=False):
# avoid 'TypeError: empty namespace prefix is not supported in XPath'
nsmap = {k: v for k, v in tree.nsmap.items() if k is not None}
nsmap = nsmap or {k: v for k, v in tree.nsmap.items() if k is not None}
return find_xml_value(xpath, tree, nsmap)

# -------------------------------------------------------------------------
Expand Down
19 changes: 14 additions & 5 deletions addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@
from odoo import models, _
from odoo.tools import html2plaintext, cleanup_xml_node

UBL_NAMESPACES = {
'cbc': "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
'cac': "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
}


class AccountEdiXmlUBL20(models.AbstractModel):
_name = "account.edi.xml.ubl_20"
_inherit = 'account.edi.common'
_description = "UBL 2.0"

# EXTENDS account.edi.common
def _find_value(self, xpath, tree):
return super()._find_value(xpath, tree, UBL_NAMESPACES)

# -------------------------------------------------------------------------
# EXPORT
# -------------------------------------------------------------------------
Expand Down Expand Up @@ -600,11 +609,11 @@ def _import_fill_invoice_form(self, invoice, tree, qty_factor):
# ==== partner_id ====

role = "Customer" if invoice.journal_id.type == 'sale' else "Supplier"
vat = self._find_value(f'//cac:Accounting{role}Party/cac:Party//cbc:CompanyID[string-length(text()) > 5]', tree)
phone = self._find_value(f'//cac:Accounting{role}Party/cac:Party//cbc:Telephone', tree)
mail = self._find_value(f'//cac:Accounting{role}Party/cac:Party//cbc:ElectronicMail', tree)
name = self._find_value(f'//cac:Accounting{role}Party/cac:Party//cbc:Name', tree)
country_code = self._find_value(f'//cac:Accounting{role}Party/cac:Party//cac:Country//cbc:IdentificationCode', tree)
vat = self._find_value(f'.//cac:Accounting{role}Party/cac:Party//cbc:CompanyID[string-length(text()) > 5]', tree)
phone = self._find_value(f'.//cac:Accounting{role}Party/cac:Party//cbc:Telephone', tree)
mail = self._find_value(f'.//cac:Accounting{role}Party/cac:Party//cbc:ElectronicMail', tree)
name = self._find_value(f'.//cac:Accounting{role}Party/cac:Party//cbc:Name', tree)
country_code = self._find_value(f'.//cac:Accounting{role}Party/cac:Party//cac:Country//cbc:IdentificationCode', tree)
self._import_retrieve_and_fill_partner(invoice, name=name, phone=phone, mail=mail, vat=vat, country_code=country_code)

# ==== currency_id ====
Expand Down

0 comments on commit 1e24b15

Please sign in to comment.