Skip to content

Commit 88344d9

Browse files
KangOlaj-fuentes
andcommitted
[FIX] util.adapt_domains
Also adapt domains in views Part-of: odoo/upgrade#5120 Co-authored-by: Alvaro Fuentes Suarez <[email protected]>
1 parent 35f64c4 commit 88344d9

File tree

2 files changed

+105
-9
lines changed

2 files changed

+105
-9
lines changed

src/base/tests/test_util.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,64 @@ def test_force_adapt(self, left, model, target_model="res.users", old="partner_i
235235
self.assertEqual(res, self.mock_adapter.return_value)
236236

237237

238+
class TestAdaptDomainView(UnitTestCase):
239+
def test_adapt_domain_view(self):
240+
view_form = self.env["ir.ui.view"].create(
241+
{
242+
"name": "test_adapt_domain_view_form",
243+
"model": "res.currency",
244+
"arch": """\
245+
<form>
246+
<field name="rate_ids">
247+
<tree>
248+
<field name="company_id" domain="[('email', '!=', False)]"/>
249+
<field name="company_id" domain="[('email', 'not like', 'odoo.com')]"/>
250+
</tree>
251+
</field>
252+
</form>
253+
""",
254+
}
255+
)
256+
257+
view_search_1 = self.env["ir.ui.view"].create(
258+
{
259+
"name": "test_adapt_domain_view_search",
260+
"model": "res.company",
261+
"arch": """\
262+
<search>
263+
<field name="email" string="Mail" filter_domain="[('email', '=', self)]"/>
264+
</search>
265+
""",
266+
}
267+
)
268+
269+
view_search_2 = self.env["ir.ui.view"].create(
270+
{
271+
"name": "test_adapt_domain_view_search",
272+
"model": "res.company",
273+
"arch": """\
274+
<search>
275+
<filter name="mail" string="Mail" domain="[('email', '=', self)]"/>
276+
</search>
277+
""",
278+
}
279+
)
280+
281+
util.adapt_domains(self.env.cr, "res.partner", "email", "courriel")
282+
util.invalidate(view_form | view_search_1 | view_search_2)
283+
284+
self.assertIn("email", view_form.arch)
285+
self.assertIn("email", view_search_1.arch)
286+
self.assertIn("email", view_search_2.arch)
287+
288+
util.adapt_domains(self.env.cr, "res.company", "email", "courriel")
289+
util.invalidate(view_form | view_search_1 | view_search_2)
290+
291+
self.assertIn("courriel", view_form.arch)
292+
self.assertIn("courriel", view_search_1.arch)
293+
self.assertIn("courriel", view_search_2.arch)
294+
295+
238296
class TestRemoveFieldDomains(UnitTestCase):
239297
@parametrize(
240298
[

src/util/domains.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
from .helpers import _dashboard_actions, _validate_model
2323
from .inherit import for_each_inherit
2424
from .misc import SelfPrintEvalContext
25-
from .pg import column_exists, table_exists
25+
from .pg import column_exists, get_value_or_en_translation, table_exists
26+
from .records import edit_view
2627

2728
# python3 shims
2829
try:
@@ -133,10 +134,8 @@ def _get_domain_fields(cr):
133134
yield df
134135

135136

136-
def _valid_path_to(cr, path, from_, to):
137-
model = from_
138-
while path:
139-
field = path.pop(0)
137+
def _model_of_path(cr, model, path):
138+
for field in path:
140139
cr.execute(
141140
"""
142141
SELECT relation
@@ -147,11 +146,15 @@ def _valid_path_to(cr, path, from_, to):
147146
[model, field],
148147
)
149148
if not cr.rowcount:
150-
# unknown field. Maybe an old domain. Cannot validate it.
151-
return False
149+
return None
152150
[model] = cr.fetchone()
153151

154-
return model == to
152+
return model
153+
154+
155+
def _valid_path_to(cr, path, from_, to):
156+
model = _model_of_path(cr, from_, path)
157+
return model is not None and model == to
155158

156159

157160
def _adapt_one_domain(cr, target_model, old, new, model, domain, adapter=None, force_adapt=False):
@@ -258,7 +261,7 @@ def adapt_domains(cr, model, old, new, adapter=None, skip_inherit=(), force_adap
258261
it is part of an and ("&") domain. The other parameter signals if the leaf is
259262
{negated} ("!").
260263
261-
Note that the {adapter} is called ony on leafs that use the {old} field of {model}.
264+
Note that the {adapter} is called only on leafs that use the {old} field of {model}.
262265
263266
{force_adapt} will run the adapter on all leaves having the removed field in the path. Useful
264267
when deleting a field (in which case {new} is ignored).
@@ -288,6 +291,41 @@ def adapt_domains(cr, model, old, new, adapter=None, skip_inherit=(), force_adap
288291
[unicode(new_domain), id_],
289292
)
290293

294+
# adapt search views
295+
arch_db = get_value_or_en_translation(cr, "ir_ui_view", "arch_db")
296+
cr.execute("SELECT id, model FROM ir_ui_view WHERE {} ~ %s".format(arch_db), [match_old])
297+
for view_id, view_model in cr.fetchall():
298+
with edit_view(cr, view_id=view_id) as view:
299+
for node in view.xpath(
300+
"//filter[contains(@domain, '{0}')]|//field[contains(@filter_domain, '{0}')]".format(old)
301+
):
302+
attr = "domain" if "domain" in node.attrib else "filter_domain"
303+
domain = _adapt_one_domain(
304+
cr, target_model, old, new, view_model, node.get(attr), adapter=adapter, force_adapt=force_adapt
305+
)
306+
if domain:
307+
node.set(attr, unicode(domain))
308+
309+
for node in view.xpath("//field[contains(@domain, '{0}')]".format(old)):
310+
# as <fields> can happen in sub-views, we should deternine the actual model the field belongs to
311+
path = list(reversed([p.get("name") for p in node.iterancestors("field")])) + [node.get("name")]
312+
field_model = _model_of_path(cr, view_model, path)
313+
if not field_model:
314+
continue
315+
316+
domain = _adapt_one_domain(
317+
cr,
318+
target_model,
319+
old,
320+
new,
321+
field_model,
322+
node.get("domain"),
323+
adapter=adapter,
324+
force_adapt=force_adapt,
325+
)
326+
if domain:
327+
node.set("domain", unicode(domain))
328+
291329
# adapt domain in dashboards.
292330
# NOTE: does not filter on model at dashboard selection for handle dotted domains
293331
for _, act in _dashboard_actions(cr, match_old):

0 commit comments

Comments
 (0)