From 72b7fb15db4df1a3336bc6e90fe60f49877c52f8 Mon Sep 17 00:00:00 2001 From: oco-odoo Date: Tue, 23 Mar 2021 15:29:47 +0000 Subject: [FIX] base_vat: Don't always pass VAT check when validating the VAT of a partner without country_id Before this, when making a partner without any country_id, any VAT could be set to it, which was inconsistent with the module's purpose. closes odoo/odoo#68492 X-original-commit: 4c962437bd59a1e9302d8034e8870880994eb713 Related: odoo/enterprise#17358 Signed-off-by: Cedric Snauwaert (csn) Signed-off-by: oco-odoo --- addons/base_vat/models/res_partner.py | 7 ++-- addons/base_vat/tests/test_validate_ruc.py | 58 ++++++++++++++++++++++++-- addons/l10n_be_edi/test_xml_file/efff_test.xml | 6 +-- addons/l10n_be_edi/tests/test_ubl.py | 2 +- odoo/addons/base/tests/test_base.py | 8 ++-- 5 files changed, 66 insertions(+), 15 deletions(-) diff --git a/addons/base_vat/models/res_partner.py b/addons/base_vat/models/res_partner.py index 2dcbee9d8cb..35ce8f0e4d8 100644 --- a/addons/base_vat/models/res_partner.py +++ b/addons/base_vat/models/res_partner.py @@ -159,10 +159,9 @@ class ResPartner(models.Model): if not check_func(vat_country, vat_number): #if fails, check with country code from country country_code = partner.commercial_partner_id.country_id.code - if country_code: - if not check_func(country_code.lower(), partner.vat): - msg = partner._construct_constraint_msg(country_code.lower()) - raise ValidationError(msg) + if not country_code or not check_func(country_code.lower(), partner.vat): + msg = partner._construct_constraint_msg(country_code.lower() if country_code else None) + raise ValidationError(msg) def _construct_constraint_msg(self, country_code): self.ensure_one() diff --git a/addons/base_vat/tests/test_validate_ruc.py b/addons/base_vat/tests/test_validate_ruc.py index c51433da8ed..b7a3be3fbf6 100644 --- a/addons/base_vat/tests/test_validate_ruc.py +++ b/addons/base_vat/tests/test_validate_ruc.py @@ -55,9 +55,61 @@ class TestStructure(SavepointCase): # reactivate it and correct the vat number with patch('odoo.addons.base_vat.models.res_partner.check_vies', type(self)._vies_check_func): self.env.user.company_id.vat_check_vies = True - with self.assertRaises(ValidationError), self.env.cr.savepoint(): - company.vat = "BE0987654321" # VIES refused, don't fallback on other check - company.vat = "BE0477472701" + + def test_vat_validation(self): + """ Tests VAT validation (both successes and failures), with the different country + detection cases possible. + """ + # Disable VIES; syntactic verification is enough for this test case + self.env.user.company_id.vat_check_vies = False + + test_partner =self.env['res.partner'].create({'name': "John Dex"}) + + # VAT starting with country code: use the starting country code + test_partner.write({'vat': 'BE0477472701', 'country_id': self.env.ref('base.fr').id}) + test_partner.write({'vat': 'BE0477472701', 'country_id': None}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': 'BE42', 'country_id': self.env.ref('base.fr').id}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': 'BE42', 'country_id': None}) + + # No country code in VAT: use the partner's country + test_partner.write({'vat': '0477472701', 'country_id': self.env.ref('base.be').id}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': '42', 'country_id': self.env.ref('base.be').id}) + + # If no country can be guessed: VAT number cannot be validated + with self.assertRaises(ValidationError): + test_partner.write({'vat': '0477472701', 'country_id': None}) + + def test_vat_syntactic_validation(self): + """ Tests VAT validation (both successes and failures), with the different country + detection cases possible. + """ + test_partner =self.env['res.partner'].create({'name': "John Dex"}) + + # VAT starting with country code: use the starting country code + test_partner.write({'vat': 'BE0477472701', 'country_id': self.env.ref('base.fr').id}) + test_partner.write({'vat': 'BE0477472701', 'country_id': None}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': 'BE42', 'country_id': self.env.ref('base.fr').id}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': 'BE42', 'country_id': None}) + + # No country code in VAT: use the partner's country + test_partner.write({'vat': '0477472701', 'country_id': self.env.ref('base.be').id}) + + with self.assertRaises(ValidationError): + test_partner.write({'vat': '42', 'country_id': self.env.ref('base.be').id}) + + # If no country can be guessed: VAT number cannot be validated + with self.assertRaises(ValidationError): + test_partner.write({'vat': '0477472701', 'country_id': None}) @tagged('-standard', 'external') diff --git a/addons/l10n_be_edi/test_xml_file/efff_test.xml b/addons/l10n_be_edi/test_xml_file/efff_test.xml index 625bc32737e..de7bbed9ddb 100644 --- a/addons/l10n_be_edi/test_xml_file/efff_test.xml +++ b/addons/l10n_be_edi/test_xml_file/efff_test.xml @@ -1,4 +1,4 @@ - + 2.0 1.0 @@ -13,9 +13,9 @@ 1 - BE0123456789 + BE0477472701 - 123456789 + 477472701 The best supplier diff --git a/addons/l10n_be_edi/tests/test_ubl.py b/addons/l10n_be_edi/tests/test_ubl.py index 388155ac21c..d9632de96e9 100644 --- a/addons/l10n_be_edi/tests/test_ubl.py +++ b/addons/l10n_be_edi/tests/test_ubl.py @@ -7,7 +7,7 @@ class TestUBL(AccountEdiTestCommon): def setUpClass(cls, chart_template_ref='l10n_be.l10nbe_chart_template', edi_format_ref='l10n_be_edi.edi_efff_1'): super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref) - cls.partner_a.vat = 'BE0123456789' + cls.partner_a.vat = 'BE0477472701' def test_invoice_edi_xml(self): invoice = self._create_empty_vendor_bill() diff --git a/odoo/addons/base/tests/test_base.py b/odoo/addons/base/tests/test_base.py index eef6c749095..f28d1f7c2e5 100644 --- a/odoo/addons/base/tests/test_base.py +++ b/odoo/addons/base/tests/test_base.py @@ -196,7 +196,7 @@ class TestBase(TransactionCase): self.assertEqual(p1.street, p1street, 'Address fields must not be synced after turning sync off') self.assertNotEqual(ghoststep.street, p1street, 'Parent address must never be touched') - # turn on sync again + # turn on sync again p1.write({'type': 'contact'}) self.assertEqual(p1.street, ghoststep.street, 'Address fields must be synced again') self.assertEqual(p1.phone, p1phone, 'Phone should be preserved after address sync') @@ -383,12 +383,12 @@ class TestBase(TransactionCase): for p in (p0, p1, p11, p2, p3): self.assertEqual(p.commercial_partner_id, sunhelm, 'Incorrect commercial entity resolution') self.assertEqual(p.vat, sunhelm.vat, 'Commercial fields must be automatically synced') - sunhelmvat = 'BE0123456789' + sunhelmvat = 'BE0123456749' sunhelm.write({'vat': sunhelmvat}) for p in (p0, p1, p11, p2, p3): self.assertEqual(p.vat, sunhelmvat, 'Commercial fields must be automatically and recursively synced') - p1vat = 'BE0987654321' + p1vat = 'BE0987654394' p1.write({'vat': p1vat}) for p in (sunhelm, p0, p11, p2, p3): self.assertEqual(p.vat, sunhelmvat, 'Sync to children should only work downstream and on commercial entities') @@ -401,7 +401,7 @@ class TestBase(TransactionCase): self.assertEqual(p1.commercial_partner_id, p1, 'Incorrect commercial entity resolution after setting is_company') # writing on parent should not touch child commercial entities - sunhelmvat2 = 'BE0112233445' + sunhelmvat2 = 'BE0112233453' sunhelm.write({'vat': sunhelmvat2}) self.assertEqual(p1.vat, p1vat, 'Setting is_company should stop auto-sync of commercial fields') self.assertEqual(p0.vat, sunhelmvat2, 'Commercial fields must be automatically synced') -- cgit v1.2.3