[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 <smetl@users.noreply.github.com> Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user