From 2deb95b852208a8dbfb9640ac8947533c1ad428b Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 17 Oct 2017 09:49:22 +0200 Subject: [PATCH] [FIX] base_vat, website_sale: Verification of vat number in EU country We have problems when trying to validate our EU VAT report because some vat number are wrongly encoded in Odoo. There are 2 problems: 1) We use vatnumber library to check the validity of the VAT number entered by the user on website. That library removes the following characters '.' and '-' in order to perform the check and thus can return True for a number like 123.123.123.13 or -123-3454-34 And those VAT number are then saved in our database but are rejected by the state as VAT number should only contains alphanumeric character -> Solution: prevent entering vat number with other characters than alphanumeric for users that are located in EUROPE! 2) Usually VAT is prefixed by country code, however some people in europe managed to bypass the system by prefixing their VAT number with CC instead of their country code, CC is consider valid in odoo (it means Country Code) but is not a valid European country code in general, which means that those people that should have pay some tax have not. Which is a huge problem. -> Solution: prevent the use of CC as country code by the user when entering a vatnumber only if the user country is in EUROPE! source: https://en.wikipedia.org/wiki/VAT_identification_number opw:772621 --- addons/base_vat/base_vat.py | 22 ++++++++++++++++++++++ addons/website_sale/controllers/main.py | 2 ++ 2 files changed, 24 insertions(+) diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index 9e1dcba46e4..98a988beae7 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -14,10 +14,17 @@ except ImportError: "Install it to support more countries, for example with `easy_install vatnumber`.") vatnumber = None +from openerp import api from openerp.osv import osv from openerp.tools.misc import ustr from openerp.tools.translate import _ +_eu_country_vat = { + 'GR': 'EL' +} + +_eu_country_vat_inverse = {v: k for k, v in _eu_country_vat.items()} + _ref_vat = { 'at': 'ATU12345675', 'be': 'BE0477472701', @@ -79,6 +86,7 @@ class res_partner(osv.osv): # may have a VATIN starting with "EU" instead of a country code. return True res_country = self.pool.get('res.country') + country_code = _eu_country_vat_inverse.get(country_code, country_code) return bool(res_country.search(cr, uid, [('code', '=ilike', country_code)], context=context)) return check_func(vat_number) @@ -95,6 +103,20 @@ class res_partner(osv.osv): # 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) + @api.model + def fix_eu_vat_number(self, country_id, vat): + in_europe = False + europe = self.env.ref('base.europe') + country = self.env["res.country"].browse(country_id) + if not europe: + europe = self.env["res.country.group"].search([('name', '=', 'Europe')], limit=1) + if europe and country and country.id in europe.country_ids.ids: + vat = re.sub('[^A-Za-z0-9]', '', vat).upper() + country_code = _eu_country_vat.get(country.code, country.code).upper() + if vat[:2] != country_code: + vat = country_code + vat + return vat + 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: diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index e7820976747..44c35ff3c1f 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -569,6 +569,8 @@ class website_sale(http.Controller): # vat validation if data.get("vat") and hasattr(registry["res.partner"], "check_vat"): + if data.get("country_id"): + data["vat"] = registry["res.partner"].fix_eu_vat_number(cr, uid, data.get("country_id"), data.get("vat"), context) if request.website.company_id.vat_check_vies: # force full VIES online check check_func = registry["res.partner"].vies_vat_check