diff --git a/addons/l10n_ro_edi/__init__.py b/addons/l10n_ro_edi/__init__.py
new file mode 100644
index 00000000000..0650744f6bc
--- /dev/null
+++ b/addons/l10n_ro_edi/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/addons/l10n_ro_edi/__manifest__.py b/addons/l10n_ro_edi/__manifest__.py
new file mode 100644
index 00000000000..9a7c3c57273
--- /dev/null
+++ b/addons/l10n_ro_edi/__manifest__.py
@@ -0,0 +1,20 @@
+{
+ 'author': 'Odoo',
+ 'name': 'Romania - E-invoicing',
+ 'version': '1.0',
+ 'category': 'Accounting/Localizations/EDI',
+ 'description': """
+ E-invoice implementation for Romania
+ """,
+ 'summary': """
+ E-Invoice implementation for Romania
+ """,
+ 'countries': ['ro'],
+ 'depends': [
+ 'account_edi_ubl_cii',
+ 'l10n_ro',
+ ],
+ 'installable': True,
+ 'auto_install': True,
+ 'license': 'LGPL-3',
+}
diff --git a/addons/l10n_ro_edi/i18n/l10n_ro_edi.pot b/addons/l10n_ro_edi/i18n/l10n_ro_edi.pot
new file mode 100644
index 00000000000..90b9f09cbb5
--- /dev/null
+++ b/addons/l10n_ro_edi/i18n/l10n_ro_edi.pot
@@ -0,0 +1,74 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * l10n_ro_edi
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.5alpha1+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-08-31 13:31+0000\n"
+"PO-Revision-Date: 2023-08-31 13:31+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: l10n_ro_edi
+#: model:ir.model,name:l10n_ro_edi.model_account_edi_xml_ubl_ro
+msgid "CIUS RO"
+msgstr ""
+
+#. module: l10n_ro_edi
+#: model:ir.model.fields.selection,name:l10n_ro_edi.selection__res_partner__ubl_cii_format__ciusro
+msgid "CIUSRO"
+msgstr ""
+
+#. module: l10n_ro_edi
+#: model:ir.model,name:l10n_ro_edi.model_res_partner
+msgid "Contact"
+msgstr ""
+
+#. module: l10n_ro_edi
+#: model:ir.model.fields,field_description:l10n_ro_edi.field_res_partner__ubl_cii_format
+#: model:ir.model.fields,field_description:l10n_ro_edi.field_res_users__ubl_cii_format
+msgid "Format"
+msgstr ""
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner doesn't have a VAT nor Company ID: %s. At least one of"
+" them is required. "
+msgstr ""
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's city name is invalid: %s. If partner's state is "
+"București, the city name must be 'SECTORX', where X is a number between 1-6."
+" "
+msgstr ""
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's doesn't have a country code prefix in their Company "
+"ID: %s. "
+msgstr ""
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's doesn't have a country code prefix in their VAT: %s."
+" "
+msgstr ""
diff --git a/addons/l10n_ro_edi/i18n/ro.po b/addons/l10n_ro_edi/i18n/ro.po
new file mode 100644
index 00000000000..1d130813fae
--- /dev/null
+++ b/addons/l10n_ro_edi/i18n/ro.po
@@ -0,0 +1,80 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * l10n_ro_edi
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.5alpha1+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-08-31 13:32+0000\n"
+"PO-Revision-Date: 2023-08-31 13:32+0000\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: l10n_ro_edi
+#: model:ir.model,name:l10n_ro_edi.model_account_edi_xml_ubl_ro
+msgid "CIUS RO"
+msgstr "CIUS RO"
+
+#. module: l10n_ro_edi
+#: model:ir.model.fields.selection,name:l10n_ro_edi.selection__res_partner__ubl_cii_format__ciusro
+msgid "CIUSRO"
+msgstr "CIUSRO"
+
+#. module: l10n_ro_edi
+#: model:ir.model,name:l10n_ro_edi.model_res_partner
+msgid "Contact"
+msgstr "A lua legatura"
+
+#. module: l10n_ro_edi
+#: model:ir.model.fields,field_description:l10n_ro_edi.field_res_partner__ubl_cii_format
+#: model:ir.model.fields,field_description:l10n_ro_edi.field_res_users__ubl_cii_format
+msgid "Format"
+msgstr "Format"
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner doesn't have a VAT nor Company ID: %s. At least one of"
+" them is required. "
+msgstr ""
+"Următorul partener nu are TVA sau ID de companie: %s. Cel puțin unul dintre "
+"ele este necesar. "
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's city name is invalid: %s. If partner's state is "
+"București, the city name must be 'SECTORX', where X is a number between 1-6."
+" "
+msgstr ""
+"Numele orașului următor partener este nevalid: %s. Dacă statul partenerului "
+"este București, numele orașului trebuie să fie 'SECTORX', unde X este un "
+"număr între 1-6. "
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's doesn't have a country code prefix in their Company "
+"ID: %s. "
+msgstr ""
+"Următorii parteneri nu au un prefix de cod de țară în ID-ul companiei: %s. "
+
+#. module: l10n_ro_edi
+#. odoo-python
+#: code:addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py:0
+#, python-format
+msgid ""
+"The following partner's doesn't have a country code prefix in their VAT: %s."
+" "
+msgstr "Următorii parteneri nu au un prefix de cod de țară în TVA: %s. "
diff --git a/addons/l10n_ro_edi/models/__init__.py b/addons/l10n_ro_edi/models/__init__.py
new file mode 100644
index 00000000000..ea826c82884
--- /dev/null
+++ b/addons/l10n_ro_edi/models/__init__.py
@@ -0,0 +1,2 @@
+from . import account_edi_xml_ubl_ciusro
+from . import res_partner
diff --git a/addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py b/addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py
new file mode 100644
index 00000000000..ddea1c5a999
--- /dev/null
+++ b/addons/l10n_ro_edi/models/account_edi_xml_ubl_ciusro.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, _
+
+
+SECTOR_RO_CODES = ('SECTOR1', 'SECTOR2', 'SECTOR3', 'SECTOR4', 'SECTOR5', 'SECTOR6')
+
+
+class AccountEdiXmlUBLRO(models.AbstractModel):
+ _inherit = "account.edi.xml.ubl_bis3"
+ _name = "account.edi.xml.ubl_ro"
+ _description = "CIUS RO"
+
+ def _export_invoice_filename(self, invoice):
+ return f"{invoice.name.replace('/', '_')}_cius_ro.xml"
+
+ def _get_partner_address_vals(self, partner):
+ # EXTENDS 'account_edi_ubl_cii'
+ vals = super()._get_partner_address_vals(partner)
+
+ if partner.state_id:
+ vals["country_subentity"] = partner.country_code + '-' + partner.state_id.code
+
+ return vals
+
+ def _get_invoice_tax_totals_vals_list(self, invoice, taxes_vals):
+ # EXTENDS 'account_edi_ubl_cii'
+ vals_list = super()._get_invoice_tax_totals_vals_list(invoice, taxes_vals)
+
+ if invoice.currency_id.name != 'RON':
+ ron_currency = self.env.ref("base.RON")
+ vals_list.append({
+ 'currency': ron_currency,
+ 'currency_dp': ron_currency.decimal_places,
+ 'tax_amount': taxes_vals['tax_amount'],
+ })
+
+ return vals_list
+
+ def _get_partner_party_tax_scheme_vals_list(self, partner, role):
+ # EXTENDS 'account_edi_ubl_cii'
+ vals_list = super()._get_partner_party_tax_scheme_vals_list(partner, role)
+
+ if not partner.vat and partner.company_registry:
+ return [{
+ 'company_id': partner.company_registry,
+ 'TaxScheme_vals': {},
+ 'tax_scheme_id': 'VAT',
+ }]
+
+ return vals_list
+
+ def _get_partner_party_legal_entity_vals_list(self, partner):
+ # EXTENDS 'account_edi_ubl_cii'
+ vals_list = super()._get_partner_party_legal_entity_vals_list(partner)
+
+ for vals in vals_list:
+ if not partner.vat and partner.company_registry:
+ vals['company_id'] = partner.company_registry
+
+ return vals_list
+
+ def _export_invoice_vals(self, invoice):
+ # EXTENDS 'account_edi_ubl_cii'
+ vals = super()._export_invoice_vals(invoice)
+
+ vals['vals'].update({
+ 'customization_id': 'urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1',
+ 'tax_currency_code': 'RON',
+ })
+
+ return vals
+
+ def _export_invoice_constraints(self, invoice, vals):
+ # EXTENDS 'account_edi_ubl_cii'
+ constraints = super()._export_invoice_constraints(invoice, vals)
+
+ for partner_type in ('supplier', 'customer'):
+ partner = vals[partner_type]
+
+ constraints.update({
+ f"ciusro_{partner_type}_city_required": self._check_required_fields(partner, 'city'),
+ f"ciusro_{partner_type}_street_required": self._check_required_fields(partner, 'street'),
+ f"ciusro_{partner_type}_state_id_required": self._check_required_fields(partner, 'state_id'),
+ })
+
+ if not partner.vat and not partner.company_registry:
+ constraints[f"ciusro_{partner_type}_tax_identifier_required"] = _(
+ "The following partner doesn't have a VAT nor Company ID: %s. "
+ "At least one of them is required. "
+ ) % partner.name
+
+ if partner.vat and not partner.vat.startswith(partner.country_code):
+ constraints[f"ciusro_{partner_type}_country_code_vat_required"] = _(
+ "The following partner's doesn't have a country code prefix in their VAT: %s. "
+ ) % partner.name
+
+ if (not partner.vat and partner.company_registry
+ and not partner.company_registry.startswith(partner.country_code)):
+ constraints[f"ciusro_{partner_type}_country_code_company_registry_required"] = _(
+ "The following partner's doesn't have a country code prefix in their Company ID: %s. "
+ ) % partner.name
+
+ if (partner.country_code == 'RO'
+ and partner.state_id
+ and partner.state_id.code == 'B'
+ and partner.city not in SECTOR_RO_CODES):
+ constraints[f"ciusro_{partner_type}_invalid_city_name"] = _(
+ "The following partner's city name is invalid: %s. "
+ "If partner's state is București, the city name must be 'SECTORX', "
+ "where X is a number between 1-6. "
+ ) % partner.name
+
+ return constraints
diff --git a/addons/l10n_ro_edi/models/res_partner.py b/addons/l10n_ro_edi/models/res_partner.py
new file mode 100644
index 00000000000..92014aa43d4
--- /dev/null
+++ b/addons/l10n_ro_edi/models/res_partner.py
@@ -0,0 +1,19 @@
+from odoo import api, fields, models
+
+
+class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ ubl_cii_format = fields.Selection(selection_add=[('ciusro', "CIUSRO")])
+
+ @api.depends('country_code')
+ def _compute_ubl_cii_format(self):
+ super()._compute_ubl_cii_format()
+ for partner in self:
+ if partner.country_code == 'RO':
+ partner.ubl_cii_format = 'ciusro'
+
+ def _get_edi_builder(self):
+ if self.ubl_cii_format == 'ciusro':
+ return self.env['account.edi.xml.ubl_ro']
+ return super()._get_edi_builder()
diff --git a/addons/l10n_ro_edi/tests/__init__.py b/addons/l10n_ro_edi/tests/__init__.py
new file mode 100644
index 00000000000..fe0ebdf600b
--- /dev/null
+++ b/addons/l10n_ro_edi/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_xml_ubl_ro
diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml
new file mode 100644
index 00000000000..42112b09772
--- /dev/null
+++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice.xml
@@ -0,0 +1,166 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ INV/2017/00001
+ 2017-01-01
+ 2017-02-28
+ 380
+ test narration
+ RON
+ RON
+ ref_partner_a
+
+ ref_move
+
+
+ INV_2017_00001.pdf
+
+ ___ignore___
+
+
+
+
+ RO1234567897
+
+ Hudson Construction
+
+
+ Strada Kunst, 3
+ SECTOR1
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Hudson Construction
+ RO1234567897
+
+
+ Hudson Construction
+ +40 123 456 789
+
+
+
+
+
+ RO1234567897
+
+ Roasted Romanian Roller
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Roasted Romanian Roller
+ RO1234567897
+
+
+ Roasted Romanian Roller
+ +40 123 456 780
+
+
+
+
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+
+
+ 30
+ INV/2017/00001
+
+ RO98RNCB1234567890123456
+
+
+
+ 30% Advance End of Following Month
+
+
+ 285.00
+
+ 1500.00
+ 285.00
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+
+ 1500.00
+ 1500.00
+ 1785.00
+ 0.00
+ 1785.00
+
+
+ ___ignore___
+ 1.0
+ 500.00
+
+ product_a
+ product_a
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 500.00
+
+
+
+ ___ignore___
+ 1.0
+ 1000.00
+
+ product_b
+ product_b
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 1000.00
+
+
+
diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml
new file mode 100644
index 00000000000..c42e19db678
--- /dev/null
+++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_invoice_different_currency.xml
@@ -0,0 +1,169 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ INV/2017/00001
+ 2017-01-01
+ 2017-02-28
+ 380
+ test narration
+ FUS
+ RON
+ ref_partner_a
+
+ ref_move
+
+
+ INV_2017_00001.pdf
+
+ ___ignore___
+
+
+
+
+ RO1234567897
+
+ Hudson Construction
+
+
+ Strada Kunst, 3
+ SECTOR1
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Hudson Construction
+ RO1234567897
+
+
+ Hudson Construction
+ +40 123 456 789
+
+
+
+
+
+ RO1234567897
+
+ Roasted Romanian Roller
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Roasted Romanian Roller
+ RO1234567897
+
+
+ Roasted Romanian Roller
+ +40 123 456 780
+
+
+
+
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+
+
+ 30
+ INV/2017/00001
+
+ RO98RNCB1234567890123456
+
+
+
+ 30% Advance End of Following Month
+
+
+ 285.00
+
+ 1500.00
+ 285.00
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+
+ 285.00
+
+
+ 1500.00
+ 1500.00
+ 1785.00
+ 0.00
+ 1785.00
+
+
+ ___ignore___
+ 1.0
+ 500.00
+
+ product_a
+ product_a
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 500.00
+
+
+
+ ___ignore___
+ 1.0
+ 1000.00
+
+ product_b
+ product_b
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 1000.00
+
+
+
diff --git a/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml
new file mode 100644
index 00000000000..e2a7fcf3192
--- /dev/null
+++ b/addons/l10n_ro_edi/tests/test_files/from_odoo/ciusro_out_refund.xml
@@ -0,0 +1,165 @@
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1
+ urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
+ RINV/2017/00001
+ 2017-01-01
+ 381
+ test narration
+ RON
+ RON
+ ref_partner_a
+
+ ref_move
+
+
+ RINV_2017_00001.pdf
+
+ ___ignore___
+
+
+
+
+ RO1234567897
+
+ Hudson Construction
+
+
+ Strada Kunst, 3
+ SECTOR1
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Hudson Construction
+ RO1234567897
+
+
+ Hudson Construction
+ +40 123 456 789
+
+
+
+
+
+ RO1234567897
+
+ Roasted Romanian Roller
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+ RO1234567897
+
+ VAT
+
+
+
+ Roasted Romanian Roller
+ RO1234567897
+
+
+ Roasted Romanian Roller
+ +40 123 456 780
+
+
+
+
+
+
+ Rolling Roast, 88
+ SECTOR3
+ 010101
+ RO-B
+
+ RO
+
+
+
+
+
+ 30
+ RINV/2017/00001
+
+ RO98RNCB1234567890123456
+
+
+
+ 30% Advance End of Following Month
+
+
+ 285.00
+
+ 1500.00
+ 285.00
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+
+ 1500.00
+ 1500.00
+ 1785.00
+ 0.00
+ 1785.00
+
+
+ ___ignore___
+ 1.0
+ 500.00
+
+ product_a
+ product_a
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 500.00
+
+
+
+ ___ignore___
+ 1.0
+ 1000.00
+
+ product_b
+ product_b
+
+ S
+ 19.0
+
+ VAT
+
+
+
+
+ 1000.00
+
+
+
diff --git a/addons/l10n_ro_edi/tests/test_xml_ubl_ro.py b/addons/l10n_ro_edi/tests/test_xml_ubl_ro.py
new file mode 100644
index 00000000000..84e77e978db
--- /dev/null
+++ b/addons/l10n_ro_edi/tests/test_xml_ubl_ro.py
@@ -0,0 +1,137 @@
+from odoo import Command
+from odoo.addons.l10n_account_edi_ubl_cii_tests.tests.common import TestUBLCommon
+from odoo.exceptions import UserError
+from odoo.tests import tagged
+
+
+@tagged('post_install_l10n', 'post_install', '-at_install')
+class TestUBLRO(TestUBLCommon):
+
+ @classmethod
+ def setUpClass(cls, chart_template_ref="ro"):
+ super().setUpClass(chart_template_ref=chart_template_ref)
+ cls.company_data['company'].write({
+ 'country_id': cls.env.ref('base.ro').id,
+ 'state_id': cls.env.ref('base.RO_B').id,
+ 'name': 'Hudson Construction',
+ 'city': 'SECTOR1',
+ 'zip': '010101',
+ 'vat': 'RO1234567897',
+ 'phone': '+40 123 456 789',
+ 'street': "Strada Kunst, 3",
+ 'invoice_is_ubl_cii': True,
+ })
+
+ cls.currency_data['currency'] = cls.env.ref('base.RON')
+
+ cls.env['res.partner.bank'].create({
+ 'acc_type': 'iban',
+ 'partner_id': cls.company_data['company'].partner_id.id,
+ 'acc_number': 'RO98RNCB1234567890123456',
+ })
+
+ cls.partner_a = cls.env['res.partner'].create({
+ 'country_id': cls.env.ref('base.ro').id,
+ 'state_id': cls.env.ref('base.RO_B').id,
+ 'name': 'Roasted Romanian Roller',
+ 'city': 'SECTOR3',
+ 'zip': '010101',
+ 'vat': 'RO1234567897',
+ 'phone': '+40 123 456 780',
+ 'street': "Rolling Roast, 88",
+ 'bank_ids': [(0, 0, {'acc_number': 'RO98RNCB1234567890123456'})],
+ 'ref': 'ref_partner_a',
+ })
+
+ cls.tax_19 = cls.env['account.tax'].create({
+ 'name': 'tax_19',
+ 'amount_type': 'percent',
+ 'amount': 19,
+ 'type_tax_use': 'sale',
+ 'country_id': cls.env.ref('base.ro').id,
+ })
+
+ ####################################################
+ # Test export - import
+ ####################################################
+
+ def create_move(self, move_type, send=True):
+ return self._generate_move(
+ self.env.company.partner_id,
+ self.partner_a,
+ send=send,
+ move_type=move_type,
+ invoice_line_ids=[
+ {
+ 'product_id': self.product_a.id,
+ 'price_unit': 500.0,
+ 'tax_ids': [Command.set(self.tax_19.ids)],
+ },
+ {
+ 'product_id': self.product_b.id,
+ 'price_unit': 1000.0,
+ 'tax_ids': [Command.set(self.tax_19.ids)],
+ },
+ ],
+ )
+
+ def get_attachment(self, move):
+ self.assertTrue(move.ubl_cii_xml_id)
+ self.assertEqual(move.ubl_cii_xml_id.name[-11:], "cius_ro.xml")
+ return move.ubl_cii_xml_id
+
+ def test_export_invoice(self):
+ invoice = self.create_move("out_invoice")
+ attachment = self.get_attachment(invoice)
+ self._assert_invoice_attachment(attachment, xpaths=None, expected_file_path='from_odoo/ciusro_out_invoice.xml')
+
+ def test_export_credit_note(self):
+ refund = self.create_move("out_refund")
+ attachment = self.get_attachment(refund)
+ self._assert_invoice_attachment(attachment, xpaths=None, expected_file_path='from_odoo/ciusro_out_refund.xml')
+
+ def test_export_invoice_different_currency(self):
+ self.currency_data['currency'] = self.env.ref('base.USD')
+ invoice = self.create_move("out_invoice")
+ attachment = self.get_attachment(invoice)
+ self._assert_invoice_attachment(attachment, xpaths=None, expected_file_path='from_odoo/ciusro_out_invoice_different_currency.xml')
+ self.currency_data['currency'] = self.env.ref('base.RON')
+
+ def test_export_no_vat_but_have_company_id_without_prefix(self):
+ self.company_data['company'].write({
+ 'vat': None,
+ 'company_registry': '1234567897',
+ })
+ invoice = self.create_move("out_invoice", send=False)
+ with self.assertRaisesRegex(UserError, "doesn't have a country code prefix in their Company ID"):
+ invoice._generate_pdf_and_send_invoice(self.move_template, from_cron=False, allow_fallback_pdf=False)
+
+ def test_export_no_vat_but_have_company_id_with_prefix(self):
+ self.company_data['company'].write({
+ 'vat': None,
+ 'company_registry': 'RO1234567897',
+ })
+ invoice = self.create_move("out_invoice")
+ attachment = self.get_attachment(invoice)
+ self._assert_invoice_attachment(attachment, xpaths=None, expected_file_path='from_odoo/ciusro_out_invoice.xml')
+
+ def test_export_vat_without_prefix(self):
+ self.company_data['company'].vat = '1234567897'
+ invoice = self.create_move("out_invoice", send=False)
+ with self.assertRaisesRegex(UserError, "doesn't have a country code prefix in their VAT"):
+ invoice._generate_pdf_and_send_invoice(self.move_template, from_cron=False, allow_fallback_pdf=False)
+
+ def test_export_constraints(self):
+ self.company_data['company'].company_registry = None
+ for required_field in ('city', 'street', 'state_id', 'vat'):
+ prev_val = self.company_data["company"][required_field]
+ self.company_data["company"][required_field] = None
+ invoice = self.create_move("out_invoice", send=False)
+ with self.assertRaisesRegex(UserError, "required"):
+ invoice._generate_pdf_and_send_invoice(self.move_template, from_cron=False, allow_fallback_pdf=False)
+ self.company_data["company"][required_field] = prev_val
+
+ self.company_data["company"].city = "Bucharest"
+ invoice = self.create_move("out_invoice", send=False)
+ with self.assertRaisesRegex(UserError, "city name must be 'SECTORX'"):
+ invoice._generate_pdf_and_send_invoice(self.move_template, from_cron=False, allow_fallback_pdf=False)