From b2982896afe893cd56ba42129175732f240f14eb Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 29 Dec 2015 16:29:29 +0100 Subject: [PATCH 1/7] Update base_location_nuts to 8.0.2.0.0. This makes NUTS labels and levels to be stored in the res.country object. Now creating l10n submodules is a piece of cake! Relational fields now follow guidelines on naming. Old name attribute used for backwards compatibility wherever needed. Also some methods have been renamed, and refactored to be smarter. Most cases l10n modules will just need to fill the res.contry table, and regions and substates domains will work out of the box. In case you still need to overwrite any method, splitting in smaller methods makes it easier too. Oh! And no need for recursive dictionary updates. --- base_location_nuts/README.rst | 11 +- base_location_nuts/__openerp__.py | 3 +- .../i18n/base_location_nuts.pot | 214 ------------------ base_location_nuts/i18n/es.po | 113 +++++++-- base_location_nuts/models/__init__.py | 13 +- base_location_nuts/models/res_country.py | 29 +++ base_location_nuts/models/res_partner.py | 98 ++++---- base_location_nuts/models/res_partner_nuts.py | 7 +- base_location_nuts/views/res_country_view.xml | 33 +++ base_location_nuts/views/res_partner_view.xml | 18 +- 10 files changed, 246 insertions(+), 293 deletions(-) delete mode 100644 base_location_nuts/i18n/base_location_nuts.pot create mode 100644 base_location_nuts/models/res_country.py create mode 100644 base_location_nuts/views/res_country_view.xml diff --git a/base_location_nuts/README.rst b/base_location_nuts/README.rst index 18c380523..ee531fb41 100644 --- a/base_location_nuts/README.rst +++ b/base_location_nuts/README.rst @@ -44,6 +44,13 @@ 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 ===== @@ -56,7 +63,6 @@ in order to allow to assign them to partner object. :alt: Try me on Runbot :target: https://runbot.odoo-community.org/runbot/134/{branch} - Bug Tracker =========== @@ -74,6 +80,7 @@ Contributors * Rafael Blasco * Antonio Espinosa +* Jairo Llopis Maintainer ---------- @@ -88,4 +95,4 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. \ No newline at end of file +To contribute to this module, please visit http://odoo-community.org. diff --git a/base_location_nuts/__openerp__.py b/base_location_nuts/__openerp__.py index a1aad7791..f0ff5ffb1 100644 --- a/base_location_nuts/__openerp__.py +++ b/base_location_nuts/__openerp__.py @@ -24,11 +24,12 @@ { 'name': 'NUTS Regions', 'category': 'Localisation/Europe', - 'version': '8.0.1.0.0', + 'version': '8.0.2.0.0', 'depends': [ 'base', ], 'data': [ + 'views/res_country_view.xml', 'views/res_partner_nuts_view.xml', 'views/res_partner_view.xml', 'wizard/nuts_import_view.xml', diff --git a/base_location_nuts/i18n/base_location_nuts.pot b/base_location_nuts/i18n/base_location_nuts.pot deleted file mode 100644 index 82a4f0117..000000000 --- a/base_location_nuts/i18n/base_location_nuts.pot +++ /dev/null @@ -1,214 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * base_location_nuts -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-06-11 15:26+0000\n" -"PO-Revision-Date: 2015-06-11 15:26+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: base_location_nuts -#: view:nuts.import:base_location_nuts.nuts_import_form -msgid "Cancel" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,children:0 -msgid "Children" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,code:0 -msgid "Code" -msgstr "" - -#. module: base_location_nuts -#: view:res.partner.nuts:base_location_nuts.view_res_partner_nuts_filter -#: field:res.partner.nuts,country_id:0 -msgid "Country" -msgstr "" - -#. module: base_location_nuts -#: field:nuts.import,create_uid:0 -#: field:res.partner.nuts,create_uid:0 -msgid "Created by" -msgstr "" - -#. module: base_location_nuts -#: field:nuts.import,create_date:0 -#: field:res.partner.nuts,create_date:0 -msgid "Created on" -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/wizard/nuts_import.py:149 -#, python-format -msgid "Downloaded file is not a valid XML file" -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/wizard/nuts_import.py:141 -#, python-format -msgid "Got an error %d when trying to download the file %s." -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/wizard/nuts_import.py:137 -#, python-format -msgid "Got an error when trying to download the file: %s." -msgstr "" - -#. module: base_location_nuts -#: view:res.partner.nuts:base_location_nuts.view_res_partner_nuts_filter -msgid "Group By" -msgstr "" - -#. module: base_location_nuts -#: field:nuts.import,id:0 -#: field:res.partner.nuts,id:0 -msgid "ID" -msgstr "" - -#. module: base_location_nuts -#: view:nuts.import:base_location_nuts.nuts_import_form -msgid "Import" -msgstr "" - -#. module: base_location_nuts -#: model:ir.ui.menu,name:base_location_nuts.nuts_import_menu -msgid "Import NUTS 2013" -msgstr "" - -#. module: base_location_nuts -#: model:ir.actions.act_window,name:base_location_nuts.nuts_import_action -#: view:nuts.import:base_location_nuts.nuts_import_form -msgid "Import NUTS 2013 from RAMON" -msgstr "" - -#. module: base_location_nuts -#: model:ir.model,name:base_location_nuts.model_nuts_import -msgid "Import NUTS items from European RAMON service" -msgstr "" - -#. module: base_location_nuts -#: field:nuts.import,write_uid:0 -#: field:res.partner.nuts,write_uid:0 -msgid "Last Updated by" -msgstr "" - -#. module: base_location_nuts -#: field:nuts.import,write_date:0 -#: field:res.partner.nuts,write_date:0 -msgid "Last Updated on" -msgstr "" - -#. module: base_location_nuts -#: view:res.partner.nuts:base_location_nuts.view_res_partner_nuts_filter -#: field:res.partner.nuts,level:0 -msgid "Level" -msgstr "" - -#. module: base_location_nuts -#: model:ir.model,name:base_location_nuts.model_res_partner_nuts -#: view:res.partner.nuts:base_location_nuts.res_partner_nuts_form -msgid "NUTS Item" -msgstr "" - -#. module: base_location_nuts -#: model:ir.actions.act_window,name:base_location_nuts.res_partner_nuts_action -#: model:ir.ui.menu,name:base_location_nuts.res_partner_nuts_menu -#: view:res.partner.nuts:base_location_nuts.res_partner_nuts_tree -msgid "NUTS Items" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,name:0 -msgid "Name" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,parent_left:0 -msgid "Parent Left" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,parent_right:0 -msgid "Parent Right" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,parent_id:0 -msgid "Parent id" -msgstr "" - -#. module: base_location_nuts -#: model:ir.model,name:base_location_nuts.model_res_partner -msgid "Partner" -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/models/res_partner.py:53 -#: view:res.partner:base_location_nuts.view_res_partner_filter_nuts -#: field:res.partner,region:0 -#, python-format -msgid "Region" -msgstr "" - -#. module: base_location_nuts -#: view:res.partner:base_location_nuts.view_res_partner_filter_nuts -msgid "Salesperson" -msgstr "" - -#. module: base_location_nuts -#: view:res.partner.nuts:base_location_nuts.view_res_partner_nuts_filter -msgid "Search NUTS" -msgstr "" - -#. module: base_location_nuts -#: field:res.partner.nuts,state_id:0 -msgid "State" -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/models/res_partner.py:54 -#: view:res.partner:base_location_nuts.view_res_partner_filter_nuts -#: field:res.partner,substate:0 -#, python-format -msgid "Substate" -msgstr "" - -#. module: base_location_nuts -#: view:nuts.import:base_location_nuts.nuts_import_form -msgid "This wizard will download the lastest version of\n" -" NUTS 2013 from Europe RAMON metadata service.\n" -" Updating or creating new NUTS entries if not\n" -" found already in the system, and DELETING MISSING\n" -" ENTRIES from new downloaded file." -msgstr "" - -#. module: base_location_nuts -#: code:addons/base_location_nuts/wizard/nuts_import.py:116 -#, python-format -msgid "Value not found for mandatory field %s" -msgstr "" - -#. module: base_location_nuts -#: model:ir.actions.todo,note:base_location_nuts.config_wizard_nuts -msgid "You can import NUTS from RAMON european service." -msgstr "" - -#. module: base_location_nuts -#: model:ir.actions.act_window,help:base_location_nuts.res_partner_nuts_action -msgid "You must click at import wizard to populate NUTS items\n" -" in Odoo database in:\n" -" Sales > Configuration > Address Book > Localization > Import NUTS 2013" -msgstr "" - diff --git a/base_location_nuts/i18n/es.po b/base_location_nuts/i18n/es.po index 6a27ad51f..4fadf2138 100644 --- a/base_location_nuts/i18n/es.po +++ b/base_location_nuts/i18n/es.po @@ -1,21 +1,23 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: # * base_location_nuts -# +# # Translators: msgid "" msgstr "" "Project-Id-Version: partner-contact (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-10-09 15:48+0000\n" -"PO-Revision-Date: 2015-10-06 13:57+0000\n" +"POT-Creation-Date: 2015-12-30 17:07+0100\n" +"PO-Revision-Date: 2015-12-30 17:11+0100\n" "Last-Translator: OCA Transbot \n" -"Language-Team: Spanish (http://www.transifex.com/oca/OCA-partner-contact-8-0/language/es/)\n" +"Language-Team: Spanish (http://www.transifex.com/oca/OCA-partner-contact-8-0/" +"language/es/)\n" +"Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Language: es\n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.5\n" #. module: base_location_nuts #: view:nuts.import:base_location_nuts.nuts_import_form @@ -23,7 +25,7 @@ msgid "Cancel" msgstr "Cancelar" #. module: base_location_nuts -#: field:res.partner.nuts,children:0 +#: field:res.partner.nuts,child_ids:0 msgid "Children" msgstr "Hijos" @@ -33,6 +35,7 @@ msgid "Code" msgstr "Código" #. module: base_location_nuts +#: model:ir.model,name:base_location_nuts.model_res_country #: view:res.partner.nuts:base_location_nuts.view_res_partner_nuts_filter #: field:res.partner.nuts,country_id:0 msgid "Country" @@ -97,6 +100,21 @@ msgstr "Importar NUTS 2013 desde RAMON" msgid "Import NUTS items from European RAMON service" msgstr "Importar regiones NUTS desde el servicio europeo RAMON" +#. module: base_location_nuts +#: help:res.country,region_label:0 +msgid "Label for the region NUTS category." +msgstr "Etiqueta para la categoría región NUTS." + +#. module: base_location_nuts +#: help:res.country,state_label:0 +msgid "Label for the state NUTS category." +msgstr "Etiqueta para la categoría estado NUTS." + +#. module: base_location_nuts +#: help:res.country,substate_label:0 +msgid "Label for the substate NUTS category." +msgstr "Etiqueta para la categoría subestado NUTS." + #. module: base_location_nuts #: field:nuts.import,write_uid:0 field:res.partner.nuts,write_uid:0 msgid "Last Updated by" @@ -113,18 +131,38 @@ msgstr "Última actualización en" msgid "Level" msgstr "Nivel" +#. module: base_location_nuts +#: help:res.country,region_level:0 +msgid "Level for the region NUTS category." +msgstr "Nivel para la categoría región NUTS." + +#. module: base_location_nuts +#: help:res.country,state_level:0 +msgid "Level for the state NUTS category." +msgstr "Nivel para la categoría estado NUTS." + +#. module: base_location_nuts +#: help:res.country,substate_level:0 +msgid "Level for the substate NUTS category." +msgstr "Nivel para la categoría subestado NUTS." + +#. module: base_location_nuts +#: view:res.country:base_location_nuts.view_country_form +msgid "NUTS" +msgstr "NUTS" + #. module: base_location_nuts #: model:ir.model,name:base_location_nuts.model_res_partner_nuts #: view:res.partner.nuts:base_location_nuts.res_partner_nuts_form msgid "NUTS Item" -msgstr "Región NUTS" +msgstr "Objeto NUTS" #. module: base_location_nuts #: model:ir.actions.act_window,name:base_location_nuts.res_partner_nuts_action #: model:ir.ui.menu,name:base_location_nuts.res_partner_nuts_menu #: view:res.partner.nuts:base_location_nuts.res_partner_nuts_tree msgid "NUTS Items" -msgstr "Regiones NUTS" +msgstr "Objetos NUTS" #. module: base_location_nuts #: field:res.partner.nuts,name:0 @@ -152,13 +190,24 @@ msgid "Partner" msgstr "Empresa" #. module: base_location_nuts -#: code:addons/base_location_nuts/models/res_partner.py:34 +#: code:addons/base_location_nuts/models/res_partner.py:22 +#: code:addons/base_location_nuts/models/res_partner.py:32 #: view:res.partner:base_location_nuts.view_res_partner_filter_nuts -#: field:res.partner,region:0 +#: field:res.partner,region_id:0 #, python-format msgid "Region" msgstr "Región" +#. module: base_location_nuts +#: field:res.country,region_label:0 +msgid "Region label" +msgstr "Etiqueta de región" + +#. module: base_location_nuts +#: field:res.country,region_level:0 +msgid "Region level" +msgstr "Nivel de región" + #. module: base_location_nuts #: view:res.partner:base_location_nuts.view_res_partner_filter_nuts msgid "Salesperson" @@ -175,13 +224,34 @@ msgid "State" msgstr "Provincia" #. module: base_location_nuts -#: code:addons/base_location_nuts/models/res_partner.py:35 +#: field:res.country,state_label:0 +msgid "State label" +msgstr "Etiqueta de estado" + +#. module: base_location_nuts +#: field:res.country,state_level:0 +msgid "State level" +msgstr "Nivel de estado" + +#. module: base_location_nuts +#: code:addons/base_location_nuts/models/res_partner.py:25 +#: code:addons/base_location_nuts/models/res_partner.py:33 #: view:res.partner:base_location_nuts.view_res_partner_filter_nuts -#: field:res.partner,substate:0 +#: field:res.partner,substate_id:0 #, python-format msgid "Substate" msgstr "Estado" +#. module: base_location_nuts +#: field:res.country,substate_label:0 +msgid "Substate label" +msgstr "Etiqueta de subestado" + +#. module: base_location_nuts +#: field:res.country,substate_level:0 +msgid "Substate level" +msgstr "Nivel de subestado" + #. module: base_location_nuts #: view:nuts.import:base_location_nuts.nuts_import_form msgid "" @@ -190,7 +260,13 @@ msgid "" " Updating or creating new NUTS entries if not\n" " found already in the system, and DELETING MISSING\n" " ENTRIES from new downloaded file." -msgstr "Este asistente descargará la última version de\n NUTS 2013 desde el servicio de matadatos europeo RAMON.\n Actualizando o creando nuevas regiones NUTS si no\n las encuentra en el sistemma, y BORRANDO LAS QUE NO ENCUENTRE\n en el nuevo fichero descargado." +msgstr "" +"Este asistente descargará la última version de\n" +" NUTS 2013 desde el servicio de matadatos europeo RAMON.\n" +" Actualizando o creando nuevas regiones NUTS si no\n" +" las encuentra en el sistemma, y BORRANDO LAS QUE NO " +"ENCUENTRE\n" +" en el nuevo fichero descargado." #. module: base_location_nuts #: code:addons/base_location_nuts/wizard/nuts_import.py:97 @@ -208,5 +284,10 @@ msgstr "Usted puede importar NUTS desde el servicion europeo RAMON." msgid "" "You must click at import wizard to populate NUTS items\n" " in Odoo database in:\n" -" Sales > Configuration > Address Book > Localization > Import NUTS 2013" -msgstr "Debes clicar en el asistente de importación para crear las\n las regiones NUTS en la base de datos de Odoo, en el menú:\n Ventas > Configuración > Libreta de direcciones > Localización > Importar NUTS 2013" +" Sales > Configuration > Address Book > Localization > Import NUTS " +"2013" +msgstr "" +"Debes clicar en el asistente de importación para crear las\n" +" las regiones NUTS en la base de datos de Odoo, en el menú:\n" +" Ventas > Configuración > Libreta de direcciones > Localización > " +"Importar NUTS 2013" diff --git a/base_location_nuts/models/__init__.py b/base_location_nuts/models/__init__.py index a88f82ad0..2a172bcaa 100644 --- a/base_location_nuts/models/__init__.py +++ b/base_location_nuts/models/__init__.py @@ -1,7 +1,10 @@ # -*- 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 res_partner_nuts -from . import res_partner +from . import ( + res_country, + res_partner_nuts, + res_partner, +) diff --git a/base_location_nuts/models/res_country.py b/base_location_nuts/models/res_country.py new file mode 100644 index 000000000..6d5e50dc0 --- /dev/null +++ b/base_location_nuts/models/res_country.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# © 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 + + +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 904580980..94e41d009 100644 --- a/base_location_nuts/models/res_partner.py +++ b/base_location_nuts/models/res_partner.py @@ -5,57 +5,67 @@ from openerp import models, fields, api from openerp.tools.translate import _ -import collections - - -def dict_recursive_update(d, u): - for k, v in u.iteritems(): - if isinstance(v, collections.Mapping): - r = dict_recursive_update(d.get(k, {}), v) - d[k] = r - else: - d[k] = u[k] - return d class ResPartner(models.Model): _inherit = 'res.partner' - region = fields.Many2one(comodel_name='res.partner.nuts', - string="Region") - substate = fields.Many2one(comodel_name='res.partner.nuts', - string="Substate") - lbl_region = fields.Char(compute='_labels_get') - lbl_substate = fields.Char(compute='_labels_get') + 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') - @api.one + @api.multi @api.depends('country_id') def _labels_get(self): - self.lbl_region = _('Region') - self.lbl_substate = _('Substate') + for s in self: + s.lbl_region = s.country_id.region_label or _('Region') + s.lbl_substate = s.country_id.substate_label or _('Substate') + + @api.multi + @api.onchange("substate_id") + def _onchange_substate_id(self): + for s in self: + if s.substate_id.country_id: + s.country_id = s.substate_id.country_id @api.multi - def onchange_state(self, state_id): - result = super(ResPartner, self).onchange_state(state_id) - if not state_id: - changes = { - 'domain': { - 'substate': [], - 'region': [], - }, - 'value': { - 'substate': False, - 'region': False, - } - } - dict_recursive_update(result, changes) - return result - - @api.onchange('substate', 'region') - def onchange_substate_or_region(self): - result = {'domain': {}} - if not self.substate: - result['domain']['substate'] = [] - if not self.region: - result['domain']['region'] = [] - return result + @api.onchange("region_id") + def _onchange_region_id(self): + for s in self: + if s.region_id.country_id: + s.country_id = s.region_id.country_id + + @api.multi + @api.onchange("country_id") + def _onchange_country_id(self): + """Sensible values and domains for related fields.""" + fields = {"state_id", "region_id", "substate_id"} + country_domain = ([("country_id", "=", self.country_id.id)] + if self.country_id else []) + + domain = dict() + for field in fields: + 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_id") + for field in fields: + level = self.country_id["%s_level" % field] + if level: + domain[field].append(("level", "=", level)) + + return { + "domain": domain, + } diff --git a/base_location_nuts/models/res_partner_nuts.py b/base_location_nuts/models/res_partner_nuts.py index f8e62f20b..c17c7a86d 100644 --- a/base_location_nuts/models/res_partner_nuts.py +++ b/base_location_nuts/models/res_partner_nuts.py @@ -24,7 +24,10 @@ class ResPartnerNuts(models.Model): # Parent hierarchy parent_id = fields.Many2one(comodel_name='res.partner.nuts', ondelete='restrict') - children = fields.One2many(comodel_name='res.partner.nuts', - inverse_name='parent_id') + child_ids = fields.One2many( + 'res.partner.nuts', + 'parent_id', + "Children", + oldname="children") parent_left = fields.Integer('Parent Left', select=True) parent_right = fields.Integer('Parent Right', select=True) diff --git a/base_location_nuts/views/res_country_view.xml b/base_location_nuts/views/res_country_view.xml new file mode 100644 index 000000000..57ddccaa2 --- /dev/null +++ b/base_location_nuts/views/res_country_view.xml @@ -0,0 +1,33 @@ + + + + + + + + NUTS fields + res.country + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_location_nuts/views/res_partner_view.xml b/base_location_nuts/views/res_partner_view.xml index 55192e41c..38cd98eee 100644 --- a/base_location_nuts/views/res_partner_view.xml +++ b/base_location_nuts/views/res_partner_view.xml @@ -13,7 +13,7 @@
- @@ -23,7 +23,7 @@
- @@ -35,7 +35,7 @@
- @@ -45,7 +45,7 @@
- @@ -60,19 +60,19 @@ - - + + + context="{'group_by': 'region_id'}"/> + context="{'group_by': 'substate_id'}"/> - \ No newline at end of file + From 8f3319e69506bf443ae5d499935e802be419778c Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 30 Dec 2015 18:27:32 +0100 Subject: [PATCH 2/7] Return dict() to make it easier for submodules to add domains. --- base_location_nuts/models/res_partner.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base_location_nuts/models/res_partner.py b/base_location_nuts/models/res_partner.py index 94e41d009..a1117d689 100644 --- a/base_location_nuts/models/res_partner.py +++ b/base_location_nuts/models/res_partner.py @@ -35,16 +35,16 @@ class ResPartner(models.Model): @api.multi @api.onchange("substate_id") def _onchange_substate_id(self): - for s in self: - if s.substate_id.country_id: - s.country_id = s.substate_id.country_id + if self.substate_id.country_id: + self.country_id = self.substate_id.country_id + return dict() @api.multi @api.onchange("region_id") def _onchange_region_id(self): - for s in self: - if s.region_id.country_id: - s.country_id = s.region_id.country_id + if self.region_id.country_id: + self.country_id = self.region_id.country_id + return dict() @api.multi @api.onchange("country_id") From 26427576ae508ac8ef1deed0b790a4297a6b9811 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Wed, 30 Dec 2015 18:41:01 +0100 Subject: [PATCH 3/7] Fix KeyError: 'substate_id_level'. --- base_location_nuts/models/res_partner.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base_location_nuts/models/res_partner.py b/base_location_nuts/models/res_partner.py index a1117d689..fef97cd9a 100644 --- a/base_location_nuts/models/res_partner.py +++ b/base_location_nuts/models/res_partner.py @@ -50,19 +50,21 @@ class ResPartner(models.Model): @api.onchange("country_id") def _onchange_country_id(self): """Sensible values and domains for related fields.""" - fields = {"state_id", "region_id", "substate_id"} + fields = {"state", "region", "substate"} 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_id") + fields.remove("state") for field in fields: level = self.country_id["%s_level" % field] + field += "_id" if level: domain[field].append(("level", "=", level)) From 2b239f0e433758273cd5fc21d89b2b2f3fa364a9 Mon Sep 17 00:00:00 2001 From: Antonio Espinosa Date: Mon, 1 Feb 2016 17:58:21 +0100 Subject: [PATCH 4/7] 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 @@ + From 4334407d7218a78a6aab7ba8d734543b42b1c2b3 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 2 Feb 2016 15:50:39 +0100 Subject: [PATCH 5/7] Make method recieve the level as int. --- base_location_nuts/models/res_partner.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base_location_nuts/models/res_partner.py b/base_location_nuts/models/res_partner.py index bbc3f9225..c5ddae6e7 100644 --- a/base_location_nuts/models/res_partner.py +++ b/base_location_nuts/models/res_partner.py @@ -23,16 +23,16 @@ class ResPartner(models.Model): string="NUTS L4") @api.multi - def _onchange_nuts(self, field): - country_id = self[field].country_id.id - state_id = self[field].state_id.id + def _onchange_nuts(self, level): + field = self["nuts%d_id" % level] + country_id = field.country_id.id + state_id = 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 + parent_id = field.parent_id.id if parent_id: parent_field = 'nuts%d_id' % (level - 1) if self[parent_field].id != parent_id: @@ -54,22 +54,22 @@ class ResPartner(models.Model): @api.multi @api.onchange('nuts4_id') def _onchange_nuts4_id(self): - return self._onchange_nuts('nuts4_id') + return self._onchange_nuts(4) @api.multi @api.onchange('nuts3_id') def _onchange_nuts3_id(self): - return self._onchange_nuts('nuts3_id') + return self._onchange_nuts(3) @api.multi @api.onchange('nuts2_id') def _onchange_nuts2_id(self): - return self._onchange_nuts('nuts2_id') + return self._onchange_nuts(2) @api.multi @api.onchange('nuts1_id') def _onchange_nuts1_id(self): - return self._onchange_nuts('nuts1_id') + return self._onchange_nuts(1) @api.multi @api.onchange('country_id') From 8108537531e9d4fbbb0337199a09b21dbc8ce978 Mon Sep 17 00:00:00 2001 From: Jairo Llopis Date: Tue, 2 Feb 2016 18:18:28 +0100 Subject: [PATCH 6/7] Fix linter. --- base_location_nuts/__openerp__.py | 3 +++ base_location_nuts/images/new_fields.png | Bin 0 -> 17020 bytes base_location_nuts/wizard/nuts_import.py | 19 +++++++++---------- 3 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 base_location_nuts/images/new_fields.png diff --git a/base_location_nuts/__openerp__.py b/base_location_nuts/__openerp__.py index f0ff5ffb1..e1f7cb650 100644 --- a/base_location_nuts/__openerp__.py +++ b/base_location_nuts/__openerp__.py @@ -35,6 +35,9 @@ 'wizard/nuts_import_view.xml', 'security/ir.model.access.csv', ], + 'images': [ + 'images/new_fields.png', + ], 'author': 'Antiun Ingeniería S.L., ' 'Odoo Community Association (OCA)', 'website': 'http://www.antiun.com', diff --git a/base_location_nuts/images/new_fields.png b/base_location_nuts/images/new_fields.png new file mode 100644 index 0000000000000000000000000000000000000000..24f235bf5c4d0dc2ccb8ca0a2956a313ac6f2b71 GIT binary patch literal 17020 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 Date: Fri, 19 Feb 2016 16:56:24 +0100 Subject: [PATCH 7/7] Fix typo. --- base_location_nuts/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base_location_nuts/README.rst b/base_location_nuts/README.rst index 4acd2944d..39c4c3545 100644 --- a/base_location_nuts/README.rst +++ b/base_location_nuts/README.rst @@ -19,7 +19,7 @@ Installation ============ We recommend to install another addon (one for each country) in order to relate -NUTS with states define by each localization addon, for example: +NUTS with states defined by each localization addon, for example: * 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