Skip to content

Commit de26c37

Browse files
committed
[16.0][IMP] base_view_inheritance_extension: attrs_domain_add
New operation 'attrs_domain_add', used to add a domain to the attribute 'attrs'.
1 parent 02a1964 commit de26c37

File tree

4 files changed

+113
-0
lines changed

4 files changed

+113
-0
lines changed

base_view_inheritance_extension/models/ir_ui_view.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,42 @@ def inheritance_handler_attributes_domain_add(self, source, specs):
189189
node.attrib[attribute_name] = new_value
190190
return source
191191

192+
@api.model
193+
def inheritance_handler_attributes_attrs_domain_add(self, source, specs):
194+
"""Implement attrs_domain_add
195+
196+
<attribute name="$attribute" operation="attrs_domain_add"
197+
key="$attrs_key" join_operator="OR">
198+
$domain_to_add_to_attrs_key
199+
</attribute>
200+
"""
201+
node = self.locate_node(source, specs)
202+
for attribute_node in specs:
203+
attribute_name = attribute_node.get("name")
204+
key = attribute_node.get("key")
205+
join_operator = attribute_node.get("join_operator") or "AND"
206+
old_value = node.get(attribute_name) or ""
207+
if old_value:
208+
old_value = ast.literal_eval(
209+
self.var2str_domain_text(old_value.strip())
210+
)
211+
old_domain_attrs = old_value.get(key)
212+
new_domain = ast.literal_eval(
213+
self.var2str_domain_text(attribute_node.text.strip())
214+
)
215+
if join_operator == "OR":
216+
new_value = expression.OR([old_domain_attrs, new_domain])
217+
else:
218+
new_value = expression.AND([old_domain_attrs, new_domain])
219+
old_value[key] = new_value
220+
new_value = self.str2var_domain_text(str(old_value))
221+
else:
222+
# We must ensure that the domain definition has not line breaks because
223+
# in update mode the domain cause an invalid syntax error
224+
new_value = "{'%s': %s}" % (key, attribute_node.text.strip())
225+
node.attrib[attribute_name] = new_value
226+
return source
227+
192228
@api.model
193229
def var2str_domain_text(self, domain_str):
194230
"""Replaces var names with str names to allow eval without defined vars"""

base_view_inheritance_extension/readme/CONTRIBUTORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
* Carlos Dauden
77

88
* Iván Todorovich <[email protected]>
9+
* Carlos Serra-Toro <[email protected]>

base_view_inheritance_extension/readme/USAGE.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,12 @@ to refer to some xmlid, say ``%(xmlid)s``.
3131
condition="$field_condition" join_operator="OR">
3232
$domain_to_add
3333
</attribute>
34+
35+
**Add domain with AND/OR join operator (AND if missed) for key in attrs**
36+
37+
.. code-block:: xml
38+
39+
<attribute name="$attribute" operation="attrs_domain_add"
40+
key="$attrs_key" join_operator="OR">
41+
$domain_to_add_to_attrs_key
42+
</attribute>

base_view_inheritance_extension/tests/test_base_view_inheritance_extension.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,70 @@ def test_update_source_not_a_dict(self):
240240
)
241241
with self.assertRaisesRegex(TypeError, "Attribute `domain` is not a dict"):
242242
self.env["ir.ui.view"].apply_inheritance_specs(source, specs)
243+
244+
def test_attrs_domain_add_join_operator_or(self):
245+
"""Test that we can add an OR domain to an existing attrs key."""
246+
self._test_attrs_domain_add(join_operator="OR")
247+
248+
def test_attrs_domain_add_join_operator_and(self):
249+
"""Test that we can add an AND domain to an existing attrs key."""
250+
self._test_attrs_domain_add(join_operator="AND")
251+
252+
def _test_attrs_domain_add(self, join_operator):
253+
"""Test that we can add a domain to an existing attrs domain key."""
254+
source = etree.fromstring(
255+
"""
256+
<form>
257+
<field
258+
name="ref"
259+
attrs="{
260+
'invisible': [('state', '=', 'draft')],
261+
'required': [('state', '=', False)],
262+
}"
263+
/>
264+
</form>
265+
"""
266+
)
267+
specs = etree.fromstring(
268+
"""
269+
<field name="ref" position="attributes">
270+
<attribute name="attrs" operation="attrs_domain_add"
271+
key="required" join_operator="%s">
272+
[('state', '!=', 'draft')]
273+
</attribute>
274+
</field>
275+
"""
276+
% (join_operator,)
277+
)
278+
res = self.env["ir.ui.view"].apply_inheritance_specs(source, specs)
279+
self.assertEqual(
280+
res.xpath('//field[@name="ref"]')[0].attrib["attrs"],
281+
"{'invisible': [('state', '=', 'draft')], "
282+
"'required': ['%s', ('state', '=', False), ('state', '!=', 'draft')]}"
283+
% ("|" if join_operator == "OR" else "&"),
284+
)
285+
286+
def test_attrs_domain_add_no_attrs(self):
287+
"""Test attrs_domain_add if there is no attrs: attrs is created."""
288+
source = etree.fromstring(
289+
"""
290+
<form>
291+
<field name="ref"/>
292+
</form>
293+
"""
294+
)
295+
specs = etree.fromstring(
296+
"""
297+
<field name="ref" position="attributes">
298+
<attribute name="attrs" operation="attrs_domain_add"
299+
key="required" join_operator="OR">
300+
[('state', '!=', 'draft')]
301+
</attribute>
302+
</field>
303+
"""
304+
)
305+
res = self.env["ir.ui.view"].apply_inheritance_specs(source, specs)
306+
self.assertEqual(
307+
res.xpath('//field[@name="ref"]')[0].attrib["attrs"],
308+
"{'required': [('state', '!=', 'draft')]}",
309+
)

0 commit comments

Comments
 (0)