diff --git a/edi_party_data_oca/components/common.py b/edi_party_data_oca/components/common.py index bb2dec005..ad088a690 100644 --- a/edi_party_data_oca/components/common.py +++ b/edi_party_data_oca/components/common.py @@ -40,14 +40,15 @@ def _party_from_partner(self, **kw): party = DotDict( name=self._get_name(), identifiers=self._get_identifiers(), - # TODO: is this only for UBL? endpoint=self._get_endpoint(), + lang=self._get_lang(), + partner=self.partner, ) party.update(kw) return party def _get_name(self): - name_field = getattr(self.work, "party_data_name_field", "display_name") + name_field = getattr(self.work, "party_data_name_field", "name") return self.partner[name_field] def _get_endpoint(self): @@ -71,3 +72,12 @@ def _get_indentity(self, id_number): }, value=id_number.name, ) + + def _get_lang(self): + lang_code = getattr(self.work, "lang", False) or self.partner.lang + if not lang_code: + return False + lang = self.env["res.lang"]._get_data(code=lang_code) + if not lang: + return False + return {"name": lang.name, "code": lang.code, "short": lang.code.split("_")[0]} diff --git a/edi_party_data_oca/tests/test_party_data.py b/edi_party_data_oca/tests/test_party_data.py index 08a766b50..7d1484cd5 100644 --- a/edi_party_data_oca/tests/test_party_data.py +++ b/edi_party_data_oca/tests/test_party_data.py @@ -57,8 +57,16 @@ def setUpClass(cls): def _get_provider(self, partner, **kw): return get_party_data_component(self.exc_record, partner, **kw) + def _expected_lang(self, partner): + if not partner.lang: + return False + lang = self.env["res.lang"]._get_data(code=partner.lang) + if not lang: + return False + return {"name": lang.name, "code": lang.code, "short": lang.code.split("_")[0]} + def _make_expected_data( - self, partner, number, allowed_codes=None, name_field="display_name", **kw + self, partner, number, allowed_codes=None, name_field="name", **kw ): data = { "name": partner[name_field], @@ -68,6 +76,8 @@ def _make_expected_data( {"attrs": {"schemeID": "cat3"}, "value": f"cat3-p{number}"}, ], "endpoint": {}, + "lang": self._expected_lang(partner), + "partner": partner, } data.update(kw) if allowed_codes: @@ -102,32 +112,62 @@ def test_data(self): res = provider.get_party() self.assertEqual(res, expected_data) - def test_data_no_fullname(self): + def test_data_fullname_override(self): + # `name` is the default `party_data_name_field` since it doesn't embed + # multi-company/disambiguation suffixes the way `display_name` does; + # `display_name` is still available by explicit override. expected = ( ( self.partner1, - self._make_expected_data(self.partner1, 1, name_field="name"), + self._make_expected_data(self.partner1, 1, name_field="display_name"), ), ( self.partner2, self._make_expected_data( - self.partner2, 2, allowed_codes=["cat2", "cat3"], name_field="name" + self.partner2, + 2, + allowed_codes=["cat2", "cat3"], + name_field="display_name", ), ), ( self.partner3, self._make_expected_data( - self.partner3, 3, allowed_codes=["cat3"], name_field="name" + self.partner3, 3, allowed_codes=["cat3"], name_field="display_name" ), ), ) for partner, expected_data in expected: provider = self._get_provider( - partner, work_ctx={"party_data_name_field": "name"} + partner, work_ctx={"party_data_name_field": "display_name"} ) res = provider.get_party() self.assertEqual(res, expected_data) + def test_lang(self): + # No lang set on the partner -> no `lang` key rendered. + self.partner1.lang = False + provider = self._get_provider(self.partner1) + self.assertFalse(provider.get_party()["lang"]) + # Partner's own lang is used by default. + self.partner1.lang = "en_US" + provider = self._get_provider(self.partner1) + self.assertEqual( + provider.get_party()["lang"], + {"name": "English (US)", "code": "en_US", "short": "en"}, + ) + # `work_ctx["lang"]` takes precedence over the partner's own lang. + self.partner2.lang = False + provider = self._get_provider(self.partner2, work_ctx={"lang": "en_US"}) + self.assertEqual( + provider.get_party()["lang"], + {"name": "English (US)", "code": "en_US", "short": "en"}, + ) + + def test_partner_in_party_data(self): + provider = self._get_provider(self.partner1) + self.assertEqual(provider.get_party()["partner"], self.partner1) + def test_data_limited_1(self): self.exc_type.id_category_ids = self.category1 expected = ( diff --git a/edi_sale_ubl_output_oca/tests/test_order_response_out.py b/edi_sale_ubl_output_oca/tests/test_order_response_out.py index 1ecb08fb9..5b538f179 100644 --- a/edi_sale_ubl_output_oca/tests/test_order_response_out.py +++ b/edi_sale_ubl_output_oca/tests/test_order_response_out.py @@ -52,16 +52,33 @@ def test_get_template(self): def test_render_values(self): # TODO: test w/ some identifiers + def make_lang(record): + if not record.lang: + return False + lang = self.env["res.lang"]._get_data(code=record.lang) + if not lang: + return False + return { + "name": lang.name, + "code": lang.code, + "short": lang.code.split("_")[0], + } + def make_party(record): return dict( name=record.name, identifiers=[], endpoint={}, + lang=make_lang(record), + partner=record, ) values = self.exc_tmpl._get_render_values(self.record) expected = [ - ("seller_party", make_party(self.order.company_id)), + # Match what the code_snippet actually passes to `get_party_data`: + # `record.company_id.partner_id` (a res.partner), not the + # res.company itself (which has no `lang` field). + ("seller_party", make_party(self.order.company_id.partner_id)), ("buyer_party", make_party(self.order.partner_id)), ] for k, v in expected: diff --git a/edi_ubl_output_base_oca/templates/qweb_tmpl_party.xml b/edi_ubl_output_base_oca/templates/qweb_tmpl_party.xml index d1683fc88..bbb9d3516 100644 --- a/edi_ubl_output_base_oca/templates/qweb_tmpl_party.xml +++ b/edi_ubl_output_base_oca/templates/qweb_tmpl_party.xml @@ -5,6 +5,7 @@ xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" > + Moderna Produkter AB + + de + Schweiz / Deutsch + de_CH + + + + + + + + + VAT + + + + ACME + + + + + + + + + diff --git a/edi_ubl_output_base_oca/tests/test_templates.py b/edi_ubl_output_base_oca/tests/test_templates.py index e47832c07..9812f3513 100644 --- a/edi_ubl_output_base_oca/tests/test_templates.py +++ b/edi_ubl_output_base_oca/tests/test_templates.py @@ -62,6 +62,88 @@ def test_party_with_endpoint_and_identifiers(self): identification = root.find(".//cac:PartyIdentification/cbc:ID", NS) self.assertEqual(identification.text, "8591234567894") + def test_party_full_blocks(self): + self.partner.write({"vat": "CHE-000.000.000 MWST", "phone": "+41 123434343"}) + party = DotDict( + name="ACME Vendor", + identifiers=[], + endpoint={}, + partner=self.partner, + lang={"name": "Schweiz / Deutsch", "code": "de_CH", "short": "de"}, + ) + xml = self._render( + "edi_ubl_output_base_oca.qweb_tmpl_ubl_party", + { + "party": party, + "show_full_address": True, + "show_tax_scheme": True, + "show_legal_entity": True, + "show_contact": True, + }, + ) + root = etree.fromstring( + f"{xml}" + ) + lang_node = root.find(".//cac:Language", NS) + self.assertEqual(lang_node.find("cbc:ID", NS).text, "de") + self.assertEqual(lang_node.find("cbc:Name", NS).text, "Schweiz / Deutsch") + self.assertEqual(lang_node.find("cbc:LocaleCode", NS).text, "de_CH") + self.assertEqual( + root.find("cac:Party/cac:PostalAddress/cbc:StreetName", NS).text, + "Foo street 1", + ) + self.assertEqual( + root.find(".//cac:PartyTaxScheme/cbc:CompanyID", NS).text, + "CHE-000.000.000 MWST", + ) + legal_entity = root.find(".//cac:PartyLegalEntity", NS) + self.assertEqual( + legal_entity.find("cbc:RegistrationName", NS).text, "ACME Vendor" + ) + self.assertEqual( + legal_entity.find("cac:RegistrationAddress/cbc:StreetName", NS).text, + "Foo street 1", + ) + contact = root.find(".//cac:Contact", NS) + self.assertEqual(contact.find("cbc:Name", NS).text, "ACME Vendor") + self.assertEqual(contact.find("cbc:Telephone", NS).text, "+41 123434343") + + def test_party_show_flags_default_off(self): + # Without explicitly passing the `show_*` flags, none of the optional + # blocks render, even when `party.partner` carries data for them. + self.partner.write({"vat": "CHE-000.000.000 MWST"}) + party = DotDict( + name="ACME Vendor", identifiers=[], endpoint={}, partner=self.partner + ) + xml = self._render( + "edi_ubl_output_base_oca.qweb_tmpl_ubl_party", {"party": party} + ) + root = etree.fromstring( + f"{xml}" + ) + self.assertIsNone(root.find(".//cac:PostalAddress", NS)) + self.assertIsNone(root.find(".//cac:PartyTaxScheme", NS)) + self.assertIsNone(root.find(".//cac:PartyLegalEntity", NS)) + self.assertIsNone(root.find(".//cac:Contact", NS)) + + def test_party_explicit_partner_overrides_party_partner(self): + other_partner = self.env["res.partner"].create( + {"name": "Other Partner", "street": "Other street"} + ) + party = DotDict( + name="ACME Vendor", identifiers=[], endpoint={}, partner=self.partner + ) + xml = self._render( + "edi_ubl_output_base_oca.qweb_tmpl_ubl_party", + {"party": party, "partner": other_partner, "show_full_address": True}, + ) + root = etree.fromstring( + f"{xml}" + ) + self.assertEqual( + root.find(".//cac:PostalAddress/cbc:StreetName", NS).text, "Other street" + ) + def test_address(self): xml = self._render( "edi_ubl_output_base_oca.qweb_tmpl_ubl_address", {"partner": self.partner}