diff options
| author | qdp-odoo <qdp@odoo.com> | 2016-12-28 11:26:06 +0100 |
|---|---|---|
| committer | qdp-odoo <qdp@odoo.com> | 2016-12-28 11:26:06 +0100 |
| commit | 0dc4e13f145a449395aa82cfe75dfbe09afb5455 (patch) | |
| tree | 84438d6c8d9d98f8b54a7937baab43ed4222ab51 /addons/base_address_extended/models | |
| parent | 4dd27bba346e50f40769d1412fbca0b5f65bb5a6 (diff) | |
[ADD] base_address_extended: add module to take care of multiple fields inside the 'street' fields defined in base
Diffstat (limited to 'addons/base_address_extended/models')
| -rw-r--r-- | addons/base_address_extended/models/__init__.py | 4 | ||||
| -rw-r--r-- | addons/base_address_extended/models/base_address_extended.py | 140 |
2 files changed, 144 insertions, 0 deletions
diff --git a/addons/base_address_extended/models/__init__.py b/addons/base_address_extended/models/__init__.py new file mode 100644 index 00000000000..0e2d5d905fa --- /dev/null +++ b/addons/base_address_extended/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import base_address_extended diff --git a/addons/base_address_extended/models/base_address_extended.py b/addons/base_address_extended/models/base_address_extended.py new file mode 100644 index 00000000000..8e599c08402 --- /dev/null +++ b/addons/base_address_extended/models/base_address_extended.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import re + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +STREET_FIELDS = ('street_name', 'street_number', 'street_number2') + + +class ResCountry(models.Model): + _inherit = 'res.country' + + street_format = fields.Text( + help="Format to use for streets belonging to this country.\n\n" + "You can use the python-style string pattern with all the fields of the street " + "(for example, use '%(street_name)s, %(street_number)s' if you want to display " + "the street name, followed by a comma and the house number)" + "\n%(street_name)s: the name of the street" + "\n%(street_number)s: the house number" + "\n%(street_number2)s: the door number", + default='%(street_number)s/%(street_number2)s %(street_name)s', required=True) + +class Partner(models.Model): + _inherit = ['res.partner'] + _name = 'res.partner' + + street_name = fields.Char('Street Name', compute='_split_street', + inverse='_set_street', store=True) + street_number = fields.Char('House Number', compute='_split_street', + inverse='_set_street', store=True) + street_number2 = fields.Char('Door Number', compute='_split_street', + inverse='_set_street', store=True) + + def get_street_fields(self): + """Returns the fields that can be used in a street format. + Overwrite this function if you want to add your own fields.""" + return STREET_FIELDS + + @api.multi + def _set_street(self): + """Updates the street field. + Writes the `street` field on the partners when one of the sub-fields in STREET_FIELDS + has been touched""" + street_fields = self.get_street_fields() + for partner in self: + street_format = (partner.country_id.street_format or + '%(street_number)s/%(street_number2)s %(street_name)s') + previous_field = None + previous_pos = 0 + street_value = "" + separator = "" + # iter on fields in street_format, detected as '%(<field_name>)s' + for re_match in re.finditer(r'%\(\w+\)s', street_format): + # [2:-2] is used to remove the extra chars '%(' and ')s' + field_name = re_match.group()[2:-2] + field_pos = re_match.start() + if field_name not in street_fields: + raise UserError(_("Unrecognized field %s in street format.") % field_name) + if not previous_field: + # first iteration: add heading chars in street_format + if partner[field_name]: + street_value += street_format[0:field_pos] + partner[field_name] + else: + # get the substring between 2 fields, to be used as separator + separator = street_format[previous_pos:field_pos] + if street_value and partner[field_name]: + street_value += separator + if partner[field_name]: + street_value += partner[field_name] + previous_field = field_name + previous_pos = re_match.end() + + # add trailing chars in street_format + street_value += street_format[previous_pos:] + + # /!\ Note that we must use a sql query to bypass the orm as it would call _split_street() + # that would try to set the fields we just modified. + self._cr.execute('UPDATE res_partner SET street = %s WHERE ID = %s', (street_value, partner.id)) + #invalidate the cache for the field we manually set + self.invalidate_cache(['street'], [partner.id]) + + @api.multi + @api.depends('street') + def _split_street(self): + """Splits street value into sub-fields. + Recomputes the fields of STREET_FIELDS when `street` of a partner is updated""" + street_fields = self.get_street_fields() + for partner in self: + if not partner.street: + partner.street_name = '' + partner.street_number = '' + partner.street_number2 = '' + continue + + 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 '%(<field_name>)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 + # 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(): + partner[k] = v |
