mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-20 05:12:04 +02:00
935 lines
30 KiB
Python
935 lines
30 KiB
Python
# Copyright 2013 Camptocamp SA
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
|
|
|
from unittest import mock
|
|
|
|
from odoo.addons.component.core import Component, WorkContext
|
|
from odoo.addons.component.tests.common import TransactionComponentRegistryCase
|
|
from odoo.addons.connector.components.mapper import (
|
|
MapOptions,
|
|
MappingDefinition,
|
|
changed_by,
|
|
convert,
|
|
external_to_m2o,
|
|
follow_m2o_relations,
|
|
m2o_to_external,
|
|
mapping,
|
|
none,
|
|
only_create,
|
|
)
|
|
|
|
|
|
class TestMapper(TransactionComponentRegistryCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self._setup_registry(self)
|
|
self.comp_registry.load_components("connector")
|
|
|
|
def test_mapping_decorator(self):
|
|
class KifKrokerMapper(Component):
|
|
_name = "kif.kroker.mapper"
|
|
_inherit = "base.mapper"
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
@only_create
|
|
def name(self):
|
|
pass
|
|
|
|
@changed_by("email")
|
|
@mapping
|
|
def email(self):
|
|
pass
|
|
|
|
@changed_by("street")
|
|
@mapping
|
|
def street(self):
|
|
pass
|
|
|
|
def no_decorator(self):
|
|
pass
|
|
|
|
# build our mapper component
|
|
KifKrokerMapper._build_component(self.comp_registry)
|
|
|
|
# what mappings we expect
|
|
name_def = MappingDefinition(changed_by={"name", "city"}, only_create=True)
|
|
email_def = MappingDefinition(changed_by={"email"}, only_create=False)
|
|
street_def = MappingDefinition(changed_by={"street"}, only_create=False)
|
|
|
|
# get our component by name in the components registry
|
|
comp = self.comp_registry["kif.kroker.mapper"]
|
|
# _map_methods contains the aggregated mapping methods for a Mapper
|
|
self.assertEqual(
|
|
comp._map_methods,
|
|
{"name": name_def, "email": email_def, "street": street_def},
|
|
)
|
|
|
|
def test_mapping_decorator_cross_classes(self):
|
|
"""Mappings should not propagate to other classes"""
|
|
|
|
class MomMapper(Component):
|
|
_name = "mom.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
class ZappMapper(Component):
|
|
_name = "zapp.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("email")
|
|
@only_create
|
|
@mapping
|
|
def email(self):
|
|
pass
|
|
|
|
self._build_components(MomMapper, ZappMapper)
|
|
|
|
mom_def = MappingDefinition(changed_by={"name", "city"}, only_create=False)
|
|
zapp_def = MappingDefinition(changed_by={"email"}, only_create=True)
|
|
|
|
comp = self.comp_registry["mom.mapper"]
|
|
self.assertEqual(comp._map_methods, {"name": mom_def})
|
|
comp = self.comp_registry["zapp.mapper"]
|
|
self.assertEqual(comp._map_methods, {"email": zapp_def})
|
|
|
|
def test_mapping_decorator_cumul(self):
|
|
"""Mappings should cumulate the ``super`` mappings
|
|
and the local mappings."""
|
|
|
|
class FryMapper(Component):
|
|
_name = "fry.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
# pylint: disable=R7980
|
|
class FryMapperInherit(Component):
|
|
_inherit = "fry.mapper"
|
|
|
|
@changed_by("email")
|
|
@mapping
|
|
def email(self):
|
|
pass
|
|
|
|
self._build_components(FryMapper, FryMapperInherit)
|
|
|
|
name_def = MappingDefinition(changed_by={"name", "city"}, only_create=False)
|
|
email_def = MappingDefinition(changed_by={"email"}, only_create=False)
|
|
|
|
comp = self.comp_registry["fry.mapper"]
|
|
self.assertEqual(comp._map_methods, {"name": name_def, "email": email_def})
|
|
|
|
def test_mapping_decorator_cumul_changed_by(self):
|
|
"""Mappings should cumulate the changed_by fields of the
|
|
``super`` mappings and the local mappings"""
|
|
|
|
class FryMapper(Component):
|
|
_name = "fry.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
class FryMapperInherit(Component):
|
|
_inherit = ( # pylint: disable=consider-merging-classes-inherited
|
|
"fry.mapper"
|
|
)
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("email")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
class ThirdMapper(Component):
|
|
_name = "third.mapper"
|
|
_inherit = "fry.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("email", "street")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
self._build_components(FryMapper, FryMapperInherit, ThirdMapper)
|
|
|
|
name_def = MappingDefinition(
|
|
changed_by={"name", "city", "email"}, only_create=False
|
|
)
|
|
|
|
comp = self.comp_registry["fry.mapper"]
|
|
self.assertEqual(comp._map_methods, {"name": name_def})
|
|
|
|
name_def = MappingDefinition(
|
|
changed_by={"name", "city", "email", "street"}, only_create=False
|
|
)
|
|
comp = self.comp_registry["third.mapper"]
|
|
self.assertEqual(comp._map_methods, {"name": name_def})
|
|
|
|
def test_several_bases_cumul(self):
|
|
class FryMapper(Component):
|
|
_name = "fry.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
@only_create
|
|
@mapping
|
|
def street(self):
|
|
pass
|
|
|
|
@only_create
|
|
@mapping
|
|
def zip(self):
|
|
pass
|
|
|
|
class FarnsworthMapper(Component):
|
|
_name = "farnsworth.mapper"
|
|
_inherit = "base.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("email")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
@changed_by("street")
|
|
@mapping
|
|
def city(self):
|
|
pass
|
|
|
|
@mapping
|
|
def zip(self):
|
|
pass
|
|
|
|
class ThirdMapper(Component):
|
|
_name = "third.mapper"
|
|
_inherit = ["fry.mapper", "farnsworth.mapper"]
|
|
_apply_on = "res.users"
|
|
|
|
@changed_by("email", "street")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
@mapping
|
|
def email(self):
|
|
pass
|
|
|
|
self._build_components(FryMapper, FarnsworthMapper, ThirdMapper)
|
|
|
|
name_def = MappingDefinition(
|
|
changed_by={"name", "city", "email", "street"}, only_create=False
|
|
)
|
|
street_def = MappingDefinition(changed_by=set(), only_create=True)
|
|
city_def = MappingDefinition(changed_by={"street"}, only_create=False)
|
|
email_def = MappingDefinition(changed_by=set(), only_create=False)
|
|
zip_def = MappingDefinition(changed_by=set(), only_create=True)
|
|
|
|
comp = self.comp_registry["third.mapper"]
|
|
self.assertEqual(comp._map_methods["name"], name_def)
|
|
self.assertEqual(comp._map_methods["street"], street_def)
|
|
self.assertEqual(comp._map_methods["city"], city_def)
|
|
self.assertEqual(comp._map_methods["email"], email_def)
|
|
self.assertEqual(comp._map_methods["zip"], zip_def)
|
|
|
|
def test_mapping_record(self):
|
|
"""Map a record and check the result"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
direct = [("name", "out_name")]
|
|
|
|
@mapping
|
|
def street(self, record):
|
|
return {"out_street": record["street"].upper()}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen", "street": "street"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Guewen", "out_street": "STREET"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_record_on_create(self):
|
|
"""Map a record and check the result for creation of record"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.users"
|
|
|
|
direct = [("name", "out_name")]
|
|
|
|
@mapping
|
|
def street(self, record):
|
|
return {"out_street": record["street"].upper()}
|
|
|
|
@only_create
|
|
@mapping
|
|
def city(self, record):
|
|
return {"out_city": "city"}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen", "street": "street"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Guewen", "out_street": "STREET"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
expected = {"out_name": "Guewen", "out_street": "STREET", "out_city": "city"}
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_update(self):
|
|
"""Force values on a map record"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [("name", "out_name")]
|
|
|
|
@mapping
|
|
def street(self, record):
|
|
return {"out_street": record["street"].upper()}
|
|
|
|
@only_create
|
|
@mapping
|
|
def city(self, record):
|
|
return {"out_city": "city"}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen", "street": "street"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
map_record.update({"test": 1}, out_city="forced")
|
|
expected = {
|
|
"out_name": "Guewen",
|
|
"out_street": "STREET",
|
|
"out_city": "forced",
|
|
"test": 1,
|
|
}
|
|
self.assertEqual(map_record.values(), expected)
|
|
expected = {
|
|
"out_name": "Guewen",
|
|
"out_street": "STREET",
|
|
"out_city": "forced",
|
|
"test": 1,
|
|
}
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
# pylint: disable=W8110
|
|
def test_finalize(self):
|
|
"""Inherit finalize to modify values"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [("name", "out_name")]
|
|
|
|
def finalize(self, record, values):
|
|
result = super().finalize(record, values)
|
|
result["test"] = "abc"
|
|
return result
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen", "street": "street"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Guewen", "test": "abc"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
expected = {"out_name": "Guewen", "test": "abc"}
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_some_fields(self):
|
|
"""Map only a selection of fields"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [("name", "out_name"), ("street", "out_street")]
|
|
|
|
@changed_by("country")
|
|
@mapping
|
|
def country(self, record):
|
|
return {"country": "country"}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen", "street": "street", "country": "country"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Guewen", "country": "country"}
|
|
self.assertEqual(map_record.values(fields=["name", "country"]), expected)
|
|
expected = {"out_name": "Guewen", "country": "country"}
|
|
self.assertEqual(
|
|
map_record.values(for_create=True, fields=["name", "country"]), expected
|
|
)
|
|
|
|
def test_mapping_modifier(self):
|
|
"""Map a direct record with a modifier function"""
|
|
|
|
def do_nothing(field):
|
|
def transform(self, record, to_attr):
|
|
return record[field]
|
|
|
|
return transform
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [(do_nothing("name"), "out_name")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Guewen"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Guewen"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_direct_property(self):
|
|
"""Map a direct record with 'direct' being a property"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
@property
|
|
def direct(self):
|
|
return [("name", "out_name")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "Foo"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": "Foo"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_convert(self):
|
|
"""Map a direct record with the convert modifier function"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [(convert("name", int), "out_name")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "300"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": 300}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_modifier_none(self):
|
|
"""Pipeline of modifiers"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [(none("in_f"), "out_f"), (none("in_t"), "out_t")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"in_f": False, "in_t": True}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_f": None, "out_t": True}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_modifier_pipeline(self):
|
|
"""Pipeline of modifiers"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [
|
|
(none(convert("in_f", bool)), "out_f"),
|
|
(none(convert("in_t", bool)), "out_t"),
|
|
]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"in_f": 0, "in_t": 1}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_f": None, "out_t": True}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_modifier_import_filter_field(self):
|
|
"""A direct mapping with a modifier must still be considered
|
|
from the list of fields
|
|
"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [
|
|
("field", "field2"),
|
|
("no_field", "no_field2"),
|
|
(convert("name", int), "out_name"),
|
|
]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "300", "field": "value", "no_field": "no_value"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": 300, "field2": "value"}
|
|
self.assertEqual(map_record.values(fields=["field", "name"]), expected)
|
|
self.assertEqual(
|
|
map_record.values(for_create=True, fields=["field", "name"]), expected
|
|
)
|
|
|
|
def test_modifier_export_filter_field(self):
|
|
"""A direct mapping with a modifier on an export mapping"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.export.mapper"
|
|
|
|
direct = [
|
|
("field", "field2"),
|
|
("no_field", "no_field2"),
|
|
(convert("name", int), "out_name"),
|
|
]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"name": "300", "field": "value", "no_field": "no_value"}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"out_name": 300, "field2": "value"}
|
|
self.assertEqual(map_record.values(fields=["field", "name"]), expected)
|
|
self.assertEqual(
|
|
map_record.values(for_create=True, fields=["field", "name"]), expected
|
|
)
|
|
|
|
def test_mapping_custom_option(self):
|
|
"""Usage of custom options in mappings"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
@mapping
|
|
def any(self, record):
|
|
if self.options.custom:
|
|
res = True
|
|
else:
|
|
res = False
|
|
return {"res": res}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"res": True}
|
|
self.assertEqual(map_record.values(custom=True), expected)
|
|
|
|
def test_mapping_custom_option_not_defined(self):
|
|
"""Usage of custom options not defined raise AttributeError"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
@mapping
|
|
def any(self, record):
|
|
if self.options.custom is None:
|
|
res = True
|
|
else:
|
|
res = False
|
|
return {"res": res}
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {}
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {"res": True}
|
|
self.assertEqual(map_record.values(), expected)
|
|
|
|
def test_map_options(self):
|
|
"""Test MapOptions"""
|
|
options = MapOptions({"xyz": "abc"}, k=1)
|
|
options.l = 2 # noqa: E741
|
|
self.assertEqual(options["xyz"], "abc")
|
|
self.assertEqual(options["k"], 1)
|
|
self.assertEqual(options["l"], 2)
|
|
self.assertEqual(options.xyz, "abc")
|
|
self.assertEqual(options.k, 1)
|
|
self.assertEqual(options.l, 2)
|
|
self.assertEqual(options["undefined"], None)
|
|
self.assertEqual(options.undefined, None)
|
|
|
|
def test_changed_by_fields(self):
|
|
"""Test attribute ``_changed_by_fields`` on Mapper."""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.export.mapper"
|
|
|
|
direct = [
|
|
("street", "out_street"),
|
|
(none("in_t"), "out_t"),
|
|
(none(convert("in_f", bool)), "out_f"),
|
|
]
|
|
|
|
@changed_by("name", "city")
|
|
@mapping
|
|
def name(self):
|
|
pass
|
|
|
|
@changed_by("email")
|
|
@mapping
|
|
def email(self):
|
|
pass
|
|
|
|
def no_decorator(self):
|
|
pass
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
work = mock.MagicMock(name="WorkContext()")
|
|
mapper = self.comp_registry["my.mapper"](work)
|
|
|
|
self.assertEqual(
|
|
mapper.changed_by_fields(),
|
|
{"street", "in_t", "in_f", "name", "city", "email"},
|
|
)
|
|
|
|
|
|
class TestMapperRecordsets(TransactionComponentRegistryCase):
|
|
"""Test mapper with "real" records instead of mocks"""
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self._setup_registry(self)
|
|
self.comp_registry.load_components("connector")
|
|
|
|
backend_record = mock.Mock()
|
|
backend_record.env = self.env
|
|
self.work = WorkContext(
|
|
model_name="res.partner",
|
|
collection=backend_record,
|
|
components_registry=self.comp_registry,
|
|
)
|
|
|
|
def test_mapping_modifier_follow_m2o_relations(self):
|
|
"""Map with the follow_m2o_relations modifier"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
|
|
direct = [(follow_m2o_relations("parent_id.name"), "parent_name")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
partner = self.env.ref("base.res_partner_address_4")
|
|
mapper = self.comp_registry["my.mapper"](self.work)
|
|
map_record = mapper.map_record(partner)
|
|
expected = {"parent_name": "Deco Addict"}
|
|
self.assertEqual(map_record.values(), expected)
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
|
|
class TestMapperBinding(TransactionComponentRegistryCase):
|
|
"""Test Mapper with Bindings"""
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self._setup_registry(self)
|
|
self.comp_registry.load_components("connector")
|
|
|
|
backend_record = mock.Mock()
|
|
backend_record.env = self.env
|
|
backend_record._name = "my.collection"
|
|
self.work = WorkContext(
|
|
model_name="res.partner",
|
|
collection=backend_record,
|
|
components_registry=self.comp_registry,
|
|
)
|
|
|
|
self.country_binder = mock.MagicMock(name="country_binder")
|
|
self.country_binder.return_value = self.country_binder
|
|
self.country_binder._name = "test.binder"
|
|
self.country_binder._inherit = "base.binder"
|
|
self.country_binder.apply_on_models = ["res.country"]
|
|
self.country_binder._usage = "binder"
|
|
self.country_binder._collection = "my.collection"
|
|
self.country_binder._abstract = False
|
|
self.comp_registry["test.binder"] = self.country_binder
|
|
|
|
def test_mapping_m2o_to_external(self):
|
|
"""Map a direct record with the m2o_to_external modifier function"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.partner"
|
|
|
|
direct = [(m2o_to_external("country_id"), "country")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
partner = self.env.ref("base.main_partner")
|
|
partner.write({"country_id": self.env.ref("base.ch").id})
|
|
self.country_binder.to_external.return_value = 10
|
|
|
|
mapper = self.comp_registry["my.mapper"](self.work)
|
|
map_record = mapper.map_record(partner)
|
|
self.assertEqual(map_record.values(), {"country": 10})
|
|
self.country_binder.to_external.assert_called_once_with(
|
|
partner.country_id.id, wrap=False
|
|
)
|
|
|
|
def test_mapping_backend_to_m2o(self):
|
|
"""Map a direct record with the backend_to_m2o modifier function"""
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.partner"
|
|
|
|
direct = [(external_to_m2o("country"), "country_id")]
|
|
|
|
self._build_components(MyMapper)
|
|
|
|
record = {"country": 10}
|
|
ch = self.env.ref("base.ch")
|
|
self.country_binder.to_internal.return_value = ch
|
|
mapper = self.comp_registry["my.mapper"](self.work)
|
|
map_record = mapper.map_record(record)
|
|
self.assertEqual(map_record.values(), {"country_id": ch.id})
|
|
self.country_binder.to_internal.assert_called_once_with(10, unwrap=False)
|
|
|
|
def test_mapping_record_children_no_map_child(self):
|
|
"""Map a record with children, using default MapChild"""
|
|
# we need these components which make the 'link' between
|
|
# the main mapper and the line mapper
|
|
|
|
class LineMapper(Component):
|
|
_name = "line.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency.rate"
|
|
|
|
direct = [("name", "name")]
|
|
|
|
@mapping
|
|
def price(self, record):
|
|
return {"rate": record["rate"] * 2}
|
|
|
|
@only_create
|
|
@mapping
|
|
def discount(self, record):
|
|
return {"test": 0.5}
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency"
|
|
|
|
direct = [("name", "name")]
|
|
|
|
children = [("lines", "line_ids", "res.currency.rate")]
|
|
|
|
self._build_components(LineMapper, MyMapper)
|
|
|
|
record = {
|
|
"name": "SO1",
|
|
"lines": [
|
|
{"name": "2013-11-07", "rate": 10},
|
|
{"name": "2013-11-08", "rate": 20},
|
|
],
|
|
}
|
|
mapper = self.comp_registry["my.mapper"](self.work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {
|
|
"name": "SO1",
|
|
"line_ids": [
|
|
(0, 0, {"name": "2013-11-07", "rate": 20}),
|
|
(0, 0, {"name": "2013-11-08", "rate": 40}),
|
|
],
|
|
}
|
|
self.assertEqual(map_record.values(), expected)
|
|
expected = {
|
|
"name": "SO1",
|
|
"line_ids": [
|
|
(0, 0, {"name": "2013-11-07", "rate": 20, "test": 0.5}),
|
|
(0, 0, {"name": "2013-11-08", "rate": 40, "test": 0.5}),
|
|
],
|
|
}
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_record_children(self):
|
|
"""Map a record with children, using defined MapChild"""
|
|
# we need these components which make the 'link' between
|
|
# the main mapper and the line mapper
|
|
|
|
class LineMapper(Component):
|
|
_name = "line.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency.rate"
|
|
|
|
direct = [("name", "name")]
|
|
|
|
@mapping
|
|
def price(self, record):
|
|
return {"rate": record["rate"] * 2}
|
|
|
|
@only_create
|
|
@mapping
|
|
def discount(self, record):
|
|
return {"test": 0.5}
|
|
|
|
class LineImportMapChild(Component):
|
|
_name = "line.map.child.import"
|
|
_inherit = "base.map.child.import"
|
|
_apply_on = "res.currency.rate"
|
|
|
|
def format_items(self, items_values):
|
|
return [("ABC", values) for values in items_values]
|
|
|
|
class MyMapper(Component):
|
|
_name = "my.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency"
|
|
|
|
direct = [("name", "name")]
|
|
|
|
children = [("lines", "line_ids", "res.currency.rate")]
|
|
|
|
self._build_components(LineMapper, LineImportMapChild, MyMapper)
|
|
|
|
record = {
|
|
"name": "SO1",
|
|
"lines": [
|
|
{"name": "2013-11-07", "rate": 10},
|
|
{"name": "2013-11-08", "rate": 20},
|
|
],
|
|
}
|
|
mapper = self.comp_registry["my.mapper"](self.work)
|
|
map_record = mapper.map_record(record)
|
|
expected = {
|
|
"name": "SO1",
|
|
"line_ids": [
|
|
("ABC", {"name": "2013-11-07", "rate": 20}),
|
|
("ABC", {"name": "2013-11-08", "rate": 40}),
|
|
],
|
|
}
|
|
self.assertEqual(map_record.values(), expected)
|
|
expected = {
|
|
"name": "SO1",
|
|
"line_ids": [
|
|
("ABC", {"name": "2013-11-07", "rate": 20, "test": 0.5}),
|
|
("ABC", {"name": "2013-11-08", "rate": 40, "test": 0.5}),
|
|
],
|
|
}
|
|
self.assertEqual(map_record.values(for_create=True), expected)
|
|
|
|
def test_mapping_record_children_void(self):
|
|
"""Map a record with children, using defined MapChild"""
|
|
|
|
class LineMapper(Component):
|
|
_name = "line.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency.rate"
|
|
|
|
@mapping
|
|
def price(self, record):
|
|
rate = record.get("rate")
|
|
if rate and rate < 40:
|
|
return {"rate": record["rate"] * 2}
|
|
|
|
class SaleLineImportMapChild(Component):
|
|
_name = "sale.line.mapper"
|
|
_inherit = "base.map.child.import"
|
|
_apply_on = "res.currency.rate"
|
|
|
|
def format_items(self, items_values):
|
|
return [("ABC", values) for values in items_values]
|
|
|
|
class ObjectMapper(Component):
|
|
_name = "currency.mapper"
|
|
_inherit = "base.import.mapper"
|
|
_apply_on = "res.currency"
|
|
|
|
direct = [("name", "name")]
|
|
|
|
children = [("lines", "line_ids", "res.currency.rate")]
|
|
|
|
self._build_components(ObjectMapper, SaleLineImportMapChild, LineMapper)
|
|
|
|
# Test with an excluded child record
|
|
record = {
|
|
"name": "SO1",
|
|
"lines": [{"rate": 10}, {"rate": 20}, {"rate": 30}, {"rate": 40}],
|
|
}
|
|
mapper = self.comp_registry["currency.mapper"](self.work)
|
|
map_record = mapper.map_record(record)
|
|
|
|
expected = {
|
|
"name": "SO1",
|
|
"line_ids": [
|
|
("ABC", {"rate": 20}),
|
|
("ABC", {"rate": 40}),
|
|
("ABC", {"rate": 60}),
|
|
],
|
|
}
|
|
self.assertEqual(map_record.values(), expected)
|