diff --git a/account_edi_ubl_cii_payment_unece/README.rst b/account_edi_ubl_cii_payment_unece/README.rst new file mode 100644 index 0000000000..9d5d7da9d8 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/README.rst @@ -0,0 +1,88 @@ +================================================= +Electronic invoices with UBL/CII - UNECE payments +================================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:2700b6157b3804b70aebf0ab3ce069449a78393795880a288a0178e0a9dff400 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github + :target: https://github.com/OCA/edi/tree/18.0/account_edi_ubl_cii_payment_unece + :alt: OCA/edi +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/edi-18-0/edi-18-0-account_edi_ubl_cii_payment_unece + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Integrate UNECE Payment Means (module ``account_payment_unece`` from +`OCA/community-data-files +project `__) with Odoo +standard UBL/CII electronic invoices (module ``account_edi_ubl_cii``). + +When using for example SEPA direct debit, your can configure the +corresponding UNECE code on the payment method and this will be declared +properly in the electronic invoice. Also, when receiving an invoice +declared with a payment means SEPA direct debit, you can configure an +outbound payment means with that UNECE code and the created invoice will +have that payment means set so that you know you don't have to pay it. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* BCIM +* Akretion + +Contributors +------------ + +- Jacques-Etienne Baudoux +- Sébastien Alix + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/edi `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_edi_ubl_cii_payment_unece/__init__.py b/account_edi_ubl_cii_payment_unece/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_edi_ubl_cii_payment_unece/__manifest__.py b/account_edi_ubl_cii_payment_unece/__manifest__.py new file mode 100644 index 0000000000..83911c831d --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +{ + "name": "Electronic invoices with UBL/CII - UNECE payments", + "version": "18.0.1.0.0", + "category": "Accounting & Finance", + "license": "AGPL-3", + "summary": "Import/Export UNECE payment codes in UBL and CII XML documents.", + "author": "BCIM, Akretion, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/edi", + "depends": [ + # Odoo + "account_edi_ubl_cii", + # OCA/community-data-files + "account_payment_unece", + ], + "data": [ + "data/account_payment_method.xml", + ], + "installable": True, + "auto_install": True, +} diff --git a/account_edi_ubl_cii_payment_unece/data/account_payment_method.xml b/account_edi_ubl_cii_payment_unece/data/account_payment_method.xml new file mode 100644 index 0000000000..f31c2bf1e6 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/data/account_payment_method.xml @@ -0,0 +1,18 @@ + + + + + Direct Debit to suppliers + direct_debit + outbound + + + + + SEPA Direct Debit to suppliers + direct_debit_sepa + outbound + + + diff --git a/account_edi_ubl_cii_payment_unece/models/__init__.py b/account_edi_ubl_cii_payment_unece/models/__init__.py new file mode 100644 index 0000000000..39afe0be9b --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/models/__init__.py @@ -0,0 +1,3 @@ +from . import account_edi_ubl +from . import account_edi_xml_cii +from . import account_edi_xml_ubl_bis3 diff --git a/account_edi_ubl_cii_payment_unece/models/account_edi_ubl.py b/account_edi_ubl_cii_payment_unece/models/account_edi_ubl.py new file mode 100644 index 0000000000..aa34ba2eb1 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/models/account_edi_ubl.py @@ -0,0 +1,40 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import models + + +class AccountEdiUBL(models.AbstractModel): + _inherit = "account.edi.ubl" + + def _import_ubl_invoice_add_payment_reference(self, collected_values): + # NOTE: we override this method to access `collected_values`. It could + # have been any method called in '._ubl_import_invoice()'. + res = super()._import_ubl_invoice_add_payment_reference(collected_values) + self._import_ubl_invoice_add_unece_payment_mean(collected_values) + return res + + def _import_ubl_invoice_add_unece_payment_mean(self, collected_values): + tree = collected_values["tree"] + payment_mean_code = None + for node in tree.findall("./{*}PaymentMeans/{*}PaymentMeansCode"): + if note := node.text: + payment_mean_code = note + break + if not payment_mean_code: + return + # Look for a matching payment method line + payment_method_line = self.env["account.payment.method.line"].search( + [ + ("journal_id.type", "in", ("cash", "bank", "credit")), + ("payment_type", "=", "outbound"), + ("payment_method_id.unece_code", "=", payment_mean_code), + ], + limit=1, + ) + if not payment_method_line: + return + collected_values["to_write"]["preferred_payment_method_line_id"] = ( + payment_method_line.id + ) diff --git a/account_edi_ubl_cii_payment_unece/models/account_edi_xml_cii.py b/account_edi_ubl_cii_payment_unece/models/account_edi_xml_cii.py new file mode 100644 index 0000000000..289be1f8c8 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/models/account_edi_xml_cii.py @@ -0,0 +1,47 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import models + + +class AccountEdiXmlCII(models.AbstractModel): + _inherit = "account.edi.xml.cii" + + def _export_invoice_vals(self, invoice): + template_values = super()._export_invoice_vals(invoice) + payment_method_line = invoice.preferred_payment_method_line_id + payment_method = payment_method_line.payment_method_id + if payment_method.unece_id: + # Integrate UNECE payment means + template_values["payment_means_code"] = payment_method.unece_id.code + return template_values + + def _import_fill_invoice(self, invoice, tree, qty_factor): + res = super()._import_fill_invoice(invoice, tree, qty_factor) + invoice_values = self._extract_invoice_unece_payment_mean(invoice, tree) + if invoice_values: + invoice.write(invoice_values) + return res + + def _extract_invoice_unece_payment_mean(self, invoice, tree): + payment_mean_code = None + for node in tree.findall( + ".//{*}SpecifiedTradeSettlementPaymentMeans/{*}TypeCode" + ): + if payment_mean_code := node.text: + break + if not payment_mean_code: + return {} + # Look for a matching payment method line + payment_method_line = self.env["account.payment.method.line"].search( + [ + ("journal_id.type", "in", ("cash", "bank", "credit")), + ("payment_type", "=", "outbound"), + ("payment_method_id.unece_code", "=", payment_mean_code), + ], + limit=1, + ) + if not payment_method_line: + return + return {"preferred_payment_method_line_id": payment_method_line.id} diff --git a/account_edi_ubl_cii_payment_unece/models/account_edi_xml_ubl_bis3.py b/account_edi_ubl_cii_payment_unece/models/account_edi_xml_ubl_bis3.py new file mode 100644 index 0000000000..b8afc7a0f1 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/models/account_edi_xml_ubl_bis3.py @@ -0,0 +1,25 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import models + + +class AccountEdiXmlUBLBIS3(models.AbstractModel): + _inherit = "account.edi.xml.ubl_bis3" + + def _ubl_add_payment_means_nodes(self, vals): + super()._ubl_add_payment_means_nodes(vals) + nodes = vals["document_node"]["cac:PaymentMeans"] + invoice = vals.get("invoice") + if not invoice: + return + payment_method_line = invoice.preferred_payment_method_line_id + payment_method = payment_method_line.payment_method_id + if payment_method.unece_id: + # Integrate UNECE payment means + for node in nodes: + node["cbc:PaymentMeansCode"] = { + "_text": payment_method.unece_id.code, + "name": payment_method.unece_id.name, + } diff --git a/account_edi_ubl_cii_payment_unece/pyproject.toml b/account_edi_ubl_cii_payment_unece/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/account_edi_ubl_cii_payment_unece/readme/CONTRIBUTORS.md b/account_edi_ubl_cii_payment_unece/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..171e9a614d --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Jacques-Etienne Baudoux \<\> +- Sébastien Alix \<\> diff --git a/account_edi_ubl_cii_payment_unece/readme/DESCRIPTION.md b/account_edi_ubl_cii_payment_unece/readme/DESCRIPTION.md new file mode 100644 index 0000000000..4446587b90 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/readme/DESCRIPTION.md @@ -0,0 +1,10 @@ +Integrate UNECE Payment Means (module `account_payment_unece` from +[OCA/community-data-files project](https://github.com/OCA/community-data-files/)) +with Odoo standard UBL/CII electronic invoices (module `account_edi_ubl_cii`). + +When using for example SEPA direct debit, your can configure the corresponding +UNECE code on the payment method and this will be declared properly in the +electronic invoice. +Also, when receiving an invoice declared with a payment means SEPA direct debit, +you can configure an outbound payment means with that UNECE code and the created +invoice will have that payment means set so that you know you don't have to pay it. diff --git a/account_edi_ubl_cii_payment_unece/static/description/index.html b/account_edi_ubl_cii_payment_unece/static/description/index.html new file mode 100644 index 0000000000..f72c74e9f3 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/static/description/index.html @@ -0,0 +1,434 @@ + + + + + +Electronic invoices with UBL/CII - UNECE payments + + + +
+

Electronic invoices with UBL/CII - UNECE payments

+ + +

Beta License: AGPL-3 OCA/edi Translate me on Weblate Try me on Runboat

+

Integrate UNECE Payment Means (module account_payment_unece from +OCA/community-data-files +project) with Odoo +standard UBL/CII electronic invoices (module account_edi_ubl_cii).

+

When using for example SEPA direct debit, your can configure the +corresponding UNECE code on the payment method and this will be declared +properly in the electronic invoice. Also, when receiving an invoice +declared with a payment means SEPA direct debit, you can configure an +outbound payment means with that UNECE code and the created invoice will +have that payment means set so that you know you don’t have to pay it.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • BCIM
  • +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/edi project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/account_edi_ubl_cii_payment_unece/tests/__init__.py b/account_edi_ubl_cii_payment_unece/tests/__init__.py new file mode 100644 index 0000000000..06967cd30a --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_edi_ubl_bis3 diff --git a/account_edi_ubl_cii_payment_unece/tests/common.py b/account_edi_ubl_cii_payment_unece/tests/common.py new file mode 100644 index 0000000000..f4a9b557b5 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/common.py @@ -0,0 +1,83 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import base64 + +from odoo import Command +from odoo.tests.common import TransactionCase +from odoo.tools.misc import file_open + + +class CommonAccountEdiUnece(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.tax = cls.env["account.tax"].create( + { + "name": "TEST Tax", + "amount": 20, + "amount_type": "percent", + } + ) + cls.journal = cls.env.ref("account.1_bank") + cls.inbound_payment_method = cls.env.ref( + "account.account_payment_method_manual_in" + ) + cls.inbound_payment_method_line = cls.inbound_payment_method.line_ids.filtered( + lambda line: line.journal_id == cls.journal + ) + cls.outbound_payment_method = cls.env.ref( + "account.account_payment_method_manual_out" + ) + cls.outbound_payment_method_line = ( + cls.outbound_payment_method.line_ids.filtered( + lambda line: line.journal_id == cls.journal + ).copy({"journal_id": cls.env.ref("account.1_purchase").id}) + ) + cls.partner = cls.env["res.partner"].create( + { + "name": "TEST", + "email": "test@example.net", + "property_inbound_payment_method_line_id": ( + cls.inbound_payment_method_line.id + ), + } + ) + + def _create_out_invoice(self, post=False): + vals = { + "move_type": "out_invoice", + "partner_id": self.partner.id, + "invoice_line_ids": [ + Command.create( + { + "name": "TEST", + "price_unit": 100, + "quantity": 1, + "tax_ids": self.tax.ids, + } + ) + ], + } + invoice = self.env["account.move"].create(vals) + if post: + invoice.action_post() + return invoice + + def _create_in_invoice(self): + vals = { + "move_type": "in_invoice", + "partner_id": self.partner.id, + } + return self.env["account.move"].create(vals) + + def _import_invoice_xml_file(self, invoice, file_path): + """Update `invoice` by importing `file_path` XML file data.""" + with file_open(file_path, mode="rb") as file_: + content = file_.read() + invoice.ubl_cii_xml_file = base64.b64encode(content) + file_data = invoice.ubl_cii_xml_id._unwrap_edi_attachments()[0] + decoder = invoice._get_edi_decoder(file_data) + decoder(invoice, file_data) diff --git a/account_edi_ubl_cii_payment_unece/tests/test_account_edi_cii.py b/account_edi_ubl_cii_payment_unece/tests/test_account_edi_cii.py new file mode 100644 index 0000000000..0b8fe6d3e3 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/test_account_edi_cii.py @@ -0,0 +1,107 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import base64 + +import lxml + +from .common import CommonAccountEdiUnece + + +class TestAccountEdiCII(CommonAccountEdiUnece): + def test_export_facturx(self): + """Test export of UNECE payment mean code to FacturX XML file.""" + # Configure company + self.env.company.write( + { + "country_id": self.env.ref("base.fr").id, + "vat": "FR00000000000", + } + ) + # Configure payment method + unece = self.env.ref("account_payment_unece.payment_means_31") + self.inbound_payment_method.unece_id = unece + # Configure partner + self.partner.write( + { + "country_id": self.env.ref("base.fr").id, + "invoice_edi_format": "facturx", + } + ) + # Create invoice + invoice = self._create_out_invoice(post=True) + self.assertTrue(invoice.preferred_payment_method_line_id) + # Send it to generate its XML file + wiz_send = ( + self.env["account.move.send.wizard"] + .with_context(active_model=invoice._name, active_ids=invoice.ids) + .create({}) + ) + wiz_send.action_send_and_print() + # Check XML file content + self.assertTrue(invoice.ubl_cii_xml_file) + xml = base64.b64decode(invoice.ubl_cii_xml_file) + root = lxml.etree.fromstring(xml) + payment_means = root.find(".//{*}SpecifiedTradeSettlementPaymentMeans") + self.assertTrue(len(payment_means)) + payment_means_code = payment_means.find("{*}TypeCode") + self.assertTrue(payment_means_code is not None) + self.assertEqual(payment_means_code.text, unece.code) + + def test_export_zugferd(self): + """Test export of UNECE payment mean code to ZUGFeRD XML file.""" + # Configure company + self.env.company.write( + { + "country_id": self.env.ref("base.de").id, + "vat": "DE00000000000", + } + ) + # Configure payment method + unece = self.env.ref("account_payment_unece.payment_means_31") + self.inbound_payment_method.unece_id = unece + # Configure partner + self.partner.write( + { + "country_id": self.env.ref("base.de").id, + "invoice_edi_format": "zugferd", + } + ) + # Create invoice + invoice = self._create_out_invoice(post=True) + self.assertTrue(invoice.preferred_payment_method_line_id) + # Send it to generate its XML file + wiz_send = ( + self.env["account.move.send.wizard"] + .with_context(active_model=invoice._name, active_ids=invoice.ids) + .create({}) + ) + wiz_send.action_send_and_print() + # Check XML file content + self.assertTrue(invoice.ubl_cii_xml_file) + xml = base64.b64decode(invoice.ubl_cii_xml_file) + root = lxml.etree.fromstring(xml) + payment_means = root.find(".//{*}SpecifiedTradeSettlementPaymentMeans") + self.assertTrue(len(payment_means)) + payment_means_code = payment_means.find("{*}TypeCode") + self.assertTrue(payment_means_code is not None) + self.assertEqual(payment_means_code.text, unece.code) + + def test_import_facturx(self): + """Test import of UNECE payment mean code from FacturX XML file.""" + # Configure payment method + unece = self.env.ref("account_payment_unece.payment_means_31") + self.outbound_payment_method.unece_id = unece + # Create a draft invoice (current partner will be overridden) + invoice = self._create_in_invoice() + # Import the XML invoice file containing the expected UNECE payment mean code + file_path = ( + "account_edi_ubl_cii_payment_unece/" + "tests/test_files/test_import_invoice_facturx.xml" + ) + self._import_invoice_xml_file(invoice, file_path) + # Check payment method + payment_method = invoice.preferred_payment_method_line_id.payment_method_id + self.assertEqual(payment_method.unece_id, unece) + self.assertEqual(payment_method, self.outbound_payment_method) diff --git a/account_edi_ubl_cii_payment_unece/tests/test_account_edi_ubl_bis3.py b/account_edi_ubl_cii_payment_unece/tests/test_account_edi_ubl_bis3.py new file mode 100644 index 0000000000..73ad5a5309 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/test_account_edi_ubl_bis3.py @@ -0,0 +1,62 @@ +# Copyright 2026 Akretion (https://www.akretion.com). +# @author Sébastien Alix +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +import base64 + +import lxml + +from .common import CommonAccountEdiUnece + + +class TestAccountEdiUBLBIS3(CommonAccountEdiUnece): + def test_export_ubl_bis3(self): + """Test export of UNECE payment mean code to BIS3 XML file.""" + # Configure payment method + unece = self.env.ref("account_payment_unece.payment_means_31") + self.inbound_payment_method.unece_id = unece + # Configure partner + self.partner.write( + { + "country_id": self.env.ref("base.be").id, + "invoice_edi_format": "ubl_bis3", + } + ) + # Create invoice + invoice = self._create_out_invoice(post=True) + self.assertTrue(invoice.preferred_payment_method_line_id) + # Send it to generate its XML file + wiz_send = ( + self.env["account.move.send.wizard"] + .with_context(active_model=invoice._name, active_ids=invoice.ids) + .create({}) + ) + wiz_send.action_send_and_print() + # Check XML file content + self.assertTrue(invoice.ubl_cii_xml_file) + xml = base64.b64decode(invoice.ubl_cii_xml_file) + root = lxml.etree.fromstring(xml) + payment_means = root.find(".//{*}PaymentMeans") + self.assertTrue(len(payment_means)) + payment_means_code = payment_means.find("{*}PaymentMeansCode") + self.assertTrue(payment_means_code is not None) + self.assertEqual(payment_means_code.text, unece.code) + self.assertEqual(payment_means_code.attrib.get("name"), unece.name) + + def test_import_ubl_bis3(self): + """Test import of UNECE payment mean code from BIS3 XML file.""" + # Configure payment method + unece = self.env.ref("account_payment_unece.payment_means_31") + self.outbound_payment_method.unece_id = unece + # Create a draft invoice (current partner will be overridden) + invoice = self._create_in_invoice() + # Import the XML invoice file containing the expected UNECE payment mean code + file_path = ( + "account_edi_ubl_cii_payment_unece/" + "tests/test_files/test_import_invoice_ubl_bis3.xml" + ) + self._import_invoice_xml_file(invoice, file_path) + # Check payment method + payment_method = invoice.preferred_payment_method_line_id.payment_method_id + self.assertEqual(payment_method.unece_id, unece) + self.assertEqual(payment_method, self.outbound_payment_method) diff --git a/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_facturx.xml b/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_facturx.xml new file mode 100644 index 0000000000..06937c5172 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_facturx.xml @@ -0,0 +1,149 @@ + + + + + urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended + + + + FAC/2026/00003 + 380 + + 20260506 + + + + + + 1 + + + E-COM06 + Bureau d'angle avec siège à droite + [E-COM06] Bureau d'angle avec siège à droite + + + + 147.00 + + + 147.00 + + + + 1.0 + + + + VAT + S + 21.0 + + + 147.00 + + + + + + TEST FR + + TEST FR + + 0202030405 + + + test@example.net + + + + FR + + + FR00000000000 + + + + TEST FR + + TEST FR + + test@example.net + + + + FR + + + + FAC/2026/00003 + + + + + TEST FR + + TEST FR + + test@example.net + + + + FR + + + + + 20260506 + + + + + +++000/0000/05252+++ + EUR + + 31 + + BNQTEST + + + + 30.87 + VAT + 147.00 + S + 5 + 21.0 + + + + 20260506 + + + 20260506 + + + + + 20260506 + + + + 147.00 + 147.00 + 30.87 + 177.87 + 0.00 + 177.87 + + + + diff --git a/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_ubl_bis3.xml b/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_ubl_bis3.xml new file mode 100644 index 0000000000..4088685a85 --- /dev/null +++ b/account_edi_ubl_cii_payment_unece/tests/test_files/test_import_invoice_ubl_bis3.xml @@ -0,0 +1,141 @@ + + + urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + FAC/2023/00052 + 2023-08-04 + 2023-09-04 + 380 + EUR + + FAC/2023/00052 + S00012 + + + + LU25587702 + + ALD Automotive LU + + + 270 rte d'Arlon + Strassen + 8010 + + LU + + + + LU12977109 + + VAT + + + + ALD Automotive LU + LU12977109 + + + ALD Automotive LU + adl@test.com + + + + + + LU25587702 + + Odoo Lu + + + Rue de l'industrie 13 + Windhof + + LU + + + + LU25587702 + + VAT + + + + Odoo Lu + LU25587702 + + + Odoo Lu + odoo@test.com + + + + + + + Rue de l'industrie 13 + Windhof + + LU + + + + + + partner_a + + + + + 31 + FAC/2023/00052 + + LU071241358706500000 + + + + 105.12 + + 657.00 + 105.12 + + S + 16.0 + + VAT + + + + + + 657.00 + 657.00 + 762.12 + 0.00 + 762.12 + + + 1 + 1.0 + 657.00 + + product_a + product_a + + S + 16.0 + + VAT + + + + + 657.00 + + +