diff --git a/CHANGELOG b/CHANGELOG index 66d7b9c18e..5efa60b6da 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add datetime_field on xxx2Many to use a specific _datetime when reading the related record * Add new tool safe_eval * Handle sequence and history renaming when renaming table * Add old_password to set_preferences of res.user on password change diff --git a/trytond/model/browse.py b/trytond/model/browse.py index eec0514940..88fd916622 100644 --- a/trytond/model/browse.py +++ b/trytond/model/browse.py @@ -123,8 +123,7 @@ class BrowseRecord(object): # add datetime_field for i, j in ffields: - if j._type == 'many2one' and hasattr(j, 'datetime_field') \ - and j.datetime_field: + if hasattr(j, 'datetime_field') and j.datetime_field: if j.datetime_field in self._model._columns: col = self._model._columns[j.datetime_field] else: @@ -165,12 +164,15 @@ class BrowseRecord(object): context=ctx) elif model and j._type in ('one2many', 'many2many') \ and len(data[i]): + ctx = self._context + if hasattr(j, 'datetime_field') and j.datetime_field: + ctx = self._context.copy() + ctx['_datetime'] = data[j.datetime_field] data[i] = BrowseRecordList([BrowseRecord(self._cursor, self._user, isinstance(x, (list, tuple)) and x[0] or x, model, local_cache=self._local_cache, - context=self._context) for x in data[i]], - self._context) + context=ctx) for x in data[i]], ctx) if isinstance(j, fields.Function): self._local_data.setdefault(data['id'], {})[i] = data[i] del data[i] diff --git a/trytond/model/fields/function.py b/trytond/model/fields/function.py index c42ce8ec61..c68b15f0ff 100644 --- a/trytond/model/fields/function.py +++ b/trytond/model/fields/function.py @@ -13,11 +13,11 @@ class Function(Field): def __init__(self, fnct, arg=None, fnct_inv='', fnct_inv_arg=None, type='float', fnct_search='', model_name=None, selection=None, - digits=None, relation=None, add_remove=None, string='', help='', - required=False, readonly=False, domain=None, states=None, - priority=0, change_default=False, translate=False, select=0, - on_change=None, on_change_with=None, depends=None, order_field=None, - context=None): + digits=None, relation=None, add_remove=None, datetime_field=None, + string='', help='', required=False, readonly=False, domain=None, + states=None, priority=0, change_default=False, translate=False, + select=0, on_change=None, on_change_with=None, depends=None, + order_field=None, context=None): ''' :param fnct: The name of the function. :param arg: Argument for the function. @@ -30,7 +30,14 @@ class Function(Field): :param digits: See Float. :param relation: Like model_name. :param add_remove: See Many2One. + :param datetime_field: The name of the field that contains the datetime + value to read the target records. ''' + if datetime_field: + if depends: + depends.append(datetime_field) + else: + depends = [datetime_field] super(Function, self).__init__(string=string, help=help, required=required, readonly=readonly, domain=domain, states=states, priority=priority, change_default=change_default, @@ -51,6 +58,7 @@ class Function(Field): if relation: self.model_name = relation self.add_remove = add_remove + self.datetime_field = datetime_field __init__.__doc__ += Field.__init__.__doc__ def search(self, cursor, user, model, name, args, context=None): diff --git a/trytond/model/fields/many2many.py b/trytond/model/fields/many2many.py index 353f8c311f..b013be79b5 100644 --- a/trytond/model/fields/many2many.py +++ b/trytond/model/fields/many2many.py @@ -11,10 +11,10 @@ class Many2Many(Field): _type = 'many2many' def __init__(self, relation_name, origin, target, string='', order=None, - help='', required=False, readonly=False, domain=None, states=None, - priority=0, change_default=False, translate=False, select=0, - on_change=None, on_change_with=None, depends=None, order_field=None, - context=None): + datetime_field=None, help='', required=False, readonly=False, + domain=None, states=None, priority=0, change_default=False, + translate=False, select=0, on_change=None, on_change_with=None, + depends=None, order_field=None, context=None): ''' :param relation_name: The name of the relation model or the name of the target model for ModelView only. @@ -23,7 +23,14 @@ class Many2Many(Field): :param order: a list of tuples that are constructed like this: ``('field name', 'DESC|ASC')`` allowing to specify the order of result + :param datetime_field: The name of the field that contains the datetime + value to read the target records. ''' + if datetime_field: + if depends: + depends.append(datetime_field) + else: + depends = [datetime_field] super(Many2Many, self).__init__(string=string, help=help, required=required, readonly=readonly, domain=domain, states=states, priority=priority, change_default=change_default, @@ -34,6 +41,7 @@ class Many2Many(Field): self.origin = origin self.target = target self.order = order + self.datetime_field = datetime_field __init__.__doc__ += Field.__init__.__doc__ def get(self, cursor, user, ids, model, name, values=None, context=None): diff --git a/trytond/model/fields/one2many.py b/trytond/model/fields/one2many.py index 49fe95a960..80583a8c82 100644 --- a/trytond/model/fields/one2many.py +++ b/trytond/model/fields/one2many.py @@ -11,10 +11,10 @@ class One2Many(Field): _type = 'one2many' def __init__(self, model_name, field, string='', add_remove=None, order=None, - help='', required=False, readonly=False, domain=None, states=None, - priority=0, change_default=False, translate=False, select=0, - on_change=None, on_change_with=None, depends=None, order_field=None, - context=None): + datetime_field=None, help='', required=False, readonly=False, + domain=None, states=None, priority=0, change_default=False, + translate=False, select=0, on_change=None, on_change_with=None, + depends=None, order_field=None, context=None): ''' :param model_name: The name of the targeted model. :param field: The name of the field that handle the reverse many2one. @@ -23,7 +23,14 @@ class One2Many(Field): :param order: a list of tuples that are constructed like this: ``('field name', 'DESC|ASC')`` allowing to specify the order of result. + :param datetime_field: The name of the field that contains the datetime + value to read the target records. ''' + if datetime_field: + if depends: + depends.append(datetime_field) + else: + depends = [datetime_field] super(One2Many, self).__init__(string=string, help=help, required=required, readonly=readonly, domain=domain, states=states, priority=priority, change_default=change_default, @@ -34,6 +41,7 @@ class One2Many(Field): self.field = field self.add_remove = add_remove self.order = order + self.datetime_field = datetime_field __init__.__doc__ += Field.__init__.__doc__ def get(self, cursor, user, ids, model, name, values=None, context=None): diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 7a789cb2f2..1b2501c4de 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -580,10 +580,22 @@ class ModelSQL(ModelStorage): func_fields = {} for field in fields_post: if isinstance(self._columns[field], fields.Function): - key = (self._columns[field].fnct, self._columns[field].arg) + key = (self._columns[field].fnct, self._columns[field].arg, + self._columns[field].datetime_field) func_fields.setdefault(key, []) func_fields[key].append(field) continue + if hasattr(self._columns[field], 'datetime_field') \ + and self._columns[field].datetime_field: + ctx = context.copy() + for record in res: + ctx['_datetime'] = \ + record[self._columns[field].datetime_field] + res2 = self._columns[field].get(cursor, user, + [record['id']], self, field, values=[record], + context=ctx) + record[field] = res2[record['id']] + continue # get the value of that field for all records/ids res2 = self._columns[field].get(cursor, user, ids, self, field, values=res, context=context) @@ -592,6 +604,17 @@ class ModelSQL(ModelStorage): for i in func_fields: field_list = func_fields[i] field = field_list[0] + datetime_field = i[2] + if datetime_field: + ctx = context.copy() + for record in res: + ctx['_datetime'] = record[datetime_field] + res2 = self._columns[field].get(cursor, user, + [record['id']], self, field_list, values=[record], + context=ctx) + for field in res2: + record[field] = res2[field][record['id']] + continue res2 = self._columns[field].get(cursor, user, ids, self, field_list, values=res, context=context) for field in res2: