[FIX] base_vat: not called at all

The function was wrongly imported and used, and it was hidden by a
generic catching of all exceptions.
The return value and some legit exceptions were also badly handled:
* The return value was always thruthy as it returns an object containing
information about the check.
* Exceptions can be raised if the format is not correct. In that case,
we don't want to go to the simple vat check.

Fixes #64897
opw-2451951

closes odoo/odoo#66522

X-original-commit: e711f359fef7ed4c37cb26d3946744e140bf00e0
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
wan
2021-02-19 09:50:24 +00:00
parent 9741ef5ee6
commit 5783642ee4
2 changed files with 46 additions and 19 deletions
+20 -9
View File
@@ -5,11 +5,17 @@ import datetime
import string
import re
import stdnum
from stdnum.eu.vat import check_vies
from stdnum.exceptions import InvalidComponent
import logging
from odoo import api, models, tools, _
from odoo.tools.misc import ustr
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
_eu_country_vat = {
'GR': 'EL'
}
@@ -99,20 +105,24 @@ class ResPartner(models.Model):
def _check_vies(self, vat):
# Store the VIES result in the cache. In case an exception is raised during the request
# (e.g. service unavailable), the fallback on simple_vat_check is not kept in cache.
return stdnum.eu.vat.check_vies(vat)
return check_vies(vat)
@api.model
def vies_vat_check(self, country_code, vat_number):
try:
# Validate against VAT Information Exchange System (VIES)
# see also http://ec.europa.eu/taxation_customs/vies/
return self._check_vies(country_code.upper() + vat_number)
vies_result = self._check_vies(country_code.upper() + vat_number)
return vies_result['valid']
except InvalidComponent:
return False
except Exception:
# see http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
# Fault code may contain INVALID_INPUT, SERVICE_UNAVAILABLE, MS_UNAVAILABLE,
# TIMEOUT or SERVER_BUSY. There is no way we can validate the input
# with VIES if any of these arise, including the first one (it means invalid
# country code or empty VAT number), so we fall back to the simple check.
_logger.exception("Failed VIES VAT check.")
return self.simple_vat_check(country_code, vat_number)
@api.model
@@ -134,17 +144,18 @@ class ResPartner(models.Model):
company = self.env['res.company'].browse(self.env.context['company_id'])
else:
company = self.env.company
if company.vat_check_vies:
# force full VIES online check
check_func = self.vies_vat_check
else:
# quick and partial off-line checksum validation
check_func = self.simple_vat_check
eu_countries = self.env.ref('base.europe').country_ids
for partner in self:
if not partner.vat:
continue
#check with country code as prefix of the TIN
vat_country, vat_number = self._split_vat(partner.vat)
if company.vat_check_vies and partner.commercial_partner_id.country_id in eu_countries:
# force full VIES online check
check_func = self.vies_vat_check
else:
# quick and partial off-line checksum validation
check_func = self.simple_vat_check
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
@@ -183,7 +194,7 @@ class ResPartner(models.Model):
'''
# A new VAT number format in Switzerland has been introduced between 2011 and 2013
# https://www.estv.admin.ch/estv/fr/home/mehrwertsteuer/fachinformationen/steuerpflicht/unternehmens-identifikationsnummer--uid-.html
# The old format "TVA 123456" is not valid since 2014
# The old format "TVA 123456" is not valid since 2014
# Accepted format are: (spaces are ignored)
# CHE#########MWST
# CHE#########TVA
+26 -10
View File
@@ -1,11 +1,20 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from odoo.tests.common import TransactionCase, tagged
from odoo.exceptions import ValidationError
from unittest.mock import patch
from stdnum.eu import vat
import stdnum.eu.vat
class TestStructure(common.TransactionCase):
class TestStructure(TransactionCase):
@classmethod
def setUpClass(cls):
def check_vies(vat_number):
return {'valid': vat_number == 'BE0477472701'}
super().setUpClass()
cls.env.user.company_id.vat_check_vies = False
cls._vies_check_func = check_vies
def test_peru_ruc_format(self):
"""Only values that has the length of 11 will be checked as RUC, that's what we are proving. The second part
@@ -29,7 +38,7 @@ class TestStructure(common.TransactionCase):
def test_parent_validation(self):
"""Test the validation with company and contact"""
# disable the verification to set an invalid vat number
# set an invalid vat number
self.env.user.company_id.vat_check_vies = False
company = self.env["res.partner"].create({
"name": "World Company",
@@ -43,11 +52,18 @@ class TestStructure(common.TransactionCase):
"company_type": "person",
})
def mock_check_vies(vat_number):
""" Fake vatnumber method that will only allow one number """
return vat_number == 'BE0987654321'
# reactivate it and correct the vat number
with patch.object(vat, 'check_vies', mock_check_vies):
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
company.vat = "BE0987654321"
with self.assertRaises(ValidationError), self.env.cr.savepoint():
company.vat = "BE0987654321" # VIES refused, don't fallback on other check
company.vat = "BE0477472701"
@tagged('-standard', 'external')
class TestStructureVIES(TestStructure):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env.user.company_id.vat_check_vies = True
cls._vies_check_func = stdnum.eu.vat.check_vies