Skip to content

Commit d3fec0e

Browse files
Rad0vangiarve
authored andcommitted
[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.
1 parent 79523b0 commit d3fec0e

File tree

6 files changed

+80
-27
lines changed

6 files changed

+80
-27
lines changed

base_import_match/README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ Contributors
140140
* Jairo Llopis
141141
* Vicent Cubells
142142
* Ernesto Tejeda
143+
* Radovan Skolnik <[email protected]>
143144

144145
Maintainers
145146
~~~~~~~~~~~

base_import_match/models/base.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,33 @@ def load(self, fields, data):
3434
# Mock Odoo to believe the user is importing the ID field
3535
if "id" not in fields:
3636
fields.append("id")
37-
import_fields.append(["id"])
3837
# Needed to match with converted data field names
39-
clean_fields = [f[0] for f in import_fields]
4038
for dbid, xmlid, record, info in converted_data:
41-
row = dict(zip(clean_fields, data[info["record"]]))
42-
match = self
43-
if xmlid:
44-
# Skip rows with ID, they do not need all this
45-
row["id"] = xmlid
46-
newdata.append(tuple(row[f] for f in clean_fields))
47-
continue
48-
elif dbid:
49-
# Find the xmlid for this dbid
50-
match = self.browse(dbid)
51-
else:
52-
# Store records that match a combination
53-
match = self.env["base_import.match"]._match_find(self, record, row)
54-
# Give a valid XMLID to this row if a match was found
55-
# To generate externals IDS.
56-
match.export_data(fields)
57-
ext_id = match.get_external_id()
58-
row["id"] = ext_id[match.id] if match else row.get("id", "")
59-
# Store the modified row, in the same order as fields
60-
newdata.append(tuple(row[f] for f in clean_fields))
39+
# In case of one2many on empty lines one record may contain several rows
40+
for row_index in range(info["rows"]["from"], info["rows"]["to"] + 1):
41+
row = dict(zip(fields, data[row_index]))
42+
match = self
43+
if xmlid:
44+
# Skip rows with ID, they do not need all this
45+
row["id"] = xmlid
46+
continue
47+
elif dbid:
48+
# Find the xmlid for this dbid
49+
match = self.browse(dbid)
50+
elif row_index == info["rows"]["from"]:
51+
# Store records that match a combination
52+
# But only for first row of record,
53+
# because the rest contain one2many fields
54+
match = self.env["base_import.match"]._match_find(
55+
self, record, row
56+
)
57+
# Give a valid XMLID to this row if a match was found
58+
# To generate externals IDS.
59+
match.export_data(fields)
60+
ext_id = match.get_external_id()
61+
row["id"] = ext_id[match.id] if match else row.get("id", "")
62+
# Store the modified row, in the same order as fields
63+
newdata.append(tuple(row[f] for f in fields))
6164
# We will import the patched data to get updates on matches
6265
data = newdata
6366
# Normal method handles the rest of the job

base_import_match/readme/CONTRIBUTORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
* Jairo Llopis
33
* Vicent Cubells
44
* Ernesto Tejeda
5+
* Radovan Skolnik <[email protected]>

base_import_match/static/description/index.html

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<?xml version="1.0" encoding="utf-8"?>
21
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
32
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
43
<head>
@@ -9,10 +8,11 @@
98

109
/*
1110
:Author: David Goodger ([email protected])
12-
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
11+
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
1312
:Copyright: This stylesheet has been placed in the public domain.
1413
1514
Default cascading style sheet for the HTML output of Docutils.
15+
Despite the name, some widely supported CSS2 features are used.
1616
1717
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
1818
customize this style sheet.
@@ -275,7 +275,7 @@
275275
margin-left: 2em ;
276276
margin-right: 2em }
277277

278-
pre.code .ln { color: grey; } /* line numbers */
278+
pre.code .ln { color: gray; } /* line numbers */
279279
pre.code, code { background-color: #eeeeee }
280280
pre.code .comment, code .comment { color: #5C6576 }
281281
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@
301301
span.pre {
302302
white-space: pre }
303303

304-
span.problematic {
304+
span.problematic, pre.problematic {
305305
color: red }
306306

307307
span.section-subtitle {
@@ -495,12 +495,15 @@ <h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
495495
* Jairo Llopis
496496
* Vicent Cubells
497497
* Ernesto Tejeda</li>
498+
<li>Radovan Skolnik &lt;<a class="reference external" href="mailto:radovan&#64;skolnik.info">radovan&#64;skolnik.info</a>&gt;</li>
498499
</ul>
499500
</div>
500501
<div class="section" id="maintainers">
501502
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
502503
<p>This module is maintained by the OCA.</p>
503-
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
504+
<a class="reference external image-reference" href="https://odoo-community.org">
505+
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
506+
</a>
504507
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
505508
mission is to support the collaborative development of Odoo features and
506509
promote its widespread use.</p>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
email,function,child_ids/name,child_ids/color,child_ids/email
2+
[email protected],Bug Fixer,Bart Steward,666,[email protected]
3+
,,Lisa Steward,777,[email protected]
4+
,,Maggie Steward,555,[email protected]

base_import_match/tests/test_import.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,44 @@ def test_res_users_login(self):
111111
record = self._base_import_record("res.users", "res_users_login")
112112
record.execute_import(["login", "name"], [], OPTIONS)
113113
self.assertEqual(self.env.ref("base.user_demo").name, "Demo User Changed")
114+
115+
def test_res_partner_email_one2many(self):
116+
"""Change function based on email and import one2many record."""
117+
record = self._base_import_record("res.partner", "res_partner_email_one2many")
118+
record.do(
119+
[
120+
"email",
121+
"function",
122+
"child_ids/name",
123+
"child_ids/color",
124+
"child_ids/email",
125+
],
126+
[],
127+
OPTIONS,
128+
)
129+
self.assertEqual(
130+
self.env.ref("base.res_partner_address_4").function, "Bug Fixer"
131+
)
132+
self.assertTrue(
133+
self.env.ref("base.res_partner_address_4").child_ids,
134+
)
135+
self.assertEqual(
136+
len(self.env.ref("base.res_partner_address_4").child_ids),
137+
3,
138+
)
139+
self.assertEqual(
140+
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.name")),
141+
{"Bart Steward", "Lisa Steward", "Maggie Steward"},
142+
)
143+
self.assertEqual(
144+
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.email")),
145+
{
146+
147+
148+
149+
},
150+
)
151+
self.assertEqual(
152+
set(self.env.ref("base.res_partner_address_4").mapped("child_ids.color")),
153+
{666, 777, 555},
154+
)

0 commit comments

Comments
 (0)