From ca14f232e0ec9e794ec1ef2b2c160579b2c89a6d Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Mon, 23 Jul 2018 16:23:17 +0200 Subject: [PATCH] [FIX] base_vat_autocomplete: Create contact using VAT number Let's install base_vat_autocomplete and base_address_extended When creating a contact with a VAT number, the street was not formated by the autocomplete in a correct way because the function checkVat all the time returns the street with the following format: '%(street_name)s, %(street_number)s/%(street_number2)s' and this function doesn't take the street format of the country into account. So the function _split_street tried to split the street into street_name, street_number, street_number2 with the street_format of the partner but the street was not well formated by checkVat. opw:1867491 --- .../models/base_address_extended.py | 78 ++++++++++--------- .../models/res_partner.py | 5 +- odoo/addons/base/res/res_partner.py | 3 + 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/addons/base_address_extended/models/base_address_extended.py b/addons/base_address_extended/models/base_address_extended.py index 07125811aed..fe5ff88019b 100644 --- a/addons/base_address_extended/models/base_address_extended.py +++ b/addons/base_address_extended/models/base_address_extended.py @@ -81,6 +81,47 @@ class Partner(models.Model): #invalidate the cache for the field we manually set self.invalidate_cache(['street'], [partner.id]) + def _split_street_with_params(self, street_raw, street_format): + street_fields = self.get_street_fields() + vals = {} + previous_pos = 0 + field_name = None + # iter on fields in street_format, detected as '%()s' + for re_match in re.finditer(r'%\(\w+\)s', street_format): + field_pos = re_match.start() + if not field_name: + #first iteration: remove the heading chars + street_raw = street_raw[field_pos:] + + # get the substring between 2 fields, to be used as separator + separator = street_format[previous_pos:field_pos] + field_value = None + if separator and field_name: + #maxsplit set to 1 to unpack only the first element and let the rest untouched + tmp = street_raw.split(separator, 1) + if len(tmp) == 2: + field_value, street_raw = tmp + vals[field_name] = field_value + if field_value or not field_name: + # select next field to find (first pass OR field found) + # [2:-2] is used to remove the extra chars '%(' and ')s' + field_name = re_match.group()[2:-2] + else: + # value not found: keep looking for the same field + pass + if field_name not in street_fields: + raise UserError(_("Unrecognized field %s in street format.") % field_name) + previous_pos = re_match.end() + + # last field value is what remains in street_raw minus trailing chars in street_format + trailing_chars = street_format[previous_pos:] + if trailing_chars and street_raw.endswith(trailing_chars): + vals[field_name] = street_raw[:-len(trailing_chars)] + else: + vals[field_name] = street_raw + return vals + + @api.multi @api.depends('street') def _split_street(self): @@ -95,43 +136,8 @@ class Partner(models.Model): street_format = (partner.country_id.street_format or '%(street_number)s/%(street_number2)s %(street_name)s') - vals = {} - previous_pos = 0 street_raw = partner.street - field_name = None - # iter on fields in street_format, detected as '%()s' - for re_match in re.finditer(r'%\(\w+\)s', street_format): - field_pos = re_match.start() - if not field_name: - #first iteration: remove the heading chars - street_raw = street_raw[field_pos:] - - # get the substring between 2 fields, to be used as separator - separator = street_format[previous_pos:field_pos] - field_value = None - if separator and field_name: - #maxsplit set to 1 to unpack only the first element and let the rest untouched - tmp = street_raw.split(separator, 1) - if len(tmp) == 2: - field_value, street_raw = tmp - vals[field_name] = field_value - if field_value or not field_name: - # select next field to find (first pass OR field found) - # [2:-2] is used to remove the extra chars '%(' and ')s' - field_name = re_match.group()[2:-2] - else: - # value not found: keep looking for the same field - pass - if field_name not in street_fields: - raise UserError(_("Unrecognized field %s in street format.") % field_name) - previous_pos = re_match.end() - - # last field value is what remains in street_raw minus trailing chars in street_format - trailing_chars = street_format[previous_pos:] - if trailing_chars and street_raw.endswith(trailing_chars): - vals[field_name] = street_raw[:-len(trailing_chars)] - else: - vals[field_name] = street_raw + vals = self._split_street_with_params(street_raw, street_format) # assign the values to the fields # /!\ Note that a write(vals) would cause a recursion since it would bypass the cache for k, v in vals.items(): diff --git a/addons/base_vat_autocomplete/models/res_partner.py b/addons/base_vat_autocomplete/models/res_partner.py index edff2cae921..85fca36c2c0 100644 --- a/addons/base_vat_autocomplete/models/res_partner.py +++ b/addons/base_vat_autocomplete/models/res_partner.py @@ -54,7 +54,7 @@ class ResPartner(models.Model): for partner in self: # If a field is non set in this algorithm # wipe it anyway - non_set_address_fields = set(['street', 'street2', 'city', 'zip', 'state_id', 'country_id']) + non_set_address_fields = set(['street2', 'city', 'zip', 'state_id', 'country_id']) if not partner.vat: return {} if len(partner.vat) > 5 and partner.vat[:2].lower() in stdnum_vat.country_codes: @@ -84,7 +84,8 @@ class ResPartner(models.Model): if len(lines) == 1: lines = [x.strip() for x in lines[0].split(' ') if x] - _set_address_field(partner, 'street', lines.pop(0)) + vals = partner._split_street_with_params(', '.join(lines.pop(0).rsplit(' ', 1)), '%(street_name)s, %(street_number)s/%(street_number2)s') + partner.update(vals) if len(lines) > 0: res = _check_city(lines, result['countryCode']) diff --git a/odoo/addons/base/res/res_partner.py b/odoo/addons/base/res/res_partner.py index d229a36b585..88161c68e50 100644 --- a/odoo/addons/base/res/res_partner.py +++ b/odoo/addons/base/res/res_partner.py @@ -137,6 +137,9 @@ class Partner(models.Model): def _default_company(self): return self.env['res.company']._company_default_get('res.partner') + def _split_street_with_params(self, street_raw, street_format): + return {'street': street_raw} + name = fields.Char(index=True) display_name = fields.Char(compute='_compute_display_name', store=True, index=True) date = fields.Date(index=True)