[IMP] base_vat: add option to force online VIES check for EU VAT numbers

bzr revid: odo@openerp.com-20111128162127-a0e2n0c09noga0rq
This commit is contained in:
Olivier Dony 2011-11-28 17:21:27 +01:00
parent 26962cae9b
commit 948a558ee0
4 changed files with 65 additions and 17 deletions

View File

@ -19,6 +19,7 @@
#
##############################################################################
import res_company
import base_vat
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -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.

View File

@ -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):

View File

@ -7,12 +7,23 @@
<field name="model">res.partner</field>
<field name="inherit_id" ref="account.view_partner_property_form"/>
<field name="arch" type="xml">
<field name="property_account_payable" position="after">
<group colspan="2" col="6">
<field name="vat" on_change="vat_change(vat)" colspan="4" />
<field name="vat_subjected" colspan="1" groups="base.group_extended" />
</group>
<field name="property_account_payable" position="after">
<group colspan="2" col="6">
<field name="vat" on_change="vat_change(vat)" colspan="4" />
<field name="vat_subjected" colspan="1" groups="base.group_extended" />
</group>
</field>
</field>
</record>
<record id="company_form_vat" model="ir.ui.view">
<field name="name">res.company.form.vat.inherit</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<field name="currency_id" position="after">
<field name="vat_check_vies" groups="base.group_extended" />
</field>
</field>
</record>