[FIX] Rewrite the field.property engine to work as expected (value per

company)

bzr revid: stephane@openerp.com-20100504144642-piruhn25d8qyxiof
This commit is contained in:
Quality Team 2010-05-04 16:46:42 +02:00 committed by Stephane Wirtel
parent 60f1981def
commit 6f53850e7d
4 changed files with 123 additions and 95 deletions

View File

@ -20,36 +20,41 @@
##############################################################################
from osv import osv,fields
from operator import attrgetter
# -------------------------------------------------------------------------
# Properties
# -------------------------------------------------------------------------
def _models_get(self, cr, uid, context={}):
obj = self.pool.get('ir.model.fields')
ids = obj.search(cr, uid, [('view_load','=',1)])
res = []
done = {}
for o in obj.browse(cr, uid, ids, context=context):
if o.model_id.id not in done:
res.append( [o.model_id.model, o.model_id.name])
done[o.model_id.id] = True
return res
class ir_property(osv.osv):
_name = 'ir.property'
def _models_field_get(self, cr, uid, field_key, field_value, context=None):
get = attrgetter(field_key, field_value)
obj = self.pool.get('ir.model.fields')
ids = obj.search(cr, uid, [('view_load','=',1)], context=context)
res = set()
for o in obj.browse(cr, uid, ids, context=context):
res.add(get(o))
return res
def _models_get(self, cr, uid, context=None):
return self._models_field_get(cr, uid, 'model_id.model', 'model_id.name',
context)
def _models_get2(self, cr, uid, context=None):
return self._models_field_get(cr, uid, 'relation', 'relation', context)
_columns = {
'name': fields.char('Name', size=128),
'value': fields.char('Value', size=128),
'res_id': fields.reference('Resource', selection=_models_get, size=128),
'value': fields.reference('Value', selection=_models_get2, size=128),
# 'value': fields.char('Value', size=128),
'res_id': fields.reference('Resource', selection=_models_get, size=128,
help="If not set, act as default property"),
'company_id': fields.many2one('res.company', 'Company'),
'fields_id': fields.many2one('ir.model.fields', 'Fields', ondelete='cascade', required=True)
}
def unlink(self, cr, uid, ids, context={}):
if ids:
cr.execute('DELETE FROM ir_model_fields WHERE id IN (SELECT fields_id FROM ir_property WHERE (fields_id IS NOT NULL) AND (id = ANY (%s)))', (ids,))
res = super(ir_property, self).unlink(cr, uid, ids, context)
return res
def get(self, cr, uid, name, model, res_id=False, context={}):
cr.execute('select id from ir_model_fields where name=%s and model=%s', (name, model))

View File

@ -109,11 +109,9 @@ class res_company(osv.osv):
proxy = self.pool.get('multi_company.default')
args = [
('object_id.model', '=', object),
('field_id', '=', field),
]
if field:
args.append(('field_id.name','=',field))
else:
args.append(('field_id','=',False))
ids = proxy.search(cr, uid, args, context=context)
for rule in proxy.browse(cr, uid, ids, context):
user = self.pool.get('res.users').browse(cr, uid, uid)

View File

@ -873,87 +873,93 @@ class serialized(_column):
class property(function):
def _fnct_write(self, obj, cr, uid, id, prop, id_val, val, context=None):
if not context:
def _get_domain(self, obj, cr, uid, prop_name, context=None):
def_id = self._field_get(cr, uid, obj._name, prop_name)
company = obj.pool.get('res.company')
cid = company._company_default_get(cr, uid, obj._name, def_id,
context=context)
domain = ['&', ('fields_id', '=', def_id),
'|', ('company_id', '=', cid), ('company_id', '=', False)]
return domain
def _get_default(self, obj, cr, uid, prop_name, context=None):
prop = obj.pool.get('ir.property')
domain = self._get_domain(obj, cr, uid, prop_name, context)
ids = prop.search(cr, uid, domain, order='company_id', context=context)
if not ids:
return False
return prop.browse(cr, uid, ids[0], context).value
def _get_by_id(self, obj, cr, uid, prop_name, ids, context=None):
prop = obj.pool.get('ir.property')
vids = [obj._name + ',' + str(oid) for oid in ids]
domain = [('res_id', 'in', vids)] + \
self._get_domain(obj, cr, uid, prop_name, context)
return prop.search(cr, uid, domain, context=context)
def _fnct_write(self, obj, cr, uid, id, prop_name, id_val, obj_dest, context=None):
if context is None:
context = {}
(obj_dest,) = val
definition_id = self._field_get(cr, uid, obj._name, prop)
property = obj.pool.get('ir.property')
nid = property.search(cr, uid, [('fields_id', '=', definition_id),
('res_id', '=', obj._name+','+str(id))])
while len(nid):
cr.execute('DELETE FROM ir_property WHERE id=%s', (nid.pop(),))
nids = self._get_by_id(obj, cr, uid, prop_name, [id], context)
if nids:
cr.execute('DELETE FROM ir_property WHERE id IN %s', (tuple(nids),))
nid = property.search(cr, uid, [('fields_id', '=', definition_id),
('res_id', '=', False)])
default_val = False
if nid:
default_val = property.browse(cr, uid, nid[0], context).value
default_val = self._get_default(obj, cr, uid, prop_name, context)
id_val = "%s,%d" % (obj_dest, id_val)
company_id = obj.pool.get('res.company')._company_default_get(cr, uid, obj._name, prop, context=context)
res = False
if val[0]:
newval = (id_val and obj_dest+','+str(id_val)) or False
else:
newval = id_val or False
if (newval != default_val) and newval:
propdef = obj.pool.get('ir.model.fields').browse(cr, uid,
definition_id, context=context)
res = property.create(cr, uid, {
if id_val and id_val != default_val:
def_id = self._field_get(cr, uid, obj._name, prop_name)
company = obj.pool.get('res.company')
cid = company._company_default_get(cr, uid, obj._name, def_id,
context=context)
propdef = obj.pool.get('ir.model.fields').browse(cr, uid, def_id,
context=context)
prop = obj.pool.get('ir.property')
return prop.create(cr, uid, {
'name': propdef.name,
'value': newval,
'value': id_val,
'res_id': obj._name+','+str(id),
'company_id': company_id,
'fields_id': definition_id
}, context=context)
return res
'company_id': cid,
'fields_id': def_id,
#'type': self._type,
}, context=context)
return False
def _fnct_read(self, obj, cr, uid, ids, prop, val, context=None):
if not context:
def _fnct_read(self, obj, cr, uid, ids, prop_name, obj_dest, context=None):
from orm import browse_record
if context is None:
context = {}
property = obj.pool.get('ir.property')
definition_id = self._field_get(cr, uid, obj._name, prop)
nid = property.search(cr, uid, [('fields_id', '=', definition_id),
('res_id', '=', False)])
default_val = False
if nid:
d = property.browse(cr, uid, nid[0], context).value
default_val = (d and int(d.split(',')[1])) or False
default_val = self._get_default(obj, cr, uid, prop_name, context)
if isinstance(default_val, browse_record):
default_val = default_val.id
else:
default_val = False
vids = [obj._name + ',' + str(id) for id in ids]
nids = property.search(cr, uid, [('fields_id', '=', definition_id),
('res_id', 'in', vids)])
nids = self._get_by_id(obj, cr, uid, prop_name, ids, context)
res = {}
for id in ids:
res[id] = default_val
for prop in property.browse(cr, uid, nids):
if prop.value.find(',') >= 0:
res[int(prop.res_id.id)] = (prop.value and \
int(prop.value.split(',')[1])) or False
else:
res[int(prop.res_id.id)] = prop.value or ''
if self._obj:
obj = obj.pool.get(self._obj)
to_check = res.values()
if default_val and default_val not in to_check:
to_check += [default_val]
existing_ids = obj.search(cr, uid, [('id', 'in', to_check)])
for id, res_id in res.items():
if res_id not in existing_ids:
cr.execute('DELETE FROM ir_property WHERE value=%s', ((obj._name+','+str(res_id)),))
res[id] = default_val
names = dict(obj.name_get(cr, uid, existing_ids, context))
for r in res.keys():
if res[r] and res[r] in names:
res[r] = (res[r], names[res[r]])
else:
res[r] = False
value = prop.value
if isinstance(value, browse_record):
if not value.exists():
cr.execute('DELETE FROM ir_property WHERE id=%s', (prop.id,))
continue
value = value.id
res[prop.res_id.id] = value or False
return res
def _field_get(self, cr, uid, model_name, prop):
if not self.field_id.get(cr.dbname):
cr.execute('SELECT id \
@ -964,9 +970,10 @@ class property(function):
return self.field_id[cr.dbname]
def __init__(self, obj_prop, **args):
#assert obj_prop
self.field_id = {}
function.__init__(self, self._fnct_read, False, self._fnct_write,
(obj_prop, ), **args)
obj_prop, **args)
def restart(self):
self.field_id = {}

View File

@ -170,6 +170,7 @@ class browse_record(object):
def __getitem__(self, name):
if name == 'id':
return self._id
if name not in self._data[self._id]:
# build the list of fields we will fetch
@ -179,10 +180,12 @@ class browse_record(object):
elif name in self._table._inherit_fields:
col = self._table._inherit_fields[name][2]
elif hasattr(self._table, str(name)):
if isinstance(getattr(self._table, name), (types.MethodType, types.LambdaType, types.FunctionType)):
return lambda *args, **argv: getattr(self._table, name)(self._cr, self._uid, [self._id], *args, **argv)
attr = getattr(self._table, name)
if isinstance(attr, (types.MethodType, types.LambdaType, types.FunctionType)):
return lambda *args, **argv: attr(self._cr, self._uid, [self._id], *args, **argv)
else:
return getattr(self._table, name)
return attr
else:
self.logger.notifyChannel("browse_record", netsvc.LOG_WARNING,
"Field '%s' does not exist in object '%s': \n%s" % (
@ -250,6 +253,8 @@ class browse_record(object):
context=self._context,
list_class=self._list_class,
fields_process=self._fields_process)
else:
new_data[n] = ids2
else:
new_data[n] = browse_null()
else:
@ -271,6 +276,7 @@ class browse_record(object):
else:
new_data[n] = data[n]
self._data[data['id']].update(new_data)
if not name in self._data[self._id]:
#how did this happen?
self.logger.notifyChannel("browse_record", netsvc.LOG_ERROR,
@ -299,9 +305,13 @@ class browse_record(object):
return "browse_record(%s, %d)" % (self._table_name, self._id)
def __eq__(self, other):
if not isinstance(other, browse_record):
return False
return (self._table_name, self._id) == (other._table_name, other._id)
def __ne__(self, other):
if not isinstance(other, browse_record):
return True
return (self._table_name, self._id) != (other._table_name, other._id)
# we need to define __unicode__ even though we've already defined __str__
@ -2583,8 +2593,13 @@ class orm(orm_template):
if nid:
prop_value = property_obj.browse(cr, uid, nid[0],
context=context).value
value[f] = (prop_value and int(prop_value.split(',')[1])) \
or False
if prop_value:
if isinstance(prop_value, (browse_record, browse_null)):
value[f] = prop_value.id
else:
value[f] = int(prop_value.rsplit(',', 1)[1])
else:
value[f] = False
# get the default values set by the user and override the default
# values defined in the object
@ -3802,9 +3817,12 @@ class orm(orm_template):
trans_obj.create(cr, uid, record, context)
return new_id
def exists(self, cr, uid, id, context=None):
cr.execute('SELECT count(1) FROM "%s" where id=%%s' % (self._table,), (id,))
return bool(cr.fetchone()[0])
def exists(self, cr, uid, ids, context=None):
if type(ids) in (int,long):
ids = [ids]
query = 'SELECT count(1) FROM "%s"' % (self._table)
cr.execute(query + "WHERE ID IN %s", (tuple(ids),))
return cr.fetchone()[0] == len(ids)
def check_recursion(self, cr, uid, ids, parent=None):
"""