changeset 72ccc8121d55 in tryton:5.6
details: https://hg.tryton.org/tryton?cmd=changeset&node=72ccc8121d55
description:
        Use specific search domain for reference field searches

        issue9997
        review324781002
        (grafted from 558aeef898cd410c74d51a2e5ced9cbe8baaa899)
diffstat:

 tryton/common/domain_inversion.py          |  57 ++++++++++++++++++++++++++---
 tryton/gui/window/view_form/model/field.py |   3 +-
 2 files changed, 53 insertions(+), 7 deletions(-)

diffs (86 lines):

diff -r d0256c1d535c -r 72ccc8121d55 tryton/common/domain_inversion.py
--- a/tryton/common/domain_inversion.py Sun Apr 11 18:28:37 2021 +0200
+++ b/tryton/common/domain_inversion.py Mon Apr 12 20:54:03 2021 +0200
@@ -164,15 +164,60 @@
 
 def prepare_reference_domain(domain, reference):
     "convert domain to replace reference fields by their local part"
+
+    def value2reference(value):
+        model, ref_id = None, None
+        if isinstance(value, str) and ',' in value:
+            model, ref_id = value.split(',', 1)
+            if ref_id != '%':
+                try:
+                    ref_id = int(ref_id)
+                except ValueError:
+                    model, ref_id = None, value
+        elif (isinstance(value, (list, tuple))
+                and len(value) == 2
+                and isinstance(value[0], str)
+                and (isinstance(value[1], int) or value[1] == '%')):
+            model, ref_id = value
+        else:
+            ref_id = value
+        return model, ref_id
+
     if domain in ('AND', 'OR'):
         return domain
     elif is_leaf(domain):
-        # When a Reference field is using the dotted notation the model
-        # specified must be removed from the clause
-        if domain[0].count('.') and len(domain) > 3:
-            local_name, target_name = domain[0].split('.', 1)
-            if local_name == reference:
-                return [target_name] + list(domain[1:3] + domain[4:])
+        if domain[0] == reference:
+            if domain[1] in {'=', '!='}:
+                model, ref_id = value2reference(domain[2])
+                if model is not None:
+                    if ref_id == '%':
+                        if domain[1] == '=':
+                            return [reference + '.id', '!=', None, model]
+                        else:
+                            return [reference, 'not like', domain[2]]
+                    return [reference + '.id', domain[1], ref_id, model]
+            elif domain[1] in {'in', 'not in'}:
+                model_values = {}
+                for value in domain[2]:
+                    model, ref_id = value2reference(value)
+                    if model is None:
+                        break
+                    model_values.setdefault(model, []).append(ref_id)
+                else:
+                    new_domain = ['OR'] if domain[1] == 'in' else ['AND']
+                    for model, ref_ids in model_values.items():
+                        if '%' in ref_ids:
+                            if domain[1] == 'in':
+                                new_domain.append(
+                                    [reference + '.id', '!=', None, model])
+                            else:
+                                new_domain.append(
+                                    [reference, 'not like', model + ',%'])
+                        else:
+                            new_domain.append(
+                                [reference + '.id', domain[1], ref_ids, model])
+                    return new_domain
+            return []
         return domain
     else:
         return [prepare_reference_domain(d, reference) for d in domain]
diff -r d0256c1d535c -r 72ccc8121d55 tryton/gui/window/view_form/model/field.py
--- a/tryton/gui/window/view_form/model/field.py        Sun Apr 11 18:28:37 
2021 +0200
+++ b/tryton/gui/window/view_form/model/field.py        Mon Apr 12 20:54:03 
2021 +0200
@@ -949,10 +949,11 @@
         screen_domain = filter_leaf(screen_domain, self.name, model)
         screen_domain = prepare_reference_domain(screen_domain, self.name)
         return concat(localize_domain(
-                screen_domain, strip_target=True), attr_domain)
+                screen_domain, self.name, strip_target=True), attr_domain)
 
     def get_models(self, record):
         screen_domain, attr_domain = self.domains_get(record)
+        screen_domain = prepare_reference_domain(screen_domain, self.name)
         return extract_reference_models(
             concat(screen_domain, attr_domain), self.name)
 

Reply via email to