diff --git a/trytond/model/fields/many2many.py b/trytond/model/fields/many2many.py index b1933ad517..b0b81f8b28 100644 --- a/trytond/model/fields/many2many.py +++ b/trytond/model/fields/many2many.py @@ -4,10 +4,12 @@ from itertools import chain from sql import Cast, Literal, Null from sql.functions import Substring, Position +from sql.conditionals import Coalesce from .field import Field, size_validate from ...pool import Pool from ...tools import grouped_slice +from ...transaction import Transaction class Many2Many(Field): @@ -260,13 +262,23 @@ class Many2Many(Field): return expression def convert_domain(self, domain, tables, Model): + from ..modelsql import convert_from pool = Pool() + Rule = pool.get('ir.rule') Target = self.get_target() Relation = pool.get(self.relation_name) - relation = Relation.__table__() + transaction = Transaction() table, _ = tables[None] name, operator, value = domain[:3] + if Relation._history and transaction.context.get('_datetime'): + relation = Relation.__table_history__() + history_where = ( + Coalesce(relation.write_date, relation.create_date) + <= transaction.context['_datetime']) + else: + relation = Relation.__table__() + history_where = None origin_field = Relation._fields[self.origin] origin = getattr(Relation, self.origin).sql_column(relation) origin_where = None @@ -283,6 +295,8 @@ class Many2Many(Field): query = Target.search([(domain[3], 'child_of', value)], order=[], query=True) where = (target.in_(query) & (origin != Null)) + if history_where: + where &= history_where if origin_where: where &= origin_where query = relation.select(origin, where=where) @@ -309,6 +323,8 @@ class Many2Many(Field): if value is None: where = origin != value + if history_where: + where &= history_where if origin_where: where &= origin_where query = relation.select(origin, where=where) @@ -323,10 +339,20 @@ class Many2Many(Field): target_name = 'id' else: _, target_name = name.split('.', 1) - target_domain = [(target_name,) + tuple(domain[1:])] - query = Target.search(target_domain, order=[], query=True) - where = target.in_(query) - if origin_where: - where &= origin_where - query = relation.select(origin, where=where) + + relation_domain = [('%s.%s' % (self.target, target_name),) + + tuple(domain[1:])] + if origin_field._type == 'reference': + relation_domain.append( + (self.origin, 'like', Model.__name__ + ',%')) + rule_domain = Rule.domain_get(Relation.__name__, mode='read') + if rule_domain: + relation_domain = [relation_domain, rule_domain] + relation_tables = { + None: (relation, None), + } + tables, expression = Relation.search_domain( + relation_domain, tables=relation_tables) + query_table = convert_from(None, relation_tables) + query = query_table.select(origin, where=expression) return table.id.in_(query) diff --git a/trytond/model/fields/one2many.py b/trytond/model/fields/one2many.py index 2ea150f452..d2c1a432a7 100644 --- a/trytond/model/fields/one2many.py +++ b/trytond/model/fields/one2many.py @@ -3,10 +3,12 @@ from itertools import chain from sql import Cast, Literal from sql.functions import Substring, Position +from sql.conditionals import Coalesce from .field import Field, size_validate from ...pool import Pool from ...tools import grouped_slice +from ...transaction import Transaction def add_remove_validate(value): @@ -222,11 +224,22 @@ class One2Many(Field): super(One2Many, self).__set__(inst, value) def convert_domain(self, domain, tables, Model): + from ..modelsql import convert_from + pool = Pool() + Rule = pool.get('ir.rule') Target = self.get_target() - target = Target.__table__() + transaction = Transaction() table, _ = tables[None] name, operator, value = domain[:3] + if Target._history and transaction.context.get('_datetime'): + target = Target.__table_history__() + history_where = ( + Coalesce(target.write_date, target.create_date) + <= transaction.context['_datetime']) + else: + target = Target.__table__() + history_where = None origin_field = Target._fields[self.field] origin = getattr(Target, self.field).sql_column(target) origin_where = None @@ -239,6 +252,8 @@ class One2Many(Field): if '.' not in name: if value is None: where = origin != value + if history_where: + where &= history_where if origin_where: where &= origin_where query = target.select(origin, where=where) @@ -254,9 +269,17 @@ class One2Many(Field): else: _, target_name = name.split('.', 1) target_domain = [(target_name,) + tuple(domain[1:])] - query = Target.search(target_domain, order=[], query=True) - where = target.id.in_(query) - if origin_where: - where &= origin_where - query = target.select(origin, where=where) + if origin_field._type == 'reference': + target_domain.append( + (self.field, 'like', Model.__name__ + ',%')) + rule_domain = Rule.domain_get(Target.__name__, mode='read') + if rule_domain: + target_domain = [target_domain, rule_domain] + target_tables = { + None: (target, None), + } + tables, expression = Target.search_domain( + target_domain, tables=target_tables) + query_table = convert_from(None, target_tables) + query = query_table.select(origin, where=expression) return table.id.in_(query)