KERNEL, MULTI_COMPANY_*, STOCK, BASE: extend search child_of

bzr revid: ced-7181fea25ddbb261cae5d70e3cfae2b01a7795d9
This commit is contained in:
ced 2007-06-07 08:43:46 +00:00
parent 3e70243021
commit 1edadd4f76
4 changed files with 87 additions and 88 deletions

View File

@ -995,7 +995,7 @@
</record>
<record model="ir.rule" id="property_rule">
<field name="field_id" search="[('model', '=', 'ir.property'), ('name', '=', 'company_id')]" model="ir.model.fields"/>
<field name="operator">=</field>
<field name="operator">child_of</field>
<field name="operand">user.company_id.id</field>
<field name="rule_group" ref="property_rule_group"/>
</record>

View File

@ -51,6 +51,7 @@ ir_rule_group()
class ir_rule(osv.osv):
_name = 'ir.rule'
_rec_name = 'field_id'
def _operand(self,cr,uid,context):
def get(object, level=3, ending=[], ending_excl=[], recur=[], root_tech='', root=''):
@ -71,9 +72,9 @@ class ir_rule(osv.osv):
return res
_columns = {
'field_id': fields.many2one('ir.model.fields', 'Field',domain= "[('model_id','=', parent.model_id)]",select=1),
'operator':fields.selection( (('=','='),('<>','<>'),('<=','<='),('>=','>=')),'Operator'),
'operand':fields.selection(_operand,'Operand', size=64),
'field_id': fields.many2one('ir.model.fields', 'Field',domain= "[('model_id','=', parent.model_id)]", select=1, required=True),
'operator':fields.selection((('=', '='), ('<>', '<>'), ('<=', '<='), ('>=', '>='), ('in', 'in'), ('child_of', 'child_of')), 'Operator', required=True),
'operand':fields.selection(_operand,'Operand', size=64, required=True),
'rule_group': fields.many2one('ir.rule.group', 'Group', select=2, required=True, ondelete="cascade")
}
@ -103,9 +104,12 @@ class ir_rule(osv.osv):
clause={}
# Use root user to prevent recursion
for rule in self.browse(cr, 1, ids):
dom = eval("[('%s', '%s', %s)]"%(rule.field_id.name, rule.operator, rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid), 'time':time})
if rule.operator in ('in', 'child_of'):
dom = eval("[('%s', '%s', [%s])]"%(rule.field_id.name, rule.operator, rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid), 'time':time})
else:
dom = eval("[('%s', '%s', %s)]"%(rule.field_id.name, rule.operator, rule.operand), {'user': self.pool.get('res.users').browse(cr, 1, uid), 'time':time})
clause.setdefault(rule.rule_group.id, [])
clause[rule.rule_group.id].append(obj._where_calc(dom))
clause[rule.rule_group.id].append(obj._where_calc(cr, uid, dom))
str = ''
val = []
for g in clause.values():

View File

@ -86,6 +86,8 @@ class res_company(osv.osv):
def write(self, *args, **argv):
self.cache_restart()
# Restart the cache on the company_get method
self.pool.get('ir.rule').domain_get()
return super(res_company, self).write(*args, **argv)
def _get_euro(self, cr, uid, context={}):

View File

@ -265,6 +265,7 @@ class orm(object):
_table = None
_name = None
_rec_name = 'name'
_parent_name = 'parent_id'
_order = 'id'
_inherits = {}
_sequence = None
@ -1337,69 +1338,7 @@ class orm(object):
return result
# TODO: ameliorer avec NULL
def _where_calc(self, args):
qu1, qu2 = [], []
for x in args:
table=self
if len(x) > 3:
table=x[3]
if x[1] != 'in':
#FIXME: this replace all (..., '=', False) values with 'is null' and this is
# not what we want for real boolean fields. The problem is, we can't change it
# easily because we use False everywhere instead of None
# NOTE FAB: we can't use None because it is not accepted by XML-RPC, that's why
# boolean (0-1), None -> False
# Ged> boolean fields are not always = 0 or 1
if (x[2] is False) and (x[1]=='='):
qu1.append(x[0]+' is null')
elif (x[2] is False) and (x[1]=='<>' or x[1]=='!='):
qu1.append(x[0]+' is not null')
else:
if x[0]=='id':
if x[1]=='join':
qu1.append('(%s.%s = %s)' % (table._table, x[0], x[2]))
else:
qu1.append('(%s.%s %s %%s)' % (table._table, x[0], x[1]))
qu2.append(x[2])
else:
if x[1] in ('like', 'ilike'):
if isinstance(x[2], str):
str_utf8 = x[2]
elif isinstance(x[2], unicode):
str_utf8 = x[2].encode('utf-8')
else:
str_utf8 = str(x[2])
qu2.append('%%%s%%' % str_utf8)
else:
qu2.append(table._columns[x[0]]._symbol_set[1](x[2]))
if x[1]=='=like':
x1 = 'like'
else:
x1 = x[1]
qu1.append('(%s.%s %s %s)' % (table._table, x[0], x1, table._columns[x[0]]._symbol_set[0]))
elif x[1]=='in':
if len(x[2])>0:
todel = []
for xitem in range(len(x[2])):
if x[2][xitem]==False and isinstance(x[2][xitem],bool):
todel.append(xitem)
for xitem in todel[::-1]:
del x[2][xitem]
if x[0]=='id':
qu1.append('(%s.id in (%s))' % (table._table, ','.join(['%d'] * len(x[2])),))
else:
qu1.append('(%s.%s in (%s))' % (table._table, x[0], ','.join([table._columns[x[0]]._symbol_set[0]]*len(x[2]))))
if todel:
qu1[-1] = '('+qu1[-1]+' or '+x[0]+' is null)'
qu2+=x[2]
else:
qu1.append(' (1=0)')
return (qu1,qu2)
def search_count(self, cr, user, args, context={}):
return 128
def search(self, cr, user, args, offset=0, limit=None, order=None, context={}):
def _where_calc(self, cr, user, args):
# if the object has a field named 'active', filter out all inactive
# records unless they were explicitely asked for
if 'active' in self._columns:
@ -1413,17 +1352,6 @@ class orm(object):
if not active_found:
args.append(('active', '=', 1))
# if the object has a field named 'company_id', filter out all
# records which do not concern the current company (the company
# of the current user) or its "childs"
# if 'company_id' in self._columns and not user == 1:
# compids = tools.get_user_companies(cr, user)
# if compids:
# compids.append(False)
# args.append(('company_id','in',compids))
i = 0
tables=[self._table]
joins=[]
@ -1481,16 +1409,18 @@ class orm(object):
ids2 = [x[0] for x in self.pool.get(field._obj).name_search(cr, user, args[i][2], [], 'like')]
else:
ids2 = args[i][2]
def _rec_get(ids, table):
if not len(ids):
def _rec_get(ids, table, parent):
if not ids:
return []
if 'active' in table._columns:
ids2 = table.search(cr, user, [(args[i][0],'in',ids),('active','=',0)])
ids2 += table.search(cr, user, [(args[i][0],'in',ids),('active','=',1)])
ids2 = table.search(cr, user, [(parent,'in',ids),('active','in', [True, False])])
else:
ids2 = table.search(cr, user, [(args[i][0], 'in', ids)])
return ids + _rec_get(ids2, table)
args[i] = ('id','in',ids2+_rec_get(ids2, table), table)
ids2 = table.search(cr, user, [(parent, 'in', ids)])
return ids + _rec_get(ids2, table, parent)
if field._obj <> table._name:
args[i] = (args[i][0],'in',ids2+_rec_get(ids2, self.pool.get(field._obj), table._parent_name), table)
else:
args[i] = ('id','in',ids2+_rec_get(ids2, table, args[i][0]), table)
else:
if isinstance(args[i][2], basestring):
res_ids = self.pool.get(field._obj).name_search(cr, user, args[i][2], [], args[i][1])
@ -1522,8 +1452,71 @@ class orm(object):
i+=1
args.extend(joins)
qu1, qu2 = [], []
for x in args:
table=self
if len(x) > 3:
table=x[3]
if x[1] != 'in':
#FIXME: this replace all (..., '=', False) values with 'is null' and this is
# not what we want for real boolean fields. The problem is, we can't change it
# easily because we use False everywhere instead of None
# NOTE FAB: we can't use None because it is not accepted by XML-RPC, that's why
# boolean (0-1), None -> False
# Ged> boolean fields are not always = 0 or 1
if (x[2] is False) and (x[1]=='='):
qu1.append(x[0]+' is null')
elif (x[2] is False) and (x[1]=='<>' or x[1]=='!='):
qu1.append(x[0]+' is not null')
else:
if x[0]=='id':
if x[1]=='join':
qu1.append('(%s.%s = %s)' % (table._table, x[0], x[2]))
else:
qu1.append('(%s.%s %s %%s)' % (table._table, x[0], x[1]))
qu2.append(x[2])
else:
if x[1] in ('like', 'ilike'):
if isinstance(x[2], str):
str_utf8 = x[2]
elif isinstance(x[2], unicode):
str_utf8 = x[2].encode('utf-8')
else:
str_utf8 = str(x[2])
qu2.append('%%%s%%' % str_utf8)
else:
qu2.append(table._columns[x[0]]._symbol_set[1](x[2]))
if x[1]=='=like':
x1 = 'like'
else:
x1 = x[1]
qu1.append('(%s.%s %s %s)' % (table._table, x[0], x1, table._columns[x[0]]._symbol_set[0]))
elif x[1]=='in':
if len(x[2])>0:
todel = []
for xitem in range(len(x[2])):
if x[2][xitem]==False and isinstance(x[2][xitem],bool):
todel.append(xitem)
for xitem in todel[::-1]:
del x[2][xitem]
if x[0]=='id':
qu1.append('(%s.id in (%s))' % (table._table, ','.join(['%d'] * len(x[2])),))
else:
qu1.append('(%s.%s in (%s))' % (table._table, x[0], ','.join([table._columns[x[0]]._symbol_set[0]]*len(x[2]))))
if todel:
qu1[-1] = '('+qu1[-1]+' or '+x[0]+' is null)'
qu2+=x[2]
else:
qu1.append(' (1=0)')
return (qu1,qu2,tables)
def search_count(self, cr, user, args, context={}):
return 128
def search(self, cr, user, args, offset=0, limit=None, order=None, context={}):
# compute the where, order by, limit and offset clauses
(qu1,qu2) = self._where_calc(args)
(qu1,qu2,tables) = self._where_calc(cr, user, args)
if len(qu1):
qu1 = ' where '+string.join(qu1,' and ')