diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/base_address_extended/models | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/base_address_extended/models')
| -rw-r--r-- | addons/base_address_extended/models/__init__.py | 6 | ||||
| -rw-r--r-- | addons/base_address_extended/models/res_company.py | 31 | ||||
| -rw-r--r-- | addons/base_address_extended/models/res_country.py | 18 | ||||
| -rw-r--r-- | addons/base_address_extended/models/res_partner.py | 139 |
4 files changed, 194 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 00000000..9af97424 --- /dev/null +++ b/addons/base_address_extended/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import res_company +from . import res_country +from . import res_partner diff --git a/addons/base_address_extended/models/res_company.py b/addons/base_address_extended/models/res_company.py new file mode 100644 index 00000000..e08dfa37 --- /dev/null +++ b/addons/base_address_extended/models/res_company.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class Company(models.Model): + _inherit = 'res.company' + + street_name = fields.Char('Street Name', compute='_compute_address', + inverse='_inverse_street_name') + street_number = fields.Char('House Number', compute='_compute_address', + inverse='_inverse_street_number') + street_number2 = fields.Char('Door Number', compute='_compute_address', + inverse='_inverse_street_number2') + + def _get_company_address_field_names(self): + fields_matching = super(Company, self)._get_company_address_field_names() + return list(set(fields_matching + ['street_name', 'street_number', 'street_number2'])) + + def _inverse_street_name(self): + for company in self: + company.partner_id.street_name = company.street_name + + def _inverse_street_number(self): + for company in self: + company.partner_id.street_number = company.street_number + + def _inverse_street_number2(self): + for company in self: + company.partner_id.street_number2 = company.street_number2 diff --git a/addons/base_address_extended/models/res_country.py b/addons/base_address_extended/models/res_country.py new file mode 100644 index 00000000..38f13f3b --- /dev/null +++ b/addons/base_address_extended/models/res_country.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +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) diff --git a/addons/base_address_extended/models/res_partner.py b/addons/base_address_extended/models/res_partner.py new file mode 100644 index 00000000..87afa90f --- /dev/null +++ b/addons/base_address_extended/models/res_partner.py @@ -0,0 +1,139 @@ +# -*- 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 + + +class Partner(models.Model): + _inherit = ['res.partner'] + + street_name = fields.Char( + 'Street Name', compute='_compute_street_data', inverse='_inverse_street_data', store=True) + street_number = fields.Char( + 'House', compute='_compute_street_data', inverse='_inverse_street_data', store=True) + street_number2 = fields.Char( + 'Door', compute='_compute_street_data', inverse='_inverse_street_data', store=True) + + def _inverse_street_data(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:] + partner.street = street_value + + @api.depends('street') + def _compute_street_data(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: + for field in street_fields: + partner[field] = None + continue + + street_format = (partner.country_id.street_format or + '%(street_number)s/%(street_number2)s %(street_name)s') + street_raw = partner.street + vals = self._split_street_with_params(street_raw, street_format) + # assign the values to the fields + for k, v in vals.items(): + partner[k] = v + for k in set(street_fields) - set(vals): + partner[k] = None + + 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 '%(<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 previous_greedy in vals: + # attach part before space to preceding greedy field + append_previous, sep, tmp[0] = tmp[0].rpartition(' ') + street_raw = separator.join(tmp) + vals[previous_greedy] += sep + append_previous + if len(tmp) == 2: + field_value, street_raw = tmp + vals[field_name] = field_value + if field_value or not field_name: + previous_greedy = None + if field_name == 'street_name' and separator == ' ': + previous_greedy = 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 + + def write(self, vals): + res = super(Partner, self).write(vals) + if 'country_id' in vals and 'street' not in vals: + self._inverse_street_data() + return res + + def _formatting_address_fields(self): + """Returns the list of address fields usable to format addresses.""" + return super(Partner, self)._formatting_address_fields() + self._get_street_fields() + + 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_name', 'street_number', 'street_number2'] |
