mirror of
https://github.com/OCA/server-backend.git
synced 2025-02-18 09:52:42 +02:00
[IMP] base_import_match: black, isort, prettier
This commit is contained in:
committed by
Augusto Weiss
parent
0480ef2a5e
commit
d45407817b
@@ -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, "
|
"author": "Tecnativa, " "Odoo Community Association (OCA)",
|
||||||
"Odoo Community Association (OCA)",
|
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"application": False,
|
"application": False,
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"depends": [
|
"depends": ["base_import",],
|
||||||
"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": ["demo/base_import_match.xml",],
|
||||||
"demo/base_import_match.xml",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<!-- 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">
|
||||||
@@ -19,7 +18,6 @@
|
|||||||
<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')" />
|
||||||
@@ -29,5 +27,4 @@
|
|||||||
<field name="match_id" ref="base_import_match.res_users_login" />
|
<field name="match_id" ref="base_import_match.res_users_login" />
|
||||||
<field name="field_id" ref="base.field_res_users__login" />
|
<field name="field_id" ref="base.field_res_users__login" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -3,25 +3,32 @@
|
|||||||
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">
|
<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="match_id" ref="res_partner_parent_name_is_company" />
|
||||||
<field name="field_id" ref="base.field_res_partner__name" />
|
<field name="field_id" ref="base.field_res_partner__name" />
|
||||||
</record>
|
</record>
|
||||||
<record model="base_import.match.field" id="res_partner_parent_name_is_company_parent">
|
<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="match_id" ref="res_partner_parent_name_is_company" />
|
||||||
<field name="field_id" ref="base.field_res_partner__parent_id" />
|
<field name="field_id" ref="base.field_res_partner__parent_id" />
|
||||||
</record>
|
</record>
|
||||||
<record model="base_import.match.field" id="res_partner_parent_name_is_company_is_company">
|
<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="match_id" ref="res_partner_parent_name_is_company" />
|
||||||
<field name="field_id" ref="base.field_res_partner__is_company" />
|
<field name="field_id" ref="base.field_res_partner__is_company" />
|
||||||
</record>
|
</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')" />
|
||||||
@@ -31,7 +38,6 @@
|
|||||||
<field name="match_id" ref="base_import_match.res_partner_email" />
|
<field name="match_id" ref="base_import_match.res_partner_email" />
|
||||||
<field name="field_id" ref="base.field_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')" />
|
||||||
@@ -41,5 +47,4 @@
|
|||||||
<field name="match_id" ref="base_import_match.res_partner_name" />
|
<field name="match_id" ref="base_import_match.res_partner_name" />
|
||||||
<field name="field_id" ref="base.field_res_partner__name" />
|
<field name="field_id" ref="base.field_res_partner__name" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -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(
|
import_fields = list(map(models.fix_import_export_id_paths, fields))
|
||||||
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(
|
match = self.env["base_import.match"]._match_find(self, record, row)
|
||||||
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]
|
row["id"] = ext_id[match.id] if match else row.get("id", u"")
|
||||||
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
|
||||||
|
|||||||
@@ -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(
|
name = fields.Char(compute="_compute_name", store=True, index=True)
|
||||||
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",
|
string="Model name", related="model_id.model", store=True, index=True
|
||||||
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(
|
name = fields.Char(related="field_id.name")
|
||||||
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)
|
required=True,
|
||||||
model_id = fields.Many2one(
|
)
|
||||||
related="match_id.model_id")
|
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,
|
name=one.field_id.name, cond=one.imported_value,
|
||||||
cond=one.imported_value,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.onchange("field_id", "match_id", "conditional", "imported_value")
|
@api.onchange("field_id", "match_id", "conditional", "imported_value")
|
||||||
|
|||||||
@@ -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,
|
self.env.ref("base.res_partner_address_4").name, "Floyd Steward Changed"
|
||||||
"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,
|
self.env.ref("base.res_partner_address_4").function, "Function Changed"
|
||||||
"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.assertEqual(self.env.ref("base.user_demo").name, "Demo User Changed")
|
||||||
self.env.ref("base.user_demo").name,
|
|
||||||
"Demo User Changed")
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
<!-- 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>
|
||||||
@@ -18,11 +16,12 @@
|
|||||||
<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"
|
<field name="field_id" options="{'no_create': True}" />
|
||||||
options="{'no_create': True}"/>
|
<field
|
||||||
<field name="match_id"
|
name="match_id"
|
||||||
invisible="True"
|
invisible="True"
|
||||||
required="False"/>
|
required="False"
|
||||||
|
/>
|
||||||
<field name="model_id" invisible="True" />
|
<field name="model_id" invisible="True" />
|
||||||
<field name="conditional" />
|
<field name="conditional" />
|
||||||
<field
|
<field
|
||||||
@@ -31,7 +30,8 @@
|
|||||||
'readonly': [
|
'readonly': [
|
||||||
('conditional', '=', False),
|
('conditional', '=', False),
|
||||||
],
|
],
|
||||||
}"/>
|
}"
|
||||||
|
/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<field name="sequence" />
|
<field name="sequence" />
|
||||||
@@ -40,7 +40,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="match_tree_view" model="ir.ui.view">
|
<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>
|
||||||
@@ -51,7 +50,6 @@
|
|||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="match_search_view" model="ir.ui.view">
|
<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>
|
||||||
@@ -62,20 +60,15 @@
|
|||||||
<field name="field_ids" />
|
<field name="field_ids" />
|
||||||
<separator />
|
<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>
|
</record>
|
||||||
|
<act_window name="Import Match" res_model="base_import.match" id="match_action" />
|
||||||
<act_window
|
<menuitem id="match_menu" action="match_action" parent="base.next_id_9" />
|
||||||
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>
|
||||||
|
|||||||
Reference in New Issue
Block a user