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)