regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
+
+POSTGRES_CONFDELTYPES = {
+ 'RESTRICT': 'r',
+ 'NO ACTION': 'a',
+ 'CASCADE': 'c',
+ 'SET NULL': 'n',
+ 'SET DEFAULT': 'd',
+}
+
def last_day_of_current_month():
today = datetime.date.today()
last_day = str(calendar.monthrange(today.year, today.month)[1])
new_data[n] = browse_null()
elif f._type in ('one2many', 'many2many') and len(data[n]):
new_data[n] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool.get(f._obj), self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in data[n]], self._context)
+ elif f._type in ('reference'):
+ if data[n]:
+ if isinstance(data[n], browse_record):
+ new_data[n] = data[n]
+ else:
+ ref_obj, ref_id = data[n].split(',')
+ ref_id = long(ref_id)
+ obj = self._table.pool.get(ref_obj)
+ compids = False
+ new_data[n] = browse_record(self._cr, self._uid, ref_id, obj, self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process)
+ else:
+ new_data[n] = browse_null()
else:
new_data[n] = data[n]
self._data[data['id']].update(new_data)
f_type = (type_dict[type(f)], type_dict[type(f)])
elif isinstance(f, fields.float):
if f.digits:
- f_type = ('numeric', 'NUMERIC(%d,%d)' % (f.digits[0], f.digits[1]))
+ f_type = ('numeric', 'NUMERIC')
else:
f_type = ('float8', 'DOUBLE PRECISION')
elif isinstance(f, (fields.char, fields.reference)):
f_type = (type_dict[t], type_dict[t])
elif isinstance(f, fields.function) and f._type == 'float':
if f.digits:
- f_type = ('numeric', 'NUMERIC(%d,%d)' % (f.digits[0], f.digits[1]))
+ f_type = ('numeric', 'NUMERIC')
else:
f_type = ('float8', 'DOUBLE PRECISION')
elif isinstance(f, fields.function) and f._type == 'selection':
CONCURRENCY_CHECK_FIELD = '__last_update'
+ def view_init(self, cr , uid , fields_list, context=None):
+ """Override this method to do specific things when a view on the object is opened."""
+ pass
+
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None):
raise _('The read_group method is not implemented on this object !')
model_id = cr.fetchone()[0]
if 'module' in context:
name_id = 'model_'+self._name.replace('.','_')
- cr.execute('select * from ir_model_data where name=%s and res_id=%s', (name_id,model_id))
+ cr.execute('select * from ir_model_data where name=%s and res_id=%s and module=%s', (name_id,model_id,context['module']))
if not cr.rowcount:
cr.execute("INSERT INTO ir_model_data (name,date_init,date_update,module,model,res_id) VALUES (%s, now(), now(), %s, %s, %s)", \
(name_id, context['module'], 'ir.model', model_id)
else:
module, xml_id = current_module, line[i]
id = ir_model_data_obj._get_id(cr, uid, module, xml_id)
+
res_res_id = ir_model_data_obj.read(cr, uid, [id],
['res_id'])
if res_res_id:
if fields and f not in fields:
continue
res[f] = {'type': self._columns[f]._type}
- for arg in ('string', 'readonly', 'states', 'size', 'required',
- 'change_default', 'translate', 'help', 'select', 'selectable'):
+ for arg in ('string', 'readonly', 'states', 'size', 'required', 'group_operator',
+ 'change_default', 'translate', 'help', 'select', 'selectable','parent_field'):
if getattr(self._columns[f], arg):
res[f][arg] = getattr(self._columns[f], arg)
if not read_access:
if context and context.get('active_id',False):
data_menu = self.pool.get('ir.ui.menu').browse(cr, user, context['active_id'], context).action
if data_menu:
- act_id = int(data_menu.split(',')[1])
+ act_id = data_menu.id
if act_id:
data_action = self.pool.get('ir.actions.act_window').browse(cr, user, [act_id], context)[0]
result['submenu'] = getattr(data_action,'menus', False)
'action': resaction,
'relate': resrelate
}
+ if result['type']=='form' and result['arch'].count("default_focus")>1:
+ msg = "Form View contain more than one default_focus attribute"
+ netsvc.Logger().notifyChannel('orm', netsvc.LOG_ERROR, msg)
+ raise except_orm('View Error !',msg)
return result
_view_look_dom_arch = __view_look_dom_arch
return id_new
def default_get(self, cr, uid, fields_list, context=None):
+ self.view_init(cr, uid, fields_list, context)
if not context:
context = {}
value = {}
_protected = ['read','write','create','default_get','perm_read','unlink','fields_get','fields_view_get','search','name_get','distinct_field_get','name_search','copy','import_data','search_count', 'exists']
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None):
+ groupby_list = groupby
+ if isinstance(groupby, list):
+ groupby = groupby[0]
context = context or {}
self.pool.get('ir.model.access').check(cr, uid, self._name, 'read', context=context)
if not fields:
fields = self._columns.keys()
(where_clause, where_params, tables) = self._where_calc(cr, uid, domain, context=context)
- dom = self.pool.get('ir.rule').domain_get(cr, uid, self._name, context=context)
+ dom = self.pool.get('ir.rule').domain_get(cr, uid, self._name, 'read', context=context)
where_clause = where_clause + dom[0]
where_params = where_params + dom[1]
for t in dom[2]:
fields_pre = [f for f in float_int_fields if
f == self.CONCURRENCY_CHECK_FIELD
or (f in self._columns and getattr(self._columns[f], '_classic_write'))]
- avg_fields = context.get('avg',[])
for f in fields_pre:
if f not in ['id','sequence']:
- if f in avg_fields:
- flist += ',avg('+f+') as '+f
- else:
- flist += ',sum('+f+') as '+f
+ operator = fget[f].get('group_operator','sum')
+ flist += ','+operator+'('+f+') as '+f
cr.execute('select min(%s.id) as id,' % self._table + flist + ' from ' + ','.join(tables) + where_clause + ' group by '+ groupby + limit_str + offset_str, where_params)
alldata = {}
groupby = group_by
for r in cr.dictfetchall():
+ for fld,val in r.items():
+ if val == None:r[fld] = False
alldata[r['id']] = r
del r['id']
data = self.read(cr, uid, alldata.keys(), [groupby], context=context)
for d in data:
d['__domain'] = [(groupby,'=',alldata[d['id']][groupby] or False)] + domain
+ d['__context'] = {'group_by':groupby_list[1:]}
if fget.has_key(groupby):
if d[groupby] and fget[groupby]['type'] in ('date','datetime'):
dt = datetime.datetime.strptime(alldata[d['id']][groupby][:7],'%Y-%m')
cr.commit()
for c in casts:
if (f_pg_type==c[0]) and (f._type==c[1]):
- # Adding upcoming 6 lines to check whether only the size of the fields got changed or not.E.g. :(16,3) to (16,4)
- field_size_change = False
- if f_pg_type in ['int4','numeric','float8']:
- if f.digits:
- field_size = (65535 * f.digits[0]) + f.digits[0] + f.digits[1]
- if field_size != f_pg_size:
- field_size_change = True
-
- if f_pg_type != f_obj_type or field_size_change:
+ if f_pg_type != f_obj_type:
if f_pg_type != f_obj_type:
logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed type to %s." % (k, self._table, c[1]))
- if field_size_change:
- logger.notifyChannel('orm', netsvc.LOG_INFO, "column '%s' in table '%s' changed in the size." % (k, self._table))
ok = True
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
"AND con.contype = 'f'", (self._table, ref, k, 'id'))
res = cr.dictfetchall()
if res:
- confdeltype = {
- 'RESTRICT': 'r',
- 'NO ACTION': 'a',
- 'CASCADE': 'c',
- 'SET NULL': 'n',
- 'SET DEFAULT': 'd',
- }
- if res[0]['confdeltype'] != confdeltype.get(f.ondelete.upper(), 'a'):
+ if res[0]['confdeltype'] != POSTGRES_CONFDELTYPES.get(f.ondelete.upper(), 'a'):
cr.execute('ALTER TABLE "' + self._table + '" DROP CONSTRAINT "' + res[0]['conname'] + '"')
cr.execute('ALTER TABLE "' + self._table + '" ADD FOREIGN KEY ("' + k + '") REFERENCES "' + ref + '" ON DELETE ' + f.ondelete)
cr.commit()
self._columns = self._columns.copy()
for store_field in self._columns:
f = self._columns[store_field]
+ if hasattr(f, 'digits_change'):
+ f.digits_change(cr)
if not isinstance(f, fields.function):
continue
if not f.store:
#
# Update objects that uses this one to update their _inherits fields
#
+
def _inherits_reload_src(self):
for obj in self.pool.obj_pool.values():
if self._name in obj._inherits:
fields_to_read = self._columns.keys()
# construct a clause for the rules :
- d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context)
-
+ d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context)
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True
fields_pre = [f for f in fields_to_read if
f == self.CONCURRENCY_CHECK_FIELD
return '"%s"' % (f,)
fields_pre2 = map(convert_field, fields_pre)
order_by = self._parent_order or self._order
- for i in range(0, len(ids), cr.IN_MAX):
- sub_ids = ids[i:i+cr.IN_MAX]
+ for sub_ids in cr.split_for_in_conditions(ids):
if d1:
- cr.execute('SELECT %s FROM %s WHERE %s.id = ANY (%%s) AND %s ORDER BY %s' % \
+ cr.execute('SELECT %s FROM %s WHERE %s.id IN %%s AND %s ORDER BY %s' % \
(','.join(fields_pre2 + [self._table + '.id']), ','.join(tables), self._table, ' and '.join(d1),
order_by),[sub_ids,]+d2)
- if not cr.rowcount == len({}.fromkeys(sub_ids)):
+ if cr.rowcount != len(sub_ids):
raise except_orm(_('AccessError'),
_('You try to bypass an access rule while reading (Document type: %s).') % self._description)
else:
- cr.execute('SELECT %s FROM \"%s\" WHERE id = ANY (%%s) ORDER BY %s' %
+ cr.execute('SELECT %s FROM \"%s\" WHERE id IN %%s ORDER BY %s' %
(','.join(fields_pre2 + ['id']), self._table,
order_by), (sub_ids,))
res.extend(cr.dictfetchall())
# all fields which need to be post-processed by a simple function (symbol_get)
fields_post = filter(lambda x: x in self._columns and self._columns[x]._symbol_get, fields_to_read)
if fields_post:
- # maybe it would be faster to iterate on the fields then on res, so that we wouldn't need
- # to get the _symbol_get in each occurence
for r in res:
for f in fields_post:
r[f] = self._columns[f]._symbol_get(r[f])
if res and res[0]:
raise except_orm('ConcurrencyException', _('Records were modified in the meanwhile'))
+ def check_access_rule(self, cr, uid, ids, operation, context=None):
+ """Verifies that the operation given by ``operation`` is allowed for the user
+ according to ir.rules.
+ @param ``operation``: one of ``'read'``, ``'write'``, ``'unlink'``
+ @raise ``except_orm``: if current ir.rules do not permit this operation.
+ @return: ``None`` if the operation is allowed
+ """
+ where_clause, where_params, tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name, operation, context=context)
+ if where_clause:
+ where_clause = ' and ' + ' and '.join(where_clause)
+ for sub_ids in cr.split_for_in_conditions(ids):
+ cr.execute('SELECT ' + self._table + '.id FROM ' + ','.join(tables) +
+ ' WHERE ' + self._table + '.id IN %s' + where_clause,
+ [sub_ids] + where_params)
+ if cr.rowcount != len(sub_ids):
+ raise except_orm(_('AccessError'),
+ _('Operation prohibited by access rules (Operation: %s, Document type: %s).')
+ % (operation, self._name))
+
def unlink(self, cr, uid, ids, context=None):
if not ids:
return True
# ids2 = [x[self._inherits[key]] for x in res]
# self.pool.get(key).unlink(cr, uid, ids2)
- d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name, context=context)
- if d1:
- d1 = ' AND '+' and '.join(d1)
-
- for i in range(0, len(ids), cr.IN_MAX):
- sub_ids = ids[i:i+cr.IN_MAX]
- str_d = string.join(('%s',)*len(sub_ids), ',')
- if d1:
- cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \
- 'WHERE '+self._table+'.id IN ('+str_d+')'+d1, sub_ids+d2)
- if not cr.rowcount == len(sub_ids):
- raise except_orm(_('AccessError'),
- _('You try to bypass an access rule (Document type: %s).') % \
- self._description)
-
- cr.execute('delete from '+self._table+' ' \
- 'where id in ('+str_d+')', sub_ids)
+ self.check_access_rule(cr, uid, ids, 'unlink', context=context)
+ for sub_ids in cr.split_for_in_conditions(ids):
+ cr.execute('delete from ' + self._table + ' ' \
+ 'where id in %s', sub_ids)
for order, object, store_ids, fields in result_store:
- if object<>self._name:
+ if object != self._name:
obj = self.pool.get(object)
cr.execute('select id from '+obj._table+' where id in ('+','.join(map(str, store_ids))+')')
rids = map(lambda x: x[0], cr.fetchall())
upd1.append(user)
if len(upd0):
-
- d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context)
- if d1:
- d1 = ' and '+' and '.join(d1)
-
- for i in range(0, len(ids), cr.IN_MAX):
- sub_ids = ids[i:i+cr.IN_MAX]
- ids_str = string.join(map(str, sub_ids), ',')
- if d1:
- cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \
- 'WHERE '+self._table+'.id IN ('+ids_str+')'+d1, d2)
- if not cr.rowcount == len({}.fromkeys(sub_ids)):
- raise except_orm(_('AccessError'),
- _('You try to bypass an access rule while writing (Document type: %s).') % \
- self._description)
- else:
- cr.execute('SELECT id FROM "'+self._table+'" WHERE id IN ('+ids_str+')')
- if not cr.rowcount == len({}.fromkeys(sub_ids)):
- raise except_orm(_('AccessError'),
- _('You try to write on an record that doesn\'t exist ' \
- '(Document type: %s).') % self._description)
- cr.execute('update '+self._table+' set '+string.join(upd0, ',')+' ' \
- 'where id in ('+ids_str+')', upd1)
+ self.check_access_rule(cr, user, ids, 'write', context=context)
+ for sub_ids in cr.split_for_in_conditions(ids):
+ cr.execute('update ' + self._table + ' set ' + ','.join(upd0) + ' ' \
+ 'where id in %s', upd1 + [sub_ids])
if totranslate:
# TODO: optimize
for table in self._inherits:
col = self._inherits[table]
nids = []
- for i in range(0, len(ids), cr.IN_MAX):
- sub_ids = ids[i:i+cr.IN_MAX]
- ids_str = string.join(map(str, sub_ids), ',')
+ for sub_ids in cr.split_for_in_conditions(ids):
cr.execute('select distinct "'+col+'" from "'+self._table+'" ' \
- 'where id in ('+ids_str+')', upd1)
+ 'where id in %s', (sub_ids,))
nids.extend([x[0] for x in cr.fetchall()])
v = {}
if self._inherits[v] not in vals:
tocreate[v] = {}
else:
- tocreate[v] = {self._inherits[v]:vals[self._inherits[v]]}
+ tocreate[v] = {'id' : vals[self._inherits[v]]}
(upd0, upd1, upd2) = ('', '', [])
upd_todo = []
for v in vals.keys():
for table in tocreate:
if self._inherits[table] in vals:
del vals[self._inherits[table]]
- id = self.pool.get(table).create(cr, user, tocreate[table])
+
+ record_id = tocreate[table].pop('id', None)
+
+ if record_id is None:
+ record_id = self.pool.get(table).create(cr, user, tocreate[table], context=context)
+ else:
+ self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=context)
+
upd0 += ','+self._inherits[table]
upd1 += ',%s'
- upd2.append(id)
+ upd2.append(record_id)
#Start : Set bool fields to be False if they are not touched(to make search more powerful)
bool_fields = [x for x in self._columns.keys() if self._columns[x]._type=='boolean']
upd1 = upd1 + ',' + self._columns[field]._symbol_set[0]
upd2.append(self._columns[field]._symbol_set[1](vals[field]))
else:
- upd_todo.append(field)
+ if not isinstance(self._columns[field], fields.related):
+ upd_todo.append(field)
if field in self._columns \
and hasattr(self._columns[field], 'selection') \
and vals[field]:
upd1 += ',%s,now()'
upd2.append(user)
cr.execute('insert into "'+self._table+'" (id'+upd0+") values ("+str(id_new)+upd1+')', tuple(upd2))
+ d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'create', context=context)
+ if d1:
+ d1 = ' AND '+' AND '.join(d1)
+ cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \
+ 'WHERE '+self._table+'.id = ' +str(id_new)+d1,d2)
+ if not cr.rowcount:
+ raise except_orm(_('AccessError'),
+ _('You try to bypass an access rule to create (Document type: %s).') \
+ % self._name)
upd_todo.sort(lambda x, y: self._columns[x].priority-self._columns[y].priority)
if self._parent_store:
upd0.append('"'+v+'"='+self._columns[v]._symbol_set[0])
upd1.append(self._columns[v]._symbol_set[1](value[v]))
upd1.append(id)
- cr.execute('update "' + self._table + '" set ' + \
- string.join(upd0, ',') + ' where id = %s', upd1)
+ if upd0 and upd1:
+ cr.execute('update "' + self._table + '" set ' + \
+ string.join(upd0, ',') + ' where id = %s', upd1)
else:
for f in val:
context = {}
# compute the where, order by, limit and offset clauses
(qu1, qu2, tables) = self._where_calc(cr, user, args, context=context)
- dom = self.pool.get('ir.rule').domain_get(cr, user, self._name, context=context)
+ dom = self.pool.get('ir.rule').domain_get(cr, user, self._name, 'read', context=context)
qu1 = qu1 + dom[0]
qu2 = qu2 + dom[1]
for t in dom[2]: