From 301bd86a21baed45ce26058343f65cf70f3303ab Mon Sep 17 00:00:00 2001 From: Bertrand Chenal Date: Wed, 25 Mar 2009 18:34:35 +0100 Subject: [PATCH] Added search method on property field --- trytond/model/fields/property.py | 120 ++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/trytond/model/fields/property.py b/trytond/model/fields/property.py index 6906dd673e..8e3150d9d5 100644 --- a/trytond/model/fields/property.py +++ b/trytond/model/fields/property.py @@ -3,6 +3,7 @@ from trytond.model.fields.function import Function from trytond.model.fields.field import Field +from trytond import backend class Property(Function): @@ -10,12 +11,11 @@ class Property(Function): Define property field that is stored in ir.property (any) ''' - def __init__(self, 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): + def __init__(self, type='float', 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): ''' :param type: The type of field. :param fnct_search: The name of the function to search. @@ -25,10 +25,10 @@ class Property(Function): :param relation: Like model_name. :param add_remove: See Many2One. ''' - super(Property, self).__init__('', type=type, fnct_search=fnct_search, - model_name=model_name, selection=selection, digits=digits, - relation=relation, add_remove=add_remove, string=string, - help=help, required=required, readonly=readonly, domain=domain, + super(Property, self).__init__('', type=type, model_name=model_name, + selection=selection, digits=digits, relation=relation, + add_remove=add_remove, string=string, help=help, + required=required, readonly=readonly, domain=domain, states=states, priority=priority, change_default=change_default, translate=translate, select=select, on_change=on_change, on_change_with=on_change_with, depends=depends, @@ -71,3 +71,103 @@ class Property(Function): return property_obj.set(cursor, user, name, model._name, record_id, (value and (self.model_name or '') + ',' + str(value)) or False, context=context) + + + def search(self, cursor, user, model, name, args, context=None): + ''' + :param cursor: The database cursor. + :param user: The user id. + :param model: The model. + :param args: The search domain. See ModelStorage.search + :param context: The context. + :return: New list of domain. + ''' + rule_obj = model.pool.get('ir.rule') + + field_class = backend.FIELDS[self._type] + if not field_class: + return [] + sql_type = field_class.sql_type(model._columns[name]) + if not sql_type: + return [] + sql_type = sql_type[0] + + + conditions = "AND ".join( + self.get_condition(sql_type, arg) for arg in args) + cond_args = self.get_condition_args(args) + + + property_query, property_val = rule_obj.domain_get( + cursor, user, 'ir.property', context=context) + + #Fetch res ids that comply with the domain + cursor.execute( + "SELECT cast(split_part(ir_property.res,',',2) as integer), ir_property.id "\ + "FROM ir_property "\ + "JOIN ir_model_field on (ir_model_field.id = ir_property.field) "\ + "JOIN ir_model on (ir_model.id = ir_model_field.model) "\ + "WHERE "\ + "CASE WHEN "\ + "ir_model.model = %s AND ir_model_field.name = %s AND " \ + + property_query + \ + " THEN " + \ + conditions + \ + " ELSE "\ + "FALSE "\ + "END", + [model._name, name] + property_val + cond_args) + + + props = cursor.fetchall() + default = None + for x in props: + if not x[0]: + default = x[1] + break + + if not default: + return [('id', 'in', [x[0] for x in props])] + + #Fetch the res ids that doesn't use the default value + cursor.execute( + "SELECT cast(split_part(res,',',2) as integer) "\ + "FROM ir_property "\ + "WHERE " \ + + property_query + " AND res is not null", + property_val) + + if not cursor.rowcount: + return [('id', 'in', [x[0] for x in props])] + + else: + other_ids = [int(x[0]) for x in cursor.fetchall()] + + res_ids = model.search( + cursor, user, + ['OR', ('id', 'in', [x[0] for x in props]), + ('id', 'not in', other_ids)], + context=context) + + return [('id', 'in', res_ids)] + + @staticmethod + def get_condition(sql_type, arg): + if arg[1] in ('in', 'not in'): + return ("(cast(split_part(value,',',2) as %s) %s ("+ \ + ",".join('%%s' for x in arg[2]) + ")) ") % (sql_type, arg[1]) + else: + return "(cast(split_part(value,',',2) as %s) %s %%s) " % \ + (sql_type, arg[1]) + + @staticmethod + def get_condition_args(args): + res = [] + for arg in args: + if arg[1] in ('in', 'not in'): + res.extend(arg[2]) + else: + res.append(arg[2]) + return res + +