From 948a558ee036bb346e5cdfc245426ad8780e0863 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 28 Nov 2011 17:21:27 +0100 Subject: [PATCH] [IMP] base_vat: add option to force online VIES check for EU VAT numbers bzr revid: odo@openerp.com-20111128162127-a0e2n0c09noga0rq --- addons/base_vat/__init__.py | 1 + addons/base_vat/__openerp__.py | 15 +++++++++++ addons/base_vat/base_vat.py | 45 ++++++++++++++++++++++--------- addons/base_vat/base_vat_view.xml | 21 +++++++++++---- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/addons/base_vat/__init__.py b/addons/base_vat/__init__.py index 43dbd0c1418..1d7c143b7dc 100644 --- a/addons/base_vat/__init__.py +++ b/addons/base_vat/__init__.py @@ -19,6 +19,7 @@ # ############################################################################## +import res_company import base_vat # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/base_vat/__openerp__.py b/addons/base_vat/__openerp__.py index 5f7c1d2d86d..147eb47b9e2 100644 --- a/addons/base_vat/__openerp__.py +++ b/addons/base_vat/__openerp__.py @@ -33,6 +33,21 @@ be validated for all supported countries. The country is inferred from the 2-letter country code that prefixes the VAT number, e.g. ``BE0477472701`` will be validated using the Belgian rules. +There are two different levels of VAT number validation: + + * By default, a simple off-line check is performed using the known validation + rules for the country, usually a simple check digit. This is quick and + always available, but allows numbers that are perhaps not truly allocated, + or not valid anymore. + * When the "VAT VIES Check" option is enabled (in the configuration of the user's + Company), VAT numbers will be instead submitted to the online EU VIES + database, which will truly verify that the number is valid and currently + allocated to a EU company. This is a little bit slower than the simple + off-line check, requires an Internet connection, and may not be available + all the time. If the service is not available or does not support the + requested country (e.g. for non-EU countries), a simple check will be performed + instead. + Supported countries currently include EU countries, and a few non-EU countries such as Chile, Colombia, Mexico, Norway or Russia. For unsupported countries, only the country code will be validated. diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index ba858d10e64..02471f67442 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -61,27 +61,48 @@ class res_partner(osv.osv): vat_country, vat_number = vat[:2].lower(), vat[2:].replace(' ', '') return vat_country, vat_number - def check_vat(self, cr, uid, ids, context=None): + def simple_vat_check(self, cr, uid, country_code, vat_number, context=None): ''' Check the VAT number depending of the country. http://sima-pc.com/nif.php ''' - country_obj = self.pool.get('res.country') + check_func_name = 'check_vat_' + country_code + check_func = getattr(self, check_func_name, None) or \ + getattr(vatnumber, check_func_name, None) + if not check_func: + # No VAT validation available, default to check that the country code exists + res_country = self.pool.get('res.country') + return bool(res_country.search(cr, uid, [('code', '=ilike', country_code)], context=context)) + return check_func(vat_number) + + def vies_vat_check(self, cr, uid, country_code, vat_number, context=None): + try: + # Validate against VAT Information Exchange System (VIES) + # see also http://ec.europa.eu/taxation_customs/vies/ + return vatnumber.check_vies(country_code.upper()+vat_number) + 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. + return self.simple_vat_check(cr, uid, country_code, vat_number, context=context) + + def check_vat(self, cr, uid, ids, context=None): + user_company = self.pool.get('res.users').browse(cr, uid, uid).company_id + if user_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 + for partner in self.browse(cr, uid, ids, context=context): if not partner.vat: continue vat_country, vat_number = self._split_vat(partner.vat) - check_func_name = 'check_vat_' + vat_country - check_func = getattr(self, check_func_name, None) or \ - getattr(vatnumber, check_func_name, None) - if not check_func: - # No VAT validation available, default to check that the country code - # exists. - if country_obj.search(cr, uid, [('code', 'ilike', vat_country)], context=context): - continue - # Country code not found, considered invalid + if not check_func(cr, uid, vat_country, vat_number, context=context): return False - return check_func(vat_number) return True def vat_change(self, cr, uid, ids, value, context=None): diff --git a/addons/base_vat/base_vat_view.xml b/addons/base_vat/base_vat_view.xml index 69a1870ea72..fa53906d667 100644 --- a/addons/base_vat/base_vat_view.xml +++ b/addons/base_vat/base_vat_view.xml @@ -7,12 +7,23 @@ res.partner - - - - - + + + + + + + + + + res.company.form.vat.inherit + res.company + + + + +