diff --git a/trytond/model/tree.py b/trytond/model/tree.py index 8fd36dca19..b4c3136580 100644 --- a/trytond/model/tree.py +++ b/trytond/model/tree.py @@ -38,39 +38,41 @@ def tree(parent='parent', name='name', separator=None): @classmethod def search_rec_name(cls, _, clause): - if isinstance(clause[2], str): - values = list(reversed(clause[2].split(separator))) - else: - values = [[]] - for value in clause[2]: - if value is None: - values[0].append(value) - continue - for i, v in range(reversed(value.split(separator))): - while len(values) <= i: - values.append([]) - values[i].append(v) domain = [] - field = name - for value in values: - domain.append((field, clause[1], value.strip())) - field = parent + '.' + field - if (( - clause[1].endswith('like') - and not clause[2].replace( - '%%', '__').startswith('%')) - or not clause[1].endswith('like')): - if clause[1].startswith('not') or clause[1] == '!=': + if isinstance(clause[2], str): + field = name + values = list(reversed(clause[2].split(separator))) + for value in values: + domain.append((field, clause[1], value.strip())) + field = parent + '.' + field + if (( + clause[1].endswith('like') + and not clause[2].replace( + '%%', '__').startswith('%')) + or not clause[1].endswith('like')): + if clause[1].startswith('not') or clause[1] == '!=': + operator = '!=' + domain.insert(0, 'OR') + else: + operator = '=' + top_parent = '.'.join((parent,) * len(values)) + domain.append((top_parent, operator, None)) + if (clause[1].endswith('like') + and clause[2].replace('%%', '__').endswith('%')): + ids = list(map(int, cls.search(domain, order=[]))) + domain = [(parent, 'child_of', ids)] + elif clause[2] is None: + domain.append((name, clause[1], clause[2])) + else: + if clause[1].startswith('not'): operator = '!=' - domain.insert(0, 'OR') + domain.append('AND') else: operator = '=' - top_parent = '.'.join((parent,) * len(values)) - domain.append((top_parent, operator, None)) - if (clause[1].endswith('like') - and clause[2].replace('%%', '__').endswith('%')): - ids = list(map(int, cls.search(domain, order=[]))) - domain = [(parent, 'child_of', ids)] + domain.append('OR') + for value in clause[2]: + domain.append(cls.search_rec_name( + name, (clause[0], operator, value))) return domain @classmethod diff --git a/trytond/tests/test_tree.py b/trytond/tests/test_tree.py index beb500b0f7..c04f74c774 100644 --- a/trytond/tests/test_tree.py +++ b/trytond/tests/test_tree.py @@ -69,6 +69,21 @@ class TreeMixinTestCase(unittest.TestCase): self.assertEqual(records, [parent]) + @with_transaction() + def test_search_rec_name_equals_none(self): + "Test search_rec_name equals" + pool = Pool() + Tree = pool.get('test.tree') + + parent = Tree(name="parent") + parent.save() + record = Tree(name="record", parent=parent) + record.save() + + records = Tree.search([('rec_name', '=', None)]) + + self.assertEqual(records, []) + @with_transaction() def test_search_rec_name_non_equals(self): "Test search_rec_name non equals" @@ -99,6 +114,51 @@ class TreeMixinTestCase(unittest.TestCase): self.assertEqual(records, [record]) + @with_transaction() + def test_search_rec_name_non_equals_none(self): + "Test search_rec_name equals" + pool = Pool() + Tree = pool.get('test.tree') + + parent = Tree(name="parent") + parent.save() + record = Tree(name="record", parent=parent) + record.save() + + records = Tree.search([('rec_name', '!=', None)]) + + self.assertEqual(records, [parent, record]) + + @with_transaction() + def test_search_rec_name_in(self): + "Test search_rec_name in" + pool = Pool() + Tree = pool.get('test.tree') + + parent = Tree(name="parent") + parent.save() + record = Tree(name="record", parent=parent) + record.save() + + records = Tree.search([('rec_name', 'in', ['parent / record'])]) + + self.assertEqual(records, [record]) + + @with_transaction() + def test_search_rec_name_in_toplevel(self): + "Test search_rec_name in top-level" + pool = Pool() + Tree = pool.get('test.tree') + + parent = Tree(name="parent") + parent.save() + record = Tree(name="record", parent=parent) + record.save() + + records = Tree.search([('rec_name', 'in', ['parent'])]) + + self.assertEqual(records, [parent]) + @with_transaction() def test_search_rec_name_like(self): "Test search_rec_name like"