Browse Source

Pre-commit

14.0
Andrea 4 years ago
committed by Andrii Skrypka
parent
commit
21dabc5265
  1. 36
      base_location_nuts/__manifest__.py
  2. 2
      base_location_nuts/migrations/12.0.1.0.0/post-migration.py
  3. 3
      base_location_nuts/models/res_country.py
  4. 83
      base_location_nuts/models/res_partner.py
  5. 28
      base_location_nuts/models/res_partner_nuts.py
  6. 69
      base_location_nuts/tests/test_base_location_nuts.py
  7. 30
      base_location_nuts/views/res_country_view.xml
  8. 134
      base_location_nuts/views/res_partner_nuts_view.xml
  9. 99
      base_location_nuts/views/res_partner_view.xml
  10. 172
      base_location_nuts/wizard/nuts_import.py
  11. 79
      base_location_nuts/wizard/nuts_import_view.xml

36
base_location_nuts/__manifest__.py

@ -4,26 +4,20 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'NUTS Regions',
'category': 'Localisation/Europe',
'version': '12.0.1.0.0',
'depends': [
'contacts',
"name": "NUTS Regions",
"category": "Localisation/Europe",
"version": "12.0.1.0.0",
"depends": ["contacts",],
"data": [
"views/res_country_view.xml",
"views/res_partner_nuts_view.xml",
"views/res_partner_view.xml",
"wizard/nuts_import_view.xml",
"security/ir.model.access.csv",
],
'data': [
'views/res_country_view.xml',
'views/res_partner_nuts_view.xml',
'views/res_partner_view.xml',
'wizard/nuts_import_view.xml',
'security/ir.model.access.csv',
],
'images': [
'images/new_fields.png',
],
'author': 'Tecnativa, '
'Agile Business Group, '
'Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/partner-contact/',
'license': 'AGPL-3',
'installable': True,
"images": ["images/new_fields.png",],
"author": "Tecnativa, " "Agile Business Group, " "Odoo Community Association (OCA)",
"website": "https://github.com/OCA/partner-contact/",
"license": "AGPL-3",
"installable": True,
}

2
base_location_nuts/migrations/12.0.1.0.0/post-migration.py

@ -3,4 +3,4 @@ from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
env['res.partner.nuts']._parent_store_compute()
env["res.partner.nuts"]._parent_store_compute()

3
base_location_nuts/models/res_country.py

@ -8,5 +8,4 @@ from odoo import fields, models
class ResCountry(models.Model):
_inherit = "res.country"
state_level = fields.Integer(
help="Level for the state NUTS category.")
state_level = fields.Integer(help="Level for the state NUTS category.")

83
base_location_nuts/models/res_partner.py

@ -6,20 +6,26 @@ from odoo import api, fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
_inherit = "res.partner"
nuts1_id = fields.Many2one(
comodel_name='res.partner.nuts', domain=[('level', '=', 1)],
string="NUTS L1")
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")
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")
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")
comodel_name="res.partner.nuts", domain=[("level", "=", 4)], string="NUTS L4"
)
def _onchange_nuts(self, level):
field = self["nuts%d_id" % level]
@ -32,82 +38,85 @@ class ResPartner(models.Model):
if level > 1:
parent_id = field.parent_id
if parent_id:
nuts_parent_level = 'nuts%d_id' % (level - 1)
nuts_parent_level = "nuts%d_id" % (level - 1)
parent_field = self[nuts_parent_level]
if parent_field != parent_id:
self[nuts_parent_level] = parent_id
result = {}
if country_id and level < 4:
result['domain'] = {}
result["domain"] = {}
while level < 4:
parent_field = 'nuts%d_id' % level
domain_field = 'nuts%d_id' % (level + 1)
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),
result["domain"][domain_field] = [
("parent_id", "=", parent_id),
]
level += 1
return result
@api.onchange('nuts4_id')
@api.onchange("nuts4_id")
def _onchange_nuts4_id(self):
return self._onchange_nuts(4)
@api.onchange('nuts3_id')
@api.onchange("nuts3_id")
def _onchange_nuts3_id(self):
return self._onchange_nuts(3)
@api.onchange('nuts2_id')
@api.onchange("nuts2_id")
def _onchange_nuts2_id(self):
return self._onchange_nuts(2)
@api.onchange('nuts1_id')
@api.onchange("nuts1_id")
def _onchange_nuts1_id(self):
return self._onchange_nuts(1)
@api.onchange('country_id')
@api.onchange("country_id")
def _onchange_country_id_base_location_nuts(self):
"""Sensible values and domains for related fields."""
fields = ['state_id', 'nuts1_id', 'nuts2_id', 'nuts3_id', 'nuts4_id']
country_domain = ([('country_id', '=', self.country_id.id)]
if self.country_id else [])
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:
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_id")
for field in fields:
level = int(field[4])
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)
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.onchange('state_id')
@api.onchange("state_id")
def onchange_state_id_base_location_nuts(self):
if self.state_id:
self.country_id = self.state_id.country_id
if self.state_id.country_id.state_level:
nuts_state = self.env['res.partner.nuts'].search([
('level', '=', self.state_id.country_id.state_level),
('state_id', '=', self.state_id.id)
], limit=1)
nuts_state = self.env["res.partner.nuts"].search(
[
("level", "=", self.state_id.country_id.state_level),
("state_id", "=", self.state_id.id),
],
limit=1,
)
if nuts_state:
field = 'nuts%d_id' % self.state_id.country_id.state_level
field = "nuts%d_id" % self.state_id.country_id.state_level
self[field] = nuts_state
@api.model
def _address_fields(self):
fields = super(ResPartner, self)._address_fields()
if fields:
fields += ['nuts1_id', 'nuts2_id', 'nuts3_id', 'nuts4_id']
fields += ["nuts1_id", "nuts2_id", "nuts3_id", "nuts4_id"]
return fields

28
base_location_nuts/models/res_partner_nuts.py

@ -6,25 +6,27 @@ from odoo import fields, models
class ResPartnerNuts(models.Model):
_name = 'res.partner.nuts'
_order = 'parent_path'
_parent_order = 'name'
_name = "res.partner.nuts"
_order = "parent_path"
_parent_order = "name"
_parent_store = True
_description = 'NUTS Item'
_description = "NUTS Item"
# NUTS fields
level = fields.Integer(required=True)
code = fields.Char(required=True)
name = fields.Char(required=True, translate=True)
country_id = fields.Many2one(comodel_name='res.country', string='Country',
required=True)
state_id = fields.Many2one(comodel_name='res.country.state',
string='State')
country_id = fields.Many2one(
comodel_name="res.country", string="Country", required=True
)
state_id = fields.Many2one(comodel_name="res.country.state", string="State")
not_updatable = fields.Boolean()
# Parent hierarchy
parent_id = fields.Many2one(comodel_name='res.partner.nuts',
ondelete='restrict')
parent_id = fields.Many2one(comodel_name="res.partner.nuts", ondelete="restrict")
parent_path = fields.Char(index=True)
child_ids = fields.One2many(comodel_name='res.partner.nuts',
inverse_name='parent_id', string='Children',
oldname='children')
child_ids = fields.One2many(
comodel_name="res.partner.nuts",
inverse_name="parent_id",
string="Children",
oldname="children",
)

69
base_location_nuts/tests/test_base_location_nuts.py

@ -1,39 +1,34 @@
# Copyright 2017 David Vidal <david.vidal@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests import common
from odoo.exceptions import UserError
from odoo.tests import common
class TestBaseLocationNuts(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(TestBaseLocationNuts, cls).setUpClass()
cls.importer = cls.env['nuts.import']
cls.importer = cls.env["nuts.import"]
cls.importer.run_import() # loads nuts
cls.country_1 = cls.env['res.country'].search([('code', '=', 'ES')])
cls.country_2 = cls.env['res.country'].search([('code', '=', 'PT')])
cls.nuts_model = cls.env['res.partner.nuts']
cls.nuts1_2 = cls.nuts_model.search([('code', '=', 'PT')])
cls.nuts2_1 = cls.nuts_model.search([('code', '=', 'ES2')])
cls.nuts3_1 = cls.nuts_model.search([('code', '=', 'ES24')])
cls.nuts4_1 = cls.nuts_model.search([('code', '=', 'ES243')])
cls.nuts4_2 = cls.nuts_model.search([('code', '=', 'ES300')])
cls.partner = cls.env['res.partner'].create({
'name': 'Test partner',
'country_id': cls.country_1.id,
})
cls.state_1 = cls.env['res.country.state'].create({
'name': 'Zaragoza Test',
'code': 'ZT',
'country_id': cls.country_1.id,
})
cls.country_1 = cls.env["res.country"].search([("code", "=", "ES")])
cls.country_2 = cls.env["res.country"].search([("code", "=", "PT")])
cls.nuts_model = cls.env["res.partner.nuts"]
cls.nuts1_2 = cls.nuts_model.search([("code", "=", "PT")])
cls.nuts2_1 = cls.nuts_model.search([("code", "=", "ES2")])
cls.nuts3_1 = cls.nuts_model.search([("code", "=", "ES24")])
cls.nuts4_1 = cls.nuts_model.search([("code", "=", "ES243")])
cls.nuts4_2 = cls.nuts_model.search([("code", "=", "ES300")])
cls.partner = cls.env["res.partner"].create(
{"name": "Test partner", "country_id": cls.country_1.id,}
)
cls.state_1 = cls.env["res.country.state"].create(
{"name": "Zaragoza Test", "code": "ZT", "country_id": cls.country_1.id,}
)
cls.nuts4_1.state_id = cls.state_1
cls.state_2 = cls.env['res.country.state'].create({
'name': 'Madrid Test',
'code': 'MT',
'country_id': cls.country_1.id,
})
cls.state_2 = cls.env["res.country.state"].create(
{"name": "Madrid Test", "code": "MT", "country_id": cls.country_1.id,}
)
cls.nuts4_2.state_id = cls.state_2
cls.country_1.state_level = 4
@ -45,12 +40,10 @@ class TestBaseLocationNuts(common.SavepointCase):
def test_onchange_nuts(self):
self.partner.country_id = self.country_2
self.partner._onchange_country_id_base_location_nuts()
self.assertEqual(self.partner.nuts1_id.country_id,
self.partner.country_id)
self.assertEqual(self.partner.nuts1_id.country_id, self.partner.country_id)
self.partner.nuts4_id = self.nuts4_1
self.partner._onchange_nuts4_id()
self.assertEqual(self.partner.country_id,
self.country_1)
self.assertEqual(self.partner.country_id, self.country_1)
self.assertEqual(self.partner.nuts3_id, self.nuts3_1)
self.partner._onchange_nuts3_id()
self.assertEqual(self.partner.nuts2_id, self.nuts2_1)
@ -80,18 +73,20 @@ class TestBaseLocationNuts(common.SavepointCase):
def test_download_exceptions(self):
""" Tests download exceptions """
with self.assertRaises(UserError):
self.importer._download_nuts(url_base='htttt://test.com')
self.importer._download_nuts(url_base="htttt://test.com")
with self.assertRaises(UserError):
self.importer._download_nuts(url_base='http://ec.europa.eu/_404')
self.importer._download_nuts(url_base="http://ec.europa.eu/_404")
def create_new_parent(self, orig_parent):
new_parent = self.nuts_model.create({
'level': orig_parent.level,
'code': 'NEW' + orig_parent.code,
'name': 'New parent',
'country_id': orig_parent.country_id.id,
'not_updatable': False
})
new_parent = self.nuts_model.create(
{
"level": orig_parent.level,
"code": "NEW" + orig_parent.code,
"name": "New parent",
"country_id": orig_parent.country_id.id,
"not_updatable": False,
}
)
return new_parent
def test_no_update(self):

30
base_location_nuts/views/res_country_view.xml

@ -1,19 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_country_form" model="ir.ui.view">
<field name="name">NUTS fields</field>
<field name="model">res.country</field>
<field name="inherit_id" ref="base.view_country_form"/>
<field name="arch" type="xml">
<xpath expr="/form">
<group name="nuts" string="NUTS">
<group>
<field name="state_level"/>
<record id="view_country_form" model="ir.ui.view">
<field name="name">NUTS fields</field>
<field name="model">res.country</field>
<field name="inherit_id" ref="base.view_country_form" />
<field name="arch" type="xml">
<xpath expr="/form">
<group name="nuts" string="NUTS">
<group>
<field name="state_level" />
</group>
</group>
</group>
</xpath>
</field>
</record>
</xpath>
</field>
</record>
</odoo>

134
base_location_nuts/views/res_partner_nuts_view.xml

@ -1,77 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="res_partner_nuts_tree" model="ir.ui.view">
<field name="name">NUTS Items tree</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<tree string="NUTS Items">
<field name="level"/>
<field name="code"/>
<field name="name"/>
</tree>
</field>
</record>
<record id="res_partner_nuts_form" model="ir.ui.view">
<field name="name">NUTS Items form</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<form string="NUTS Item">
<group>
<record id="res_partner_nuts_tree" model="ir.ui.view">
<field name="name">NUTS Items tree</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<tree string="NUTS Items">
<field name="level" />
<field name="code" />
<field name="name" />
</tree>
</field>
</record>
<record id="res_partner_nuts_form" model="ir.ui.view">
<field name="name">NUTS Items form</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<form string="NUTS Item">
<group>
<field name="level"/>
<field name="code"/>
<field name="parent_id"/>
<field name="name"/>
<field name="not_updatable"/>
<group>
<field name="level" />
<field name="code" />
<field name="parent_id" />
<field name="name" />
<field name="not_updatable" />
</group>
<group>
<field name="country_id" />
<field name="state_id" />
</group>
</group>
<group>
<field name="country_id"/>
<field name="state_id"/>
</group>
</group>
</form>
</field>
</record>
<record id="res_partner_nuts_action" model="ir.actions.act_window">
<field name="name">NUTS Items</field>
<field name="res_model">res.partner.nuts</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help">You must click at import wizard to populate NUTS items
</form>
</field>
</record>
<record id="res_partner_nuts_action" model="ir.actions.act_window">
<field name="name">NUTS Items</field>
<field name="res_model">res.partner.nuts</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help">You must click at import wizard to populate NUTS items
in Odoo database in:
Sales > Configuration > Address Book > Localization > Import NUTS 2013</field>
</record>
<record model="ir.ui.view" id="view_res_partner_nuts_filter">
<field name="name">NUTS search filters</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<search string="Search NUTS">
<field name="name"/>
<field name="country_id"/>
<field name="state_id"/>
<group expand="0" string="Group By">
<filter name="country"
</record>
<record model="ir.ui.view" id="view_res_partner_nuts_filter">
<field name="name">NUTS search filters</field>
<field name="model">res.partner.nuts</field>
<field name="arch" type="xml">
<search string="Search NUTS">
<field name="name" />
<field name="country_id" />
<field name="state_id" />
<group expand="0" string="Group By">
<filter
name="country"
string="Country"
domain="[]"
context="{'group_by': 'country_id'}"/>
<filter name="level"
context="{'group_by': 'country_id'}"
/>
<filter
name="level"
string="Level"
domain="[]"
context="{'group_by': 'level'}"/>
</group>
</search>
</field>
</record>
<menuitem action="res_partner_nuts_action"
id="res_partner_nuts_menu"
groups="base.group_partner_manager"
name="NUTS Items"
parent="contacts.menu_localisation"
sequence="40"/>
context="{'group_by': 'level'}"
/>
</group>
</search>
</field>
</record>
<menuitem
action="res_partner_nuts_action"
id="res_partner_nuts_menu"
groups="base.group_partner_manager"
name="NUTS Items"
parent="contacts.menu_localisation"
sequence="40"
/>
</odoo>

99
base_location_nuts/views/res_partner_view.xml

@ -1,57 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="ir.ui.view" id="view_partner_form_nuts">
<field name="name">Partner form with NUTS</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet/group//field[@name='country_id']/.." position="after">
<field name="nuts1_id"/>
<field name="nuts2_id"/>
<field name="nuts3_id"/>
<field name="nuts4_id"/>
</xpath>
<xpath expr="//field[@name='child_ids']/form//field[@name='country_id']/.." position="after">
<field name="nuts1_id"/>
<field name="nuts2_id"/>
<field name="nuts3_id"/>
<field name="nuts4_id"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="view_res_partner_filter_nuts">
<field name="name">Partner search with NUTS</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="arch" type="xml">
<field name="category_id" position="after">
<field name="nuts1_id"/>
<field name="nuts2_id"/>
<field name="nuts3_id"/>
<field name="nuts4_id"/>
<record model="ir.ui.view" id="view_partner_form_nuts">
<field name="name">Partner form with NUTS</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<xpath expr="//sheet/group//field[@name='country_id']/.." position="after">
<field name="nuts1_id" />
<field name="nuts2_id" />
<field name="nuts3_id" />
<field name="nuts4_id" />
</xpath>
<xpath
expr="//field[@name='child_ids']/form//field[@name='country_id']/.."
position="after"
>
<field name="nuts1_id" />
<field name="nuts2_id" />
<field name="nuts3_id" />
<field name="nuts4_id" />
</xpath>
</field>
<filter name="salesperson" position="after">
<filter name="nuts_l1"
</record>
<record model="ir.ui.view" id="view_res_partner_filter_nuts">
<field name="name">Partner search with NUTS</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter" />
<field name="arch" type="xml">
<field name="category_id" position="after">
<field name="nuts1_id" />
<field name="nuts2_id" />
<field name="nuts3_id" />
<field name="nuts4_id" />
</field>
<filter name="salesperson" position="after">
<filter
name="nuts_l1"
string="NUTS L1"
domain="[]"
context="{'group_by': 'nuts1_id'}"/>
<filter name="nuts_l2"
context="{'group_by': 'nuts1_id'}"
/>
<filter
name="nuts_l2"
string="NUTS L2"
domain="[]"
context="{'group_by': 'nuts2_id'}"/>
<filter name="nuts_l3"
context="{'group_by': 'nuts2_id'}"
/>
<filter
name="nuts_l3"
string="NUTS L3"
domain="[]"
context="{'group_by': 'nuts3_id'}"/>
<filter name="nuts_l4"
context="{'group_by': 'nuts3_id'}"
/>
<filter
name="nuts_l4"
string="NUTS L4"
domain="[]"
context="{'group_by': 'nuts4_id'}"/>
</filter>
</field>
</record>
context="{'group_by': 'nuts4_id'}"
/>
</filter>
</field>
</record>
</odoo>

172
base_location_nuts/wizard/nuts_import.py

@ -3,30 +3,33 @@
# Copyright 2017 David Vidal <jairo.llopis@tecnativa.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import _, api, models
from odoo.exceptions import UserError
import requests
import re
import logging
from lxml import etree
import re
from collections import OrderedDict
import requests
from lxml import etree
from odoo import _, api, models
from odoo.exceptions import UserError
logger = logging.getLogger(__name__)
# Default server values
URL_BASE = 'http://ec.europa.eu'
URL_PATH = '/eurostat/ramon/nomenclatures/index.cfm'
URL_PARAMS = {'TargetUrl': 'ACT_OTH_CLS_DLD',
'StrNom': 'NUTS_2013',
'StrFormat': 'XML',
'StrLanguageCode': 'EN',
'StrLayoutCode': 'HIERARCHIC'
}
URL_BASE = "http://ec.europa.eu"
URL_PATH = "/eurostat/ramon/nomenclatures/index.cfm"
URL_PARAMS = {
"TargetUrl": "ACT_OTH_CLS_DLD",
"StrNom": "NUTS_2013",
"StrFormat": "XML",
"StrLanguageCode": "EN",
"StrLayoutCode": "HIERARCHIC",
}
class NutsImport(models.TransientModel):
_name = 'nuts.import'
_description = 'Import NUTS items from European RAMON service'
_name = "nuts.import"
_description = "Import NUTS items from European RAMON service"
_parents = [False, False, False, False]
_countries = {
"BE": False,
@ -59,53 +62,65 @@ class NutsImport(models.TransientModel):
"GB": False, # UK
}
_current_country = False
_map = OrderedDict([
('level', {
'xpath': '', 'attrib': 'idLevel',
'type': 'integer', 'required': True}),
('code', {
'xpath': './Label/LabelText[@language="ALL"]',
'type': 'string', 'required': True}),
('name', {
'xpath': './Label/LabelText[@language="EN"]',
'type': 'string', 'required': True}),
])
_map = OrderedDict(
[
(
"level",
{"xpath": "", "attrib": "idLevel", "type": "integer", "required": True},
),
(
"code",
{
"xpath": './Label/LabelText[@language="ALL"]',
"type": "string",
"required": True,
},
),
(
"name",
{
"xpath": './Label/LabelText[@language="EN"]',
"type": "string",
"required": True,
},
),
]
)
def _check_node(self, node):
if node.get('id') and node.get('idLevel'):
if node.get("id") and node.get("idLevel"):
return True
return False
def _mapping(self, node):
item = {}
for k, v in self._map.items():
field_xpath = v.get('xpath', '')
field_attrib = v.get('attrib', False)
field_type = v.get('type', 'string')
field_required = v.get('required', False)
value = ''
field_xpath = v.get("xpath", "")
field_attrib = v.get("attrib", False)
field_type = v.get("type", "string")
field_required = v.get("required", False)
value = ""
if field_xpath:
n = node.find(field_xpath)
else:
n = node
if n is not None:
if field_attrib:
value = n.get(field_attrib, '')
value = n.get(field_attrib, "")
else:
value = n.text
if field_type == 'integer':
if field_type == "integer":
try:
value = int(value)
except (ValueError, TypeError):
logger.warn(
"Value %s for field %s replaced by 0" %
(value, k))
"Value {} for field {} replaced by 0".format(value, k)
)
value = 0
else:
logger.debug("xpath = '%s', not found" % field_xpath)
if field_required and not value:
raise UserError(
_('Value not found for mandatory field %s' % k))
raise UserError(_("Value not found for mandatory field %s" % k))
item[k] = value
return item
@ -116,48 +131,47 @@ class NutsImport(models.TransientModel):
url_path = URL_PATH
if not url_params:
url_params = URL_PARAMS
url = url_base + url_path + '?'
url += '&'.join([k + '=' + v for k, v in url_params.items()])
logger.info('Starting to download %s' % url)
url = url_base + url_path + "?"
url += "&".join([k + "=" + v for k, v in url_params.items()])
logger.info("Starting to download %s" % url)
try:
res_request = requests.get(url)
except Exception as e:
raise UserError(
_('Got an error when trying to download the file: %s.') %
str(e))
_("Got an error when trying to download the file: %s.") % str(e)
)
if res_request.status_code != requests.codes.ok:
raise UserError(
_('Got an error %d when trying to download the file %s.')
% (res_request.status_code, url))
logger.info('Download successfully %d bytes' %
len(res_request.content))
_("Got an error %d when trying to download the file %s.")
% (res_request.status_code, url)
)
logger.info("Download successfully %d bytes" % len(res_request.content))
# Workaround XML: Remove all characters before <?xml
pattern = re.compile(rb'^.*<\?xml', re.DOTALL)
content_fixed = re.sub(pattern, b'<?xml', res_request.content)
if not re.match(rb'<\?xml', content_fixed):
raise UserError(_('Downloaded file is not a valid XML file'))
pattern = re.compile(rb"^.*<\?xml", re.DOTALL)
content_fixed = re.sub(pattern, b"<?xml", res_request.content)
if not re.match(rb"<\?xml", content_fixed):
raise UserError(_("Downloaded file is not a valid XML file"))
return content_fixed
@api.model
def _load_countries(self):
for k in self._countries:
self._countries[k] = self.env['res.country'].search(
[('code', '=', k)])
self._countries[k] = self.env["res.country"].search([("code", "=", k)])
# Workaround to translate some country codes:
# EL => GR (Greece)
# UK => GB (United Kingdom)
self._countries['EL'] = self._countries['GR']
self._countries['UK'] = self._countries['GB']
self._countries["EL"] = self._countries["GR"]
self._countries["UK"] = self._countries["GB"]
@api.model
def state_mapping(self, data, node):
# Method to inherit and add state_id relation depending on country
level = data.get('level', 0)
code = data.get('code', '')
level = data.get("level", 0)
code = data.get("code", "")
if level == 1:
self._current_country = self._countries[code]
return {
'country_id': self._current_country.id,
"country_id": self._current_country.id,
}
@api.model
@ -165,14 +179,15 @@ class NutsImport(models.TransientModel):
if not self._check_node(node):
return False
nuts_model = self.env['res.partner.nuts']
nuts_model = self.env["res.partner.nuts"]
data = self._mapping(node)
data.update(self.state_mapping(data, node))
level = data.get('level', 0)
level = data.get("level", 0)
if level >= 2 and level <= 5:
data['parent_id'] = self._parents[level - 2]
nuts = nuts_model.search([('level', '=', data['level']),
('code', '=', data['code'])])
data["parent_id"] = self._parents[level - 2]
nuts = nuts_model.search(
[("level", "=", data["level"]), ("code", "=", data["code"])]
)
if nuts:
nuts.filtered(lambda n: not n.not_updatable).write(data)
else:
@ -183,30 +198,37 @@ class NutsImport(models.TransientModel):
@api.multi
def run_import(self):
nuts_model = self.env['res.partner.nuts'].\
with_context(defer_parent_store_computation=True)
nuts_model = self.env["res.partner.nuts"].with_context(
defer_parent_store_computation=True
)
self._load_countries()
# All current NUTS (for available countries),
# delete if not found above
nuts_to_delete = nuts_model.search(
[('country_id', 'in', [x.id for x in self._countries.values()]),
('not_updatable', '=', False)])
[
("country_id", "in", [x.id for x in self._countries.values()]),
("not_updatable", "=", False),
]
)
# Download NUTS in english, create or update
logger.info('Importing NUTS 2013 English...')
logger.info("Importing NUTS 2013 English...")
xmlcontent = self._download_nuts()
dom = etree.fromstring(xmlcontent)
for node in dom.iter('Item'):
logger.debug('Reading level=%s, id=%s',
node.get('idLevel', 'N/A'),
node.get('id', 'N/A'))
for node in dom.iter("Item"):
logger.debug(
"Reading level=%s, id=%s",
node.get("idLevel", "N/A"),
node.get("id", "N/A"),
)
nuts = self.create_or_update_nuts(node)
if nuts and nuts in nuts_to_delete:
nuts_to_delete -= nuts
# Delete obsolete NUTS
if nuts_to_delete:
logger.info('%d NUTS entries deleted' % len(nuts_to_delete))
logger.info("%d NUTS entries deleted" % len(nuts_to_delete))
nuts_to_delete.unlink()
logger.info(
'The wizard to create NUTS entries from RAMON '
'has been successfully completed.')
"The wizard to create NUTS entries from RAMON "
"has been successfully completed."
)
return True

79
base_location_nuts/wizard/nuts_import_view.xml

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="nuts_import_form" model="ir.ui.view">
<field name="name">NUTS import</field>
<field name="model">nuts.import</field>
<field name="arch" type="xml">
<form string="Import NUTS 2013 from RAMON">
<div>
<record id="nuts_import_form" model="ir.ui.view">
<field name="name">NUTS import</field>
<field name="model">nuts.import</field>
<field name="arch" type="xml">
<form string="Import NUTS 2013 from RAMON">
<div>
This wizard will download the lastest version of
NUTS 2013 from Europe RAMON metadata service.
Updating or creating new NUTS entries if not
@ -15,35 +14,37 @@
Update or deletion is prevented for NUTS entries with the flag 'Not updatable'.
</div>
<footer>
<button name="run_import" type="object"
class="oe_highlight" string="Import"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="nuts_import_action" model="ir.actions.act_window">
<field name="name">Import NUTS 2013 from RAMON</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">nuts.import</field>
<field name="view_id" ref="nuts_import_form"/>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem action="nuts_import_action"
id="nuts_import_menu"
name="Import NUTS 2013"
parent="contacts.menu_localisation"
sequence="45"/>
<record id="config_wizard_nuts" model="ir.actions.todo">
<field name="name">Import NUTS 2013 from RAMON</field>
<field name="action_id" ref="nuts_import_action"/>
<field name="sequence">20</field>
</record>
<footer>
<button
name="run_import"
type="object"
class="oe_highlight"
string="Import"
/>
<button special="cancel" string="Cancel" class="oe_link" />
</footer>
</form>
</field>
</record>
<record id="nuts_import_action" model="ir.actions.act_window">
<field name="name">Import NUTS 2013 from RAMON</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">nuts.import</field>
<field name="view_id" ref="nuts_import_form" />
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem
action="nuts_import_action"
id="nuts_import_menu"
name="Import NUTS 2013"
parent="contacts.menu_localisation"
sequence="45"
/>
<record id="config_wizard_nuts" model="ir.actions.todo">
<field name="name">Import NUTS 2013 from RAMON</field>
<field name="action_id" ref="nuts_import_action" />
<field name="sequence">20</field>
</record>
</odoo>
Loading…
Cancel
Save