From 01ad0bfd8b1784c57b67211b5b8e36235d098bc4 Mon Sep 17 00:00:00 2001 From: Antonio Espinosa Date: Mon, 1 Feb 2016 17:58:21 +0100 Subject: [PATCH] Use separate and explicit fields for each NUTS level --- base_location_nuts/README.rst | 33 ++--- base_location_nuts/i18n/es.po | 4 +- base_location_nuts/models/res_country.py | 18 +-- base_location_nuts/models/res_partner.py | 139 ++++++++++++------ base_location_nuts/models/res_partner_nuts.py | 6 +- base_location_nuts/views/res_country_view.xml | 10 +- .../views/res_partner_nuts_view.xml | 3 + base_location_nuts/views/res_partner_view.xml | 71 ++++----- base_location_nuts/wizard/__init__.py | 6 +- base_location_nuts/wizard/nuts_import.py | 11 +- .../wizard/nuts_import_view.xml | 3 + 11 files changed, 150 insertions(+), 154 deletions(-) diff --git a/base_location_nuts/README.rst b/base_location_nuts/README.rst index ee531fb41..4acd2944d 100644 --- a/base_location_nuts/README.rst +++ b/base_location_nuts/README.rst @@ -7,28 +7,22 @@ NUTS Regions This module allows to import NUTS locations. -Creates two new fields in Partner object: +Creates four new fields in Partner object, one per NUTS level -* Region (res.partner.region): Classification over state, automatically - calculated when state is selected -* Substate (res.partner.substate): Classification above state, user must select - one from available for selected state +* NUTS L1: Country level +* NUTS L2: Normally state or big region level +* NUTS L3: Normally substate or state level +* NUTS L4: Normally small region or province level Installation ============ -You need to install another addon (one for each country) in order to use -these NUTS, for example: +We recommend to install another addon (one for each country) in order to relate +NUTS with states define by each localization addon, for example: -* l10n_es_location_nuts : - * Spanish Provinces (NUTS level 4) as Partner State - * Spanish Autonomous communities (NUTS level 3) as Partner Substate - * Spanish Regions (NUTS level 2) as Partner Region -* l10n_de_location_nuts : - * German states (NUTS level 2) as Partner State - * German districts (NUTS level 3) as Partner Substate - * German regions (NUTS level 4) as Partner Region +* l10n_es_location_nuts : Spanish Provinces (NUTS level 4) related to Partner State +* l10n_de_location_nuts : German states (NUTS level 2) related to Partner State Configuration @@ -44,13 +38,6 @@ l10n_de_location_nuts, ...) will inherit this wizard and relate each NUTS item with states. So if you install a new localization addon you must re-build NUTS clicking this wizard again. -To configure lables and levels per country, you should install a l10n module, -but if you want to do it manually, you need to: - -* Have *Sales / Responsible permissions*. -* Go to *Sales > Configuration > Address Book > Localization > Countries*. -* Choose one. -* Use the fields under the *NUTS* section. Usage ===== @@ -61,7 +48,7 @@ in order to allow to assign them to partner object. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/134/{branch} + :target: https://runbot.odoo-community.org/runbot/134/8.0 Bug Tracker =========== diff --git a/base_location_nuts/i18n/es.po b/base_location_nuts/i18n/es.po index 4fadf2138..86f6ef3ca 100644 --- a/base_location_nuts/i18n/es.po +++ b/base_location_nuts/i18n/es.po @@ -262,9 +262,9 @@ msgid "" " ENTRIES from new downloaded file." msgstr "" "Este asistente descargará la última version de\n" -" NUTS 2013 desde el servicio de matadatos europeo RAMON.\n" +" NUTS 2013 desde el servicio de metadatos europeo RAMON.\n" " Actualizando o creando nuevas regiones NUTS si no\n" -" las encuentra en el sistemma, y BORRANDO LAS QUE NO " +" las encuentra en el sistema, y BORRANDO LAS QUE NO " "ENCUENTRE\n" " en el nuevo fichero descargado." diff --git a/base_location_nuts/models/res_country.py b/base_location_nuts/models/res_country.py index 6d5e50dc0..e82947561 100644 --- a/base_location_nuts/models/res_country.py +++ b/base_location_nuts/models/res_country.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# © 2015 Antiun Ingeniería S.L. - Antonio Espinosa # © 2015 Antiun Ingeniería S.L. - Jairo Llopis # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). @@ -6,24 +7,7 @@ from openerp import models, fields class ResCountry(models.Model): - """Add labels corresponding to each country. - - These stay empty in this base module, and should be filled by l10n ones. - """ _inherit = "res.country" - state_label = fields.Char( - translate=True, - help="Label for the state NUTS category.") - substate_label = fields.Char( - translate=True, - help="Label for the substate NUTS category.") - region_label = fields.Char( - translate=True, - help="Label for the region NUTS category.") state_level = fields.Integer( help="Level for the state NUTS category.") - substate_level = fields.Integer( - help="Level for the substate NUTS category.") - region_level = fields.Integer( - help="Level for the region NUTS category.") diff --git a/base_location_nuts/models/res_partner.py b/base_location_nuts/models/res_partner.py index fef97cd9a..bbc3f9225 100644 --- a/base_location_nuts/models/res_partner.py +++ b/base_location_nuts/models/res_partner.py @@ -1,73 +1,122 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# © 2015 Antiun Ingeniería S.L. - Antonio Espinosa +# © 2015 Antiun Ingeniería S.L. - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields, api -from openerp.tools.translate import _ class ResPartner(models.Model): _inherit = 'res.partner' - region_id = fields.Many2one( - 'res.partner.nuts', - "Region", - oldname="region") - substate_id = fields.Many2one( - 'res.partner.nuts', - "Substate", - oldname="substate") - lbl_region = fields.Char( - default=_("Region"), - compute='_labels_get') - lbl_substate = fields.Char( - default=_("Substate"), - compute='_labels_get') + nuts1_id = fields.Many2one( + comodel_name='res.partner.nuts', domain=[('level', '=', 1)], + string="NUTS L1") + nuts2_id = fields.Many2one( + comodel_name='res.partner.nuts', domain=[('level', '=', 2)], + string="NUTS L2", oldname="region") + nuts3_id = fields.Many2one( + comodel_name='res.partner.nuts', domain=[('level', '=', 3)], + string="NUTS L3", oldname="substate") + nuts4_id = fields.Many2one( + comodel_name='res.partner.nuts', domain=[('level', '=', 4)], + string="NUTS L4") @api.multi - @api.depends('country_id') - def _labels_get(self): - for s in self: - s.lbl_region = s.country_id.region_label or _('Region') - s.lbl_substate = s.country_id.substate_label or _('Substate') + def _onchange_nuts(self, field): + country_id = self[field].country_id.id + state_id = self[field].state_id.id + if country_id and self.country_id.id != country_id: + self.country_id = country_id + if state_id and self.state_id.id != state_id: + self.state_id = state_id + level = int(field[:5][-1]) + if (level - 1) > 0: + parent_id = self[field].parent_id.id + if parent_id: + parent_field = 'nuts%d_id' % (level - 1) + if self[parent_field].id != parent_id: + self[parent_field] = parent_id + result = dict() + if country_id and level < 4: + result['domain'] = dict() + while level < 4: + parent_field = 'nuts%d_id' % level + domain_field = 'nuts%d_id' % (level + 1) + parent_id = self[parent_field].id + if parent_id: + result['domain'][domain_field] = [ + ('parent_id', '=', parent_id), + ] + level += 1 + return result @api.multi - @api.onchange("substate_id") - def _onchange_substate_id(self): - if self.substate_id.country_id: - self.country_id = self.substate_id.country_id - return dict() + @api.onchange('nuts4_id') + def _onchange_nuts4_id(self): + return self._onchange_nuts('nuts4_id') @api.multi - @api.onchange("region_id") - def _onchange_region_id(self): - if self.region_id.country_id: - self.country_id = self.region_id.country_id - return dict() + @api.onchange('nuts3_id') + def _onchange_nuts3_id(self): + return self._onchange_nuts('nuts3_id') @api.multi - @api.onchange("country_id") + @api.onchange('nuts2_id') + def _onchange_nuts2_id(self): + return self._onchange_nuts('nuts2_id') + + @api.multi + @api.onchange('nuts1_id') + def _onchange_nuts1_id(self): + return self._onchange_nuts('nuts1_id') + + @api.multi + @api.onchange('country_id') def _onchange_country_id(self): """Sensible values and domains for related fields.""" - fields = {"state", "region", "substate"} - country_domain = ([("country_id", "=", self.country_id.id)] + fields = ['state_id', 'nuts1_id', 'nuts2_id', 'nuts3_id', 'nuts4_id'] + country_domain = ([('country_id', '=', self.country_id.id)] if self.country_id else []) - domain = dict() for field in fields: - field += "_id" if self.country_id and self[field].country_id != self.country_id: self[field] = False domain[field] = list(country_domain) # Using list() to copy - - fields.remove("state") + fields.remove('state_id') for field in fields: - level = self.country_id["%s_level" % field] - field += "_id" + level = int(field[:5][-1]) if level: - domain[field].append(("level", "=", level)) - + domain[field].append(('level', '=', level)) + if self.country_id: + nuts1 = self.env['res.partner.nuts'].search([ + ('level', '=', 1), + ('country_id', '=', self.country_id.id), + ], limit=1) + if self.nuts1_id.id != nuts1.id: + self.nuts1_id = nuts1.id return { - "domain": domain, + 'domain': domain, } + + @api.multi + def onchange_state(self, state_id): + result = super(ResPartner, self).onchange_state(state_id) + state = self.env['res.country.state'].browse(state_id) + if state.country_id.state_level: + nuts_state = self.env['res.partner.nuts'].search([ + ('level', '=', state.country_id.state_level), + ('state_id', '=', state.id) + ], limit=1) + if nuts_state: + field = 'nuts%d_id' % state.country_id.state_level + result.setdefault("value", dict()) + result['value'][field] = nuts_state.id + return result + + @api.model + def _address_fields(self): + fields = super(ResPartner, self)._address_fields() + if fields: + fields += ['nuts1_id', 'nuts2_id', 'nuts3_id', 'nuts4_id'] + return fields diff --git a/base_location_nuts/models/res_partner_nuts.py b/base_location_nuts/models/res_partner_nuts.py index c17c7a86d..cea22cf92 100644 --- a/base_location_nuts/models/res_partner_nuts.py +++ b/base_location_nuts/models/res_partner_nuts.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# © 2015 Antiun Ingeniería S.L. - Antonio Espinosa +# © 2015 Antiun Ingeniería S.L. - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, fields diff --git a/base_location_nuts/views/res_country_view.xml b/base_location_nuts/views/res_country_view.xml index 57ddccaa2..cb451f78b 100644 --- a/base_location_nuts/views/res_country_view.xml +++ b/base_location_nuts/views/res_country_view.xml @@ -1,5 +1,6 @@ @@ -13,17 +14,8 @@ - - - - - - - - - diff --git a/base_location_nuts/views/res_partner_nuts_view.xml b/base_location_nuts/views/res_partner_nuts_view.xml index 877edd243..3ecad6631 100644 --- a/base_location_nuts/views/res_partner_nuts_view.xml +++ b/base_location_nuts/views/res_partner_nuts_view.xml @@ -1,4 +1,7 @@ + diff --git a/base_location_nuts/views/res_partner_view.xml b/base_location_nuts/views/res_partner_view.xml index 38cd98eee..9bf0cd81b 100644 --- a/base_location_nuts/views/res_partner_view.xml +++ b/base_location_nuts/views/res_partner_view.xml @@ -1,4 +1,7 @@ + @@ -8,48 +11,16 @@ -
- -
-
- -
-
- -
-
- -
+ + + +
-
- -
-
- -
-
- -
-
- -
+ + + +
@@ -60,16 +31,24 @@ - - + + + + - - + + context="{'group_by': 'nuts2_id'}"/> + + diff --git a/base_location_nuts/wizard/__init__.py b/base_location_nuts/wizard/__init__.py index 1f9d83bcf..66654141f 100644 --- a/base_location_nuts/wizard/__init__.py +++ b/base_location_nuts/wizard/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# © 2015 Antiun Ingeniería S.L. - Antonio Espinosa +# © 2015 Antiun Ingeniería S.L. - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import nuts_import diff --git a/base_location_nuts/wizard/nuts_import.py b/base_location_nuts/wizard/nuts_import.py index e63f908fe..31cc49548 100644 --- a/base_location_nuts/wizard/nuts_import.py +++ b/base_location_nuts/wizard/nuts_import.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## +# © 2015 Antiun Ingeniería S.L. - Antonio Espinosa +# © 2015 Antiun Ingeniería S.L. - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, api, _ from openerp.exceptions import Warning @@ -140,7 +140,6 @@ class NutsImport(models.TransientModel): # UK => GB (United Kingdom) self._countries['EL'] = self._countries['GR'] self._countries['UK'] = self._countries['GB'] - logger.info('_load_countries = %s' % pformat(self._countries)) @api.model def state_mapping(self, data, node): @@ -184,11 +183,11 @@ class NutsImport(models.TransientModel): nuts_to_delete = nuts_model.search( [('country_id', 'in', [x.id for x in self._countries.values()])]) # Download NUTS in english, create or update - logger.info('Import NUTS 2013 English') + logger.info('Importing NUTS 2013 English') xmlcontent = self._download_nuts() dom = etree.fromstring(xmlcontent) for node in dom.iter('Item'): - logger.info('Reading level=%s, id=%s' % + logger.debug('Reading level=%s, id=%s' % (node.get('idLevel', 'N/A'), node.get('id', 'N/A'))) nuts = self.create_or_update_nuts(node) diff --git a/base_location_nuts/wizard/nuts_import_view.xml b/base_location_nuts/wizard/nuts_import_view.xml index 6acd7bdbc..1c023c834 100644 --- a/base_location_nuts/wizard/nuts_import_view.xml +++ b/base_location_nuts/wizard/nuts_import_view.xml @@ -1,4 +1,7 @@ +