Merge remote branch 'origin/master' into optimize
Conflicts: bin/osv/expression.py bin/osv/orm.py bzr revid: p_christ@hol.gr-20091026105650-49wvuk3o7qw1ybkn
This commit is contained in:
@@ -415,7 +415,8 @@ class ir_model_data(osv.osv):
|
||||
_defaults = {
|
||||
'date_init': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_update': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'noupdate': lambda *a: False
|
||||
'noupdate': lambda *a: False,
|
||||
'module': lambda *a: ''
|
||||
}
|
||||
_sql_constraints = [
|
||||
('module_name_uniq', 'unique(name, module)', 'You can not have multiple records with the same id for the same module'),
|
||||
|
||||
@@ -25,7 +25,7 @@ from report import report_sxw
|
||||
|
||||
class ir_module_reference_print(report_sxw.rml_parse):
|
||||
def __init__(self, cr, uid, name, context):
|
||||
super(ir_module_reference_print, self).__init__(cr, uid, name, context)
|
||||
super(ir_module_reference_print, self).__init__(cr, uid, name, context=context)
|
||||
self.localcontext.update({
|
||||
'time': time,
|
||||
'findobj': self._object_find,
|
||||
|
||||
+69
-21
@@ -44,18 +44,28 @@ class expression(object):
|
||||
and (((not internal) and element[1] in OPS) \
|
||||
or (internal and element[1] in INTERNAL_OPS))
|
||||
|
||||
def __execute_recursive_in(self, cr, s, f, w, ids):
|
||||
def __execute_recursive_in(self, cr, s, f, w, ids, op, type):
|
||||
# todo: merge into parent query as sub-query
|
||||
res = []
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
subids = ids[i:i+cr.IN_MAX]
|
||||
cr.execute('SELECT "%s"' \
|
||||
' FROM "%s"' \
|
||||
if ids:
|
||||
if op in ['<','>','>=','<=']:
|
||||
cr.execute('SELECT "%s"' \
|
||||
' FROM "%s"' \
|
||||
' WHERE "%s" %s %s' % (s, f, w, op, ids[0]))
|
||||
res.extend([r[0] for r in cr.fetchall()])
|
||||
else:
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
subids = ids[i:i+cr.IN_MAX]
|
||||
cr.execute('SELECT "%s"' \
|
||||
' FROM "%s"' \
|
||||
' WHERE "%s" = ANY (%%s)' % (s, f, w), (subids,))
|
||||
res.extend([r[0] for r in cr.fetchall()])
|
||||
else:
|
||||
cr.execute('SELECT distinct("%s")' \
|
||||
' FROM "%s" where "%s" is not null' % (s, f, s)),
|
||||
res.extend([r[0] for r in cr.fetchall()])
|
||||
return res
|
||||
|
||||
|
||||
def __init__(self, exp):
|
||||
# check if the expression is valid
|
||||
if not reduce(lambda acc, val: acc and (self._is_operator(val) or self._is_leaf(val)), exp, True):
|
||||
@@ -101,7 +111,6 @@ class expression(object):
|
||||
if self._is_operator(e) or e == self.__DUMMY_LEAF:
|
||||
continue
|
||||
left, operator, right = e
|
||||
|
||||
working_table = table
|
||||
main_table = table
|
||||
fargs = left.split('.', 1)
|
||||
@@ -154,14 +163,32 @@ class expression(object):
|
||||
|
||||
|
||||
elif field._type == 'one2many':
|
||||
if isinstance(right, basestring):
|
||||
ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)]
|
||||
else:
|
||||
ids2 = list(right)
|
||||
if not ids2:
|
||||
self.__exp[i] = ('id', '=', '0')
|
||||
else:
|
||||
self.__exp[i] = ('id', 'in', self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2))
|
||||
call_null = True
|
||||
|
||||
if right:
|
||||
if isinstance(right, basestring):
|
||||
ids2 = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None)]
|
||||
operator = 'in'
|
||||
else:
|
||||
if not isinstance(right,list):
|
||||
ids2 = [right]
|
||||
else:
|
||||
ids2 = right
|
||||
if not ids2:
|
||||
call_null = True
|
||||
operator = 'in' # operator changed because ids are directly related to main object
|
||||
else:
|
||||
call_null = False
|
||||
o2m_op = 'in'
|
||||
if operator in ['not like','not ilike','not in','<>','!=']:
|
||||
o2m_op = 'not in'
|
||||
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type))
|
||||
|
||||
if call_null:
|
||||
o2m_op = 'not in'
|
||||
if operator in ['not like','not ilike','not in','<>','!=']:
|
||||
o2m_op = 'in'
|
||||
self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0])
|
||||
|
||||
elif field._type == 'many2many':
|
||||
#FIXME
|
||||
@@ -174,17 +201,38 @@ class expression(object):
|
||||
def _rec_convert(ids):
|
||||
if field_obj == table:
|
||||
return ids
|
||||
return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids)
|
||||
return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids, operator, field._type)
|
||||
|
||||
dom = _rec_get(ids2, field_obj)
|
||||
ids2 = field_obj.search(cr, uid, dom, context=context)
|
||||
self.__exp[i] = ('id', 'in', _rec_convert(ids2))
|
||||
else:
|
||||
if isinstance(right, basestring):
|
||||
res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator)]
|
||||
else:
|
||||
res_ids = list(right)
|
||||
self.__exp[i] = ('id', 'in', self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids) or [0])
|
||||
call_null_m2m = True
|
||||
if right:
|
||||
if isinstance(right, basestring):
|
||||
res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator)]
|
||||
operator = 'in'
|
||||
else:
|
||||
if not isinstance(right, list):
|
||||
res_ids = [right]
|
||||
else:
|
||||
res_ids = right
|
||||
if not res_ids:
|
||||
call_null_m2m = True
|
||||
operator = 'in' # operator changed because ids are directly related to main object
|
||||
else:
|
||||
call_null_m2m = False
|
||||
m2m_op = 'in'
|
||||
if operator in ['not like','not ilike','not in','<>','!=']:
|
||||
m2m_op = 'not in'
|
||||
|
||||
self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids, operator, field._type) or [0])
|
||||
if call_null_m2m:
|
||||
m2m_op = 'not in'
|
||||
if operator in ['not like','not ilike','not in','<>','!=']:
|
||||
m2m_op = 'in'
|
||||
self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, [], operator, field._type) or [0])
|
||||
|
||||
elif field._type == 'many2one':
|
||||
if operator == 'child_of':
|
||||
if isinstance(right, basestring):
|
||||
|
||||
+68
-13
@@ -459,6 +459,15 @@ class orm_template(object):
|
||||
return False
|
||||
return ''
|
||||
|
||||
def selection_field(in_field):
|
||||
col_obj = self.pool.get(in_field.keys()[0])
|
||||
if f[i] in col_obj._columns.keys():
|
||||
return col_obj._columns[f[i]]
|
||||
elif f[i] in col_obj._inherits.keys():
|
||||
selection_field(col_obj._inherits)
|
||||
else:
|
||||
return False
|
||||
|
||||
lines = []
|
||||
data = map(lambda x: '', range(len(fields)))
|
||||
done = []
|
||||
@@ -482,7 +491,19 @@ class orm_template(object):
|
||||
else:
|
||||
break
|
||||
else:
|
||||
r = r[f[i]]
|
||||
r = r[f[i]]
|
||||
# To display external name of selection field when its exported
|
||||
if not context.get('import_comp',False):# Allow external name only if its not import compatible
|
||||
cols = False
|
||||
if f[i] in self._columns.keys():
|
||||
cols = self._columns[f[i]]
|
||||
elif f[i] in self._inherit_fields.keys():
|
||||
cols = selection_field(self._inherits)
|
||||
if cols and cols._type == 'selection':
|
||||
sel_list = cols.selection
|
||||
if type(sel_list) == type([]):
|
||||
r = [x[1] for x in sel_list if r==x[0]][0]
|
||||
|
||||
if not r:
|
||||
if f[i] in self._columns:
|
||||
r = check_type(self._columns[f[i]]._type)
|
||||
@@ -588,6 +609,9 @@ class orm_template(object):
|
||||
continue
|
||||
|
||||
field = fields[i]
|
||||
if prefix and not prefix[0] in field:
|
||||
continue
|
||||
|
||||
if (len(field)==len(prefix)+1) and field[len(prefix)].endswith(':db_id'):
|
||||
# Database ID
|
||||
res = False
|
||||
@@ -646,7 +670,7 @@ class orm_template(object):
|
||||
['res_id'])
|
||||
if res_res_id:
|
||||
res_id = res_res_id[0]['res_id']
|
||||
row[field[0][:-3]] = res_id or False
|
||||
row[field[-1][:-3]] = res_id or False
|
||||
continue
|
||||
if (len(field) == len(prefix)+1) and \
|
||||
len(field[len(prefix)].split(':lang=')) == 2:
|
||||
@@ -682,7 +706,7 @@ class orm_template(object):
|
||||
try:
|
||||
_check_db_id(self, model_name, line[i])
|
||||
data_res_id = is_db_id = int(line[i])
|
||||
except Exception,e:
|
||||
except Exception,e:
|
||||
warning += [tools.exception_to_unicode(e)]
|
||||
logger.notifyChannel("import", netsvc.LOG_ERROR,
|
||||
tools.exception_to_unicode(e))
|
||||
@@ -1071,19 +1095,37 @@ class orm_template(object):
|
||||
|
||||
buttons = (n for n in node.getElementsByTagName('button') if n.getAttribute('type') != 'object')
|
||||
for button in buttons:
|
||||
ok = True
|
||||
can_click = True
|
||||
if user != 1: # admin user has all roles
|
||||
user_roles = usersobj.read(cr, user, [user], ['roles_id'])[0]['roles_id']
|
||||
cr.execute("select role_id from wkf_transition where signal=%s", (button.getAttribute('name'),))
|
||||
# TODO handle the case of more than one workflow for a model
|
||||
cr.execute("""SELECT DISTINCT t.role_id
|
||||
FROM wkf
|
||||
INNER JOIN wkf_activity a ON a.wkf_id = wkf.id
|
||||
INNER JOIN wkf_transition t ON (t.act_to = a.id)
|
||||
WHERE wkf.osv = %s
|
||||
AND t.signal = %s
|
||||
""", (self._name, button.getAttribute('name'),))
|
||||
roles = cr.fetchall()
|
||||
for role in roles:
|
||||
if role[0]:
|
||||
ok = ok and rolesobj.check(cr, user, user_roles, role[0])
|
||||
|
||||
# draft -> valid = signal_next (role X)
|
||||
# draft -> cancel = signal_cancel (no role)
|
||||
#
|
||||
# valid -> running = signal_next (role Y)
|
||||
# valid -> cancel = signal_cancel (role Z)
|
||||
#
|
||||
# running -> done = signal_next (role Z)
|
||||
# running -> cancel = signal_cancel (role Z)
|
||||
|
||||
|
||||
if not ok:
|
||||
button.setAttribute('readonly', '1')
|
||||
else:
|
||||
button.setAttribute('readonly', '0')
|
||||
# As we don't know the object state, in this scenario,
|
||||
# the button "signal_cancel" will be always shown as there is no restriction to cancel in draft
|
||||
# the button "signal_next" will be show if the user has any of the roles (X Y or Z)
|
||||
# The verification will be made later in workflow process...
|
||||
if roles:
|
||||
can_click = any((not role) or rolesobj.check(cr, user, user_roles, role) for (role,) in roles)
|
||||
|
||||
button.setAttribute('readonly', str(int(not can_click)))
|
||||
|
||||
arch = node.toxml(encoding="utf-8").replace('\t', '')
|
||||
fields = self.fields_get(cr, user, fields_def.keys(), context)
|
||||
@@ -1221,6 +1263,15 @@ class orm_template(object):
|
||||
model = True
|
||||
sql_res = False
|
||||
while ok:
|
||||
view_ref = context.get(view_type + '_view_ref', False)
|
||||
if view_ref:
|
||||
if '.' in view_ref:
|
||||
module, view_ref = view_ref.split('.', 1)
|
||||
cr.execute("SELECT res_id FROM ir_model_data WHERE model='ir.ui.view' AND module=%s AND name=%s", (module, view_ref))
|
||||
view_ref_res = cr.fetchone()
|
||||
if view_ref_res:
|
||||
view_id = view_ref_res[0]
|
||||
|
||||
if view_id:
|
||||
where = (model and (" and model='%s'" % (self._name,))) or ''
|
||||
cr.execute('SELECT arch,name,field_parent,id,type,inherit_id FROM ir_ui_view WHERE id=%s'+where, (view_id,))
|
||||
@@ -1462,6 +1513,8 @@ class orm_memory(orm_template):
|
||||
return result
|
||||
|
||||
def write(self, cr, user, ids, vals, context=None):
|
||||
if not ids:
|
||||
return True
|
||||
vals2 = {}
|
||||
upd_todo = []
|
||||
for field in vals:
|
||||
@@ -1556,7 +1609,7 @@ class orm_memory(orm_template):
|
||||
|
||||
# get the default values from the context
|
||||
for key in context or {}:
|
||||
if key.startswith('default_'):
|
||||
if key.startswith('default_') and (key[8:] in fieds_list):
|
||||
value[key[8:]] = context[key]
|
||||
return value
|
||||
|
||||
@@ -2122,10 +2175,12 @@ class orm(orm_template):
|
||||
else:
|
||||
select = map(int,ids)
|
||||
result = self._read_flat(cr, user, select, fields, context, load)
|
||||
|
||||
for r in result:
|
||||
for key, v in r.items():
|
||||
if v == None:
|
||||
r[key] = False
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
return result and result[0] or False
|
||||
return result
|
||||
|
||||
@@ -475,10 +475,10 @@ class _rml_flowable(object):
|
||||
if key in ('rml_except', 'rml_loop', 'rml_tag'):
|
||||
del txt_n.attrib[key]
|
||||
if True or not self._textual(n).isspace():
|
||||
txt_n.text = utils.xml2str(self._textual(n))
|
||||
txt_n.tail = ''
|
||||
if not n.tag == 'bullet':
|
||||
txt_n.text = utils.xml2str(self._textual(n))
|
||||
txt_n.tail = n.tail and utils._process_text(self, n.tail.replace('\n','')) or ''
|
||||
rc1 += etree.tostring(txt_n)
|
||||
#rc1 += utils._process_text(self, node.tail or '')
|
||||
return rc1
|
||||
|
||||
def _table(self, node):
|
||||
|
||||
@@ -43,6 +43,8 @@ from lxml import etree
|
||||
import copy
|
||||
import tools
|
||||
import locale
|
||||
import netsvc
|
||||
import traceback, sys
|
||||
|
||||
_regex = re.compile('\[\[(.+?)\]\]')
|
||||
|
||||
@@ -108,9 +110,13 @@ def _process_text(self, txt):
|
||||
result += self.localcontext.get('translate', lambda x:x)(sps.pop(0))
|
||||
if sps:
|
||||
try:
|
||||
txt = eval(sps.pop(0),self.localcontext)
|
||||
except:
|
||||
pass
|
||||
expr = sps.pop(0)
|
||||
txt = eval(expr,self.localcontext)
|
||||
except Exception,e:
|
||||
tb_s = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
|
||||
netsvc.Logger().notifyChannel('report', netsvc.LOG_ERROR,
|
||||
'report :\n%s\n%s\nexpr: %s' % (tb_s, str(e),
|
||||
expr.encode('utf-8')))
|
||||
if type(txt)==type('') or type(txt)==type(u''):
|
||||
txt2 = str2xml(txt)
|
||||
result += tools.ustr(txt2)
|
||||
@@ -173,7 +179,7 @@ def attr_get(node, attrs, dict={}):
|
||||
res[key] = int(node.get(key))
|
||||
elif dict[key]=='unit':
|
||||
res[key] = unit_get(node.get(key))
|
||||
elif dict[key] == 'float' :
|
||||
elif dict[key] == 'float' :
|
||||
res[key] = float(node.get(key))
|
||||
return res
|
||||
|
||||
|
||||
Reference in New Issue
Block a user