changeset d8984ce5a8e6 in tryton:5.8 details: https://hg.tryton.org/tryton?cmd=changeset&node=d8984ce5a8e6 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 cee6239e02c3 -r d8984ce5a8e6 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 @@ -170,15 +170,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 cee6239e02c3 -r d8984ce5a8e6 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 @@ -971,10 +971,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)