[FIX] base_import_match: importing related o2m records

The original code did improperly handle importing
related one2many records where at best all their
attribute values would get overwritten by last
of them. This was caused by mapping them only by
their first part.
This commit is contained in:
Rad0van
2022-01-18 22:38:27 +01:00
parent 0414dd0b05
commit 79bd879eb4
4 changed files with 68 additions and 21 deletions

View File

@@ -26,11 +26,11 @@ class Base(models.AbstractModel):
# 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")
import_fields.append(["id"])
# Needed to match with converted data field names # Needed to match with converted data field names
clean_fields = [f[0] for f in import_fields]
for dbid, xmlid, record, info in converted_data: for dbid, xmlid, record, info in converted_data:
row = dict(zip(clean_fields, data[info["record"]])) # In case of one2many on empty lines one record may contain several rows
for row_index in range(info["rows"]["from"], info["rows"]["to"] + 1):
row = dict(zip(fields, data[row_index]))
match = self match = self
if xmlid: if xmlid:
# Skip rows with ID, they do not need all this # Skip rows with ID, they do not need all this
@@ -39,16 +39,20 @@ class Base(models.AbstractModel):
elif dbid: elif dbid:
# Find the xmlid for this dbid # Find the xmlid for this dbid
match = self.browse(dbid) match = self.browse(dbid)
else: elif row_index == info["rows"]["from"]:
# Store records that match a combination # Store records that match a combination
match = self.env["base_import.match"]._match_find(self, record, row) # But only for first row of record,
# because the rest contain one2many fields
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 fields))
# We will import the patched data to get updates on matches # We will import the patched data to get updates on matches
data = newdata data = newdata
# Normal method handles the rest of the job # Normal method handles the rest of the job

View File

@@ -2,3 +2,4 @@
* Jairo Llopis * Jairo Llopis
* Vicent Cubells * Vicent Cubells
* Ernesto Tejeda * Ernesto Tejeda
* Radovan Skolnik <radovan@skolnik.info>

View File

@@ -0,0 +1,4 @@
email,function,child_ids/name,child_ids/color,child_ids/email
floyd.steward34@example.com,Bug Fixer,Bart Steward,666,bart.steward@example.com
,,Lisa Steward,777,lisa.steward@example.com
,,Maggie Steward,555,maggie.steward@example.com
1 email function child_ids/name child_ids/color child_ids/email
2 floyd.steward34@example.com Bug Fixer Bart Steward 666 bart.steward@example.com
3 Lisa Steward 777 lisa.steward@example.com
4 Maggie Steward 555 maggie.steward@example.com

View File

@@ -68,3 +68,41 @@ class ImportCase(TransactionCase):
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")
def test_res_partner_email_one2many(self):
"""Change function based on email and import one2many record."""
record = self._base_import_record("res.partner", "res_partner_email_one2many")
record.do(
[
"email",
"function",
"child_ids/name",
"child_ids/color",
"child_ids/email",
],
[],
OPTIONS,
)
self.assertEqual(
self.env.ref("base.res_partner_address_4").function, "Bug Fixer"
)
self.assertTrue(self.env.ref("base.res_partner_address_4").child_ids,)
self.assertEqual(
len(self.env.ref("base.res_partner_address_4").child_ids), 3,
)
self.assertEqual(
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.name")),
{"Bart Steward", "Lisa Steward", "Maggie Steward"},
)
self.assertEqual(
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.email")),
{
"bart.steward@example.com",
"lisa.steward@example.com",
"maggie.steward@example.com",
},
)
self.assertEqual(
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.color")),
{666, 777, 555},
)