From eaf5d86fe74f7e1088addfbd17d5c89773a592fc Mon Sep 17 00:00:00 2001 From: oco-odoo Date: Wed, 7 Apr 2021 12:44:15 +0000 Subject: [PATCH] [FIX] base_vat: patch orm limitation https://github.com/odoo/odoo/pull/68253 fixed a bug in check_vat that caused it not to run any check when called on a partner with no country. However, doing this caused another issue because of an ORM limitation: when writing vat and country_id with a single write() on the res.company, two distinct write are triggered on the related res.partner, one for each field. Both those write trigger the check_vat constraint. Depending on the order in which the keys of the dictionnary passed to res.company's write were ordered, country_id could or could not be written before vat. If vat was written first and did not start with a country code, the write() on res.partner failed the constraint, because country_id wasn't set yet. This was wrong, but used to pass as there was no country_id on the partner, before https://github.com/odoo/odoo/pull/68253 fixed that. To circumvent the issue, we now allow entering any vat number without performing any check if it does not start with a country code and no country_id is set on the partner. closes odoo/odoo#69243 X-original-commit: 7036b671228fdb5986b4f62a610a2e4d4132b8b1 Signed-off-by: Laurent Smet Signed-off-by: oco-odoo --- addons/base_vat/models/res_partner.py | 27 ++++++++++++++++------ addons/base_vat/tests/test_validate_ruc.py | 6 ++--- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/addons/base_vat/models/res_partner.py b/addons/base_vat/models/res_partner.py index 9c78f6ebe4e..936ba3596ae 100644 --- a/addons/base_vat/models/res_partner.py +++ b/addons/base_vat/models/res_partner.py @@ -142,7 +142,7 @@ class ResPartner(models.Model): def check_vat(self): for partner in self: country = partner.commercial_partner_id.country_id - if partner.vat and not self._run_vat_test(partner.vat, country): + if partner.vat and self._run_vat_test(partner.vat, country) is False: partner_label = _("partner [%s]", partner.name) msg = partner._build_vat_error_message(country and country.code.lower() or None, partner.vat, partner_label) raise ValidationError(msg) @@ -158,7 +158,9 @@ class ResPartner(models.Model): :param default_country: a res.country object :return: The country code (in lower case) of the country the VAT number - was validated for, if it was validated. Else, False. + was validated for, if it was validated. False if it could not be validated + against the provided or guessed country. None if no country was available + for the check, and no conclusion could be made with certainty. """ # Get company if self.env.context.get('company_id'): @@ -173,16 +175,27 @@ class ResPartner(models.Model): else: check_func = self.simple_vat_check + check_result = None + # First check with country code as prefix of the TIN vat_country_code, vat_number_split = self._split_vat(vat_number) - if check_func(vat_country_code, vat_number_split): - return vat_country_code + vat_guessed_country = self.env['res.country'].search([('code', '=', vat_country_code.upper())]) + if vat_guessed_country: + check_result = check_func(vat_country_code, vat_number_split) + if check_result: + return vat_country_code # If it fails, check with default_country (if it exists) - if default_country and check_func(default_country.code.lower(), vat_number): - return default_country.code.lower() + if default_country: + check_result = check_func(default_country.code.lower(), vat_number) + if check_result: + return default_country.code.lower() - return False + # We allow any number if it doesn't start with a country code and the partner has no country. + # This is necessary to support an ORM limitation: setting vat and country_id together on a company + # triggers two distinct write on res.partner, one for each field, both triggering this constraint. + # If vat is set before country_id, the constraint must not break. + return check_result @api.model def _build_vat_error_message(self, country_code, wrong_vat, record_label): diff --git a/addons/base_vat/tests/test_validate_ruc.py b/addons/base_vat/tests/test_validate_ruc.py index d7f3eccbbb7..3a0f8e87b1d 100644 --- a/addons/base_vat/tests/test_validate_ruc.py +++ b/addons/base_vat/tests/test_validate_ruc.py @@ -81,9 +81,9 @@ class TestStructure(TransactionCase): 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}) + # If no country can be guessed: VAT number should always be considered valid + # (for technical reasons due to ORM and res.company making related fields towards res.partner for country_id and vat) + test_partner.write({'vat': '0477472701', 'country_id': None}) @tagged('-standard', 'external')