Browse Source

[IMP] base_import_match: black, isort, prettier

14.0
Radovan Skolnik 4 years ago
committed by Jesus Ramoneda
parent
commit
e892b743d7
  1. 11
      base_import_match/__manifest__.py
  2. 21
      base_import_match/data/base_import_match.xml
  3. 51
      base_import_match/demo/base_import_match.xml
  4. 12
      base_import_match/models/base.py
  5. 39
      base_import_match/models/base_import.py
  6. 26
      base_import_match/tests/test_import.py
  7. 71
      base_import_match/views/base_import_match_view.xml

11
base_import_match/__manifest__.py

@ -7,20 +7,15 @@
"version": "12.0.1.0.0", "version": "12.0.1.0.0",
"category": "Tools", "category": "Tools",
"website": "https://tecnativa.com", "website": "https://tecnativa.com",
"author": "Tecnativa, "
"Odoo Community Association (OCA)",
"author": "Tecnativa, " "Odoo Community Association (OCA)",
"license": "AGPL-3", "license": "AGPL-3",
"application": False, "application": False,
"installable": True, "installable": True,
"depends": [
"base_import",
],
"depends": ["base_import",],
"data": [ "data": [
"security/ir.model.access.csv", "security/ir.model.access.csv",
"data/base_import_match.xml", "data/base_import_match.xml",
"views/base_import_match_view.xml", "views/base_import_match_view.xml",
], ],
"demo": [
"demo/base_import_match.xml",
],
"demo": ["demo/base_import_match.xml",],
} }

21
base_import_match/data/base_import_match.xml

@ -1,33 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis <!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis
Copyright 2016 Tecnativa - Vicent Cubells Copyright 2016 Tecnativa - Vicent Cubells
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo noupdate="1"> <odoo noupdate="1">
<!-- Match partners by VAT when is_company is True --> <!-- Match partners by VAT when is_company is True -->
<record model="base_import.match" id="res_partner_vat"> <record model="base_import.match" id="res_partner_vat">
<field name="model_id" eval="ref('base.model_res_partner')"/>
<field name="model_id" eval="ref('base.model_res_partner')" />
<field name="sequence" type="int">10</field> <field name="sequence" type="int">10</field>
</record> </record>
<record model="base_import.match.field" id="res_partner_vat_vat"> <record model="base_import.match.field" id="res_partner_vat_vat">
<field name="match_id" ref="base_import_match.res_partner_vat"/>
<field name="field_id" ref="base.field_res_partner__vat"/>
<field name="match_id" ref="base_import_match.res_partner_vat" />
<field name="field_id" ref="base.field_res_partner__vat" />
</record> </record>
<record model="base_import.match.field" id="res_partner_vat_is_company"> <record model="base_import.match.field" id="res_partner_vat_is_company">
<field name="match_id" ref="base_import_match.res_partner_vat"/>
<field name="field_id" ref="base.field_res_partner__is_company"/>
<field name="match_id" ref="base_import_match.res_partner_vat" />
<field name="field_id" ref="base.field_res_partner__is_company" />
<field name="conditional">True</field> <field name="conditional">True</field>
<field name="imported_value">True</field> <field name="imported_value">True</field>
</record> </record>
<!-- Match users by login --> <!-- Match users by login -->
<record model="base_import.match" id="res_users_login"> <record model="base_import.match" id="res_users_login">
<field name="model_id" eval="ref('base.model_res_users')"/>
<field name="model_id" eval="ref('base.model_res_users')" />
<field name="sequence" type="int">50</field> <field name="sequence" type="int">50</field>
</record> </record>
<record model="base_import.match.field" id="res_users_login_login"> <record model="base_import.match.field" id="res_users_login_login">
<field name="match_id" ref="base_import_match.res_users_login"/>
<field name="field_id" ref="base.field_res_users__login"/>
<field name="match_id" ref="base_import_match.res_users_login" />
<field name="field_id" ref="base.field_res_users__login" />
</record> </record>
</odoo> </odoo>

51
base_import_match/demo/base_import_match.xml

@ -1,45 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis <!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis
Copyright 2016 Tecnativa - Vicent Cubells Copyright 2016 Tecnativa - Vicent Cubells
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo noupdate="1"> <odoo noupdate="1">
<!-- Match partners by name, parent_id and is_company --> <!-- Match partners by name, parent_id and is_company -->
<record model="base_import.match" id="res_partner_parent_name_is_company"> <record model="base_import.match" id="res_partner_parent_name_is_company">
<field name="model_id" eval="ref('base.model_res_partner')"/>
<field name="model_id" eval="ref('base.model_res_partner')" />
<field name="sequence" type="int">20</field> <field name="sequence" type="int">20</field>
</record> </record>
<record model="base_import.match.field" id="res_partner_parent_name_is_company_name">
<field name="match_id" ref="res_partner_parent_name_is_company"/>
<field name="field_id" ref="base.field_res_partner__name"/>
<record
model="base_import.match.field"
id="res_partner_parent_name_is_company_name"
>
<field name="match_id" ref="res_partner_parent_name_is_company" />
<field name="field_id" ref="base.field_res_partner__name" />
</record>
<record
model="base_import.match.field"
id="res_partner_parent_name_is_company_parent"
>
<field name="match_id" ref="res_partner_parent_name_is_company" />
<field name="field_id" ref="base.field_res_partner__parent_id" />
</record>
<record
model="base_import.match.field"
id="res_partner_parent_name_is_company_is_company"
>
<field name="match_id" ref="res_partner_parent_name_is_company" />
<field name="field_id" ref="base.field_res_partner__is_company" />
</record> </record>
<record model="base_import.match.field" id="res_partner_parent_name_is_company_parent">
<field name="match_id" ref="res_partner_parent_name_is_company"/>
<field name="field_id" ref="base.field_res_partner__parent_id"/>
</record>
<record model="base_import.match.field" id="res_partner_parent_name_is_company_is_company">
<field name="match_id" ref="res_partner_parent_name_is_company"/>
<field name="field_id" ref="base.field_res_partner__is_company"/>
</record>
<!-- Match partner by email --> <!-- Match partner by email -->
<record model="base_import.match" id="res_partner_email"> <record model="base_import.match" id="res_partner_email">
<field name="model_id" eval="ref('base.model_res_partner')"/>
<field name="model_id" eval="ref('base.model_res_partner')" />
<field name="sequence" type="int">30</field> <field name="sequence" type="int">30</field>
</record> </record>
<record model="base_import.match.field" id="res_partner_email_email"> <record model="base_import.match.field" id="res_partner_email_email">
<field name="match_id" ref="base_import_match.res_partner_email"/>
<field name="field_id" ref="base.field_res_partner__email"/>
<field name="match_id" ref="base_import_match.res_partner_email" />
<field name="field_id" ref="base.field_res_partner__email" />
</record> </record>
<!-- Match partner by name --> <!-- Match partner by name -->
<record model="base_import.match" id="res_partner_name"> <record model="base_import.match" id="res_partner_name">
<field name="model_id" eval="ref('base.model_res_partner')"/>
<field name="model_id" eval="ref('base.model_res_partner')" />
<field name="sequence" type="int">40</field> <field name="sequence" type="int">40</field>
</record> </record>
<record model="base_import.match.field" id="res_partner_name_name"> <record model="base_import.match.field" id="res_partner_name_name">
<field name="match_id" ref="base_import_match.res_partner_name"/>
<field name="field_id" ref="base.field_res_partner__name"/>
<field name="match_id" ref="base_import_match.res_partner_name" />
<field name="field_id" ref="base.field_res_partner__name" />
</record> </record>
</odoo> </odoo>

12
base_import_match/models/base.py

@ -19,10 +19,10 @@ class Base(models.AbstractModel):
if self.env["base_import.match"]._usable_rules(self._name, fields): if self.env["base_import.match"]._usable_rules(self._name, fields):
newdata = list() newdata = list()
# Data conversion to ORM format # Data conversion to ORM format
import_fields = list(
map(models.fix_import_export_id_paths, fields))
import_fields = list(map(models.fix_import_export_id_paths, fields))
converted_data = self._convert_records( converted_data = self._convert_records(
self._extract_records(import_fields, data))
self._extract_records(import_fields, data)
)
# Mock Odoo to believe the user is importing the ID field # Mock Odoo to believe the user is importing the ID field
if "id" not in fields: if "id" not in fields:
fields.append("id") fields.append("id")
@ -41,14 +41,12 @@ class Base(models.AbstractModel):
match = self.browse(dbid) match = self.browse(dbid)
else: else:
# Store records that match a combination # Store records that match a combination
match = self.env["base_import.match"]._match_find(
self, record, row)
match = self.env["base_import.match"]._match_find(self, record, row)
# Give a valid XMLID to this row if a match was found # Give a valid XMLID to this row if a match was found
# To generate externals IDS. # To generate externals IDS.
match.export_data(fields) match.export_data(fields)
ext_id = match.get_external_id() ext_id = match.get_external_id()
row["id"] = (ext_id[match.id]
if match else row.get("id", u""))
row["id"] = ext_id[match.id] if match else row.get("id", u"")
# Store the modified row, in the same order as fields # Store the modified row, in the same order as fields
newdata.append(tuple(row[f] for f in clean_fields)) newdata.append(tuple(row[f] for f in clean_fields))
# We will import the patched data to get updates on matches # We will import the patched data to get updates on matches

39
base_import_match/models/base_import.py

@ -2,6 +2,7 @@
# Copyright 2016 Tecnativa - Vicent Cubells # Copyright 2016 Tecnativa - Vicent Cubells
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging import logging
from odoo import api, fields, models, tools from odoo import api, fields, models, tools
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -12,10 +13,7 @@ class BaseImportMatch(models.Model):
_description = "Deduplicate settings prior to CSV imports." _description = "Deduplicate settings prior to CSV imports."
_order = "sequence, name" _order = "sequence, name"
name = fields.Char(
compute="_compute_name",
store=True,
index=True)
name = fields.Char(compute="_compute_name", store=True, index=True)
sequence = fields.Integer(index=True) sequence = fields.Integer(index=True)
model_id = fields.Many2one( model_id = fields.Many2one(
"ir.model", "ir.model",
@ -23,18 +21,18 @@ class BaseImportMatch(models.Model):
required=True, required=True,
ondelete="cascade", ondelete="cascade",
domain=[("transient", "=", False)], domain=[("transient", "=", False)],
help="In this model you will apply the match.")
help="In this model you will apply the match.",
)
model_name = fields.Char( model_name = fields.Char(
string="Model name",
related="model_id.model",
store=True,
index=True)
string="Model name", related="model_id.model", store=True, index=True
)
field_ids = fields.One2many( field_ids = fields.One2many(
comodel_name="base_import.match.field", comodel_name="base_import.match.field",
inverse_name="match_id", inverse_name="match_id",
string="Fields", string="Fields",
required=True, required=True,
help="Fields that will define an unique key.")
help="Fields that will define an unique key.",
)
@api.onchange("model_id") @api.onchange("model_id")
def _onchange_model_id(self): def _onchange_model_id(self):
@ -135,37 +133,38 @@ class BaseImportMatchField(models.Model):
_name = "base_import.match.field" _name = "base_import.match.field"
_description = "Field import match definition" _description = "Field import match definition"
name = fields.Char(
related="field_id.name")
name = fields.Char(related="field_id.name")
field_id = fields.Many2one( field_id = fields.Many2one(
comodel_name="ir.model.fields", comodel_name="ir.model.fields",
string="Field", string="Field",
required=True, required=True,
ondelete="cascade", ondelete="cascade",
domain="[('model_id', '=', model_id)]", domain="[('model_id', '=', model_id)]",
help="Field that will be part of an unique key.")
help="Field that will be part of an unique key.",
)
match_id = fields.Many2one( match_id = fields.Many2one(
comodel_name="base_import.match", comodel_name="base_import.match",
string="Match", string="Match",
ondelete="cascade", ondelete="cascade",
required=True)
model_id = fields.Many2one(
related="match_id.model_id")
required=True,
)
model_id = fields.Many2one(related="match_id.model_id")
conditional = fields.Boolean( conditional = fields.Boolean(
help="Enable if you want to use this field only in some conditions.")
help="Enable if you want to use this field only in some conditions."
)
imported_value = fields.Char( imported_value = fields.Char(
help="If the imported value is not this, the whole matching rule will " help="If the imported value is not this, the whole matching rule will "
"be discarded. Be careful, this data is always treated as a " "be discarded. Be careful, this data is always treated as a "
"string, and comparison is case-sensitive so if you set 'True', " "string, and comparison is case-sensitive so if you set 'True', "
"it will NOT match '1' nor 'true', only EXACTLY 'True'.")
"it will NOT match '1' nor 'true', only EXACTLY 'True'."
)
@api.depends("conditional", "field_id", "imported_value") @api.depends("conditional", "field_id", "imported_value")
def _compute_display_name(self): def _compute_display_name(self):
for one in self: for one in self:
pattern = u"{name} ({cond})" if one.conditional else u"{name}" pattern = u"{name} ({cond})" if one.conditional else u"{name}"
one.display_name = pattern.format( one.display_name = pattern.format(
name=one.field_id.name,
cond=one.imported_value,
name=one.field_id.name, cond=one.imported_value,
) )
@api.onchange("field_id", "match_id", "conditional", "imported_value") @api.onchange("field_id", "match_id", "conditional", "imported_value")

26
base_import_match/tests/test_import.py

@ -3,8 +3,8 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from os import path from os import path
from odoo.tests.common import TransactionCase
from odoo.tests.common import TransactionCase
PATH = path.join(path.dirname(__file__), "import_data", "%s.csv") PATH = path.join(path.dirname(__file__), "import_data", "%s.csv")
OPTIONS = { OPTIONS = {
@ -18,12 +18,14 @@ class ImportCase(TransactionCase):
def _base_import_record(self, res_model, file_name): def _base_import_record(self, res_model, file_name):
"""Create and return a ``base_import.import`` record.""" """Create and return a ``base_import.import`` record."""
with open(PATH % file_name) as demo_file: with open(PATH % file_name) as demo_file:
return self.env["base_import.import"].create({
return self.env["base_import.import"].create(
{
"res_model": res_model, "res_model": res_model,
"file": demo_file.read(), "file": demo_file.read(),
"file_name": "%s.csv" % file_name, "file_name": "%s.csv" % file_name,
"file_type": "csv", "file_type": "csv",
})
}
)
def test_res_partner_vat(self): def test_res_partner_vat(self):
"""Change name based on VAT.""" """Change name based on VAT."""
@ -37,32 +39,32 @@ class ImportCase(TransactionCase):
def test_res_partner_parent_name_is_company(self): def test_res_partner_parent_name_is_company(self):
"""Change email based on parent_id, name and is_company.""" """Change email based on parent_id, name and is_company."""
record = self._base_import_record( record = self._base_import_record(
"res.partner", "res_partner_parent_name_is_company")
"res.partner", "res_partner_parent_name_is_company"
)
record.do(["name", "is_company", "parent_id/id", "email"], [], OPTIONS) record.do(["name", "is_company", "parent_id/id", "email"], [], OPTIONS)
self.assertEqual( self.assertEqual(
self.env.ref("base.res_partner_address_4").email, self.env.ref("base.res_partner_address_4").email,
"floyd.steward34.changed@example.com")
"floyd.steward34.changed@example.com",
)
def test_res_partner_email(self): def test_res_partner_email(self):
"""Change name based on email.""" """Change name based on email."""
record = self._base_import_record("res.partner", "res_partner_email") record = self._base_import_record("res.partner", "res_partner_email")
record.do(["email", "name"], [], OPTIONS) record.do(["email", "name"], [], OPTIONS)
self.assertEqual( self.assertEqual(
self.env.ref("base.res_partner_address_4").name,
"Floyd Steward Changed")
self.env.ref("base.res_partner_address_4").name, "Floyd Steward Changed"
)
def test_res_partner_name(self): def test_res_partner_name(self):
"""Change function based on name.""" """Change function based on name."""
record = self._base_import_record("res.partner", "res_partner_name") record = self._base_import_record("res.partner", "res_partner_name")
record.do(["function", "name"], [], OPTIONS) record.do(["function", "name"], [], OPTIONS)
self.assertEqual( self.assertEqual(
self.env.ref("base.res_partner_address_4").function,
"Function Changed")
self.env.ref("base.res_partner_address_4").function, "Function Changed"
)
def test_res_users_login(self): def test_res_users_login(self):
"""Change name based on login.""" """Change name based on login."""
record = self._base_import_record("res.users", "res_users_login") record = self._base_import_record("res.users", "res_users_login")
record.do(["login", "name"], [], OPTIONS) record.do(["login", "name"], [], OPTIONS)
self.assertEqual(
self.env.ref("base.user_demo").name,
"Demo User Changed")
self.assertEqual(self.env.ref("base.user_demo").name, "Demo User Changed")

71
base_import_match/views/base_import_match_view.xml

@ -1,81 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis <!-- Copyright 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis
Copyright 2016 Tecnativa - Vicent Cubells Copyright 2016 Tecnativa - Vicent Cubells
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
<odoo> <odoo>
<record id="match_form_view" model="ir.ui.view">
<record id="match_form_view" model="ir.ui.view">
<field name="name">Import match form view</field> <field name="name">Import match form view</field>
<field name="model">base_import.match</field> <field name="model">base_import.match</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Import Match"> <form string="Import Match">
<sheet> <sheet>
<h1> <h1>
<field name="name"/>
<field name="name" />
</h1> </h1>
<group> <group>
<field name="model_id"/>
<field name="model_id" />
<field name="field_ids"> <field name="field_ids">
<tree editable="bottom"> <tree editable="bottom">
<field name="field_id"
options="{'no_create': True}"/>
<field name="match_id"
<field name="field_id" options="{'no_create': True}" />
<field
name="match_id"
invisible="True" invisible="True"
required="False"/>
<field name="model_id" invisible="True"/>
<field name="conditional"/>
required="False"
/>
<field name="model_id" invisible="True" />
<field name="conditional" />
<field <field
name="imported_value" name="imported_value"
attrs="{ attrs="{
'readonly': [ 'readonly': [
('conditional', '=', False), ('conditional', '=', False),
], ],
}"/>
}"
/>
</tree> </tree>
</field> </field>
<field name="sequence"/>
<field name="sequence" />
</group> </group>
</sheet> </sheet>
</form> </form>
</field> </field>
</record>
<record id="match_tree_view" model="ir.ui.view">
</record>
<record id="match_tree_view" model="ir.ui.view">
<field name="name">Import match tree view</field> <field name="name">Import match tree view</field>
<field name="model">base_import.match</field> <field name="model">base_import.match</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Import Match"> <tree string="Import Match">
<field name="name"/>
<field name="sequence" invisible="True"/>
<field name="name" />
<field name="sequence" invisible="True" />
</tree> </tree>
</field> </field>
</record>
<record id="match_search_view" model="ir.ui.view">
</record>
<record id="match_search_view" model="ir.ui.view">
<field name="name">Import match search view</field> <field name="name">Import match search view</field>
<field name="model">base_import.match</field> <field name="model">base_import.match</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Import Match"> <search string="Import Match">
<field name="name"/>
<field name="model_id"/>
<field name="field_ids"/>
<separator/>
<field name="name" />
<field name="model_id" />
<field name="field_ids" />
<separator />
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter string="Model" context="{'group_by': 'model_id'}" name="model"/>
<filter
string="Model"
context="{'group_by': 'model_id'}"
name="model"
/>
</group> </group>
</search> </search>
</field> </field>
</record>
<act_window
name="Import Match"
res_model="base_import.match"
id="match_action"/>
<menuitem
id="match_menu"
action="match_action"
parent="base.next_id_9"/>
</record>
<act_window name="Import Match" res_model="base_import.match" id="match_action" />
<menuitem id="match_menu" action="match_action" parent="base.next_id_9" />
</odoo> </odoo>
Loading…
Cancel
Save