diff --git a/bin/addons/base/__terp__.py b/bin/addons/base/__terp__.py
index 3f50b319692..d0dc9b68dd3 100644
--- a/bin/addons/base/__terp__.py
+++ b/bin/addons/base/__terp__.py
@@ -22,7 +22,7 @@
{
'name': 'Base',
- 'version': '1.1',
+ 'version': '1.2',
'category': 'Generic Modules/Base',
'description': """The kernel of OpenERP, needed for all installation.""",
'author': 'Tiny',
diff --git a/bin/addons/base/migrations/1.2/pre-10-ir_property_rename_column.py b/bin/addons/base/migrations/1.2/pre-10-ir_property_rename_column.py
new file mode 100644
index 00000000000..8c79e735c30
--- /dev/null
+++ b/bin/addons/base/migrations/1.2/pre-10-ir_property_rename_column.py
@@ -0,0 +1,20 @@
+# -*- coding: utf8 -*-
+
+__name__ = "ir.property: Rename column value to value_reference"
+
+def migrate(cr, version):
+ rename_column(cr, 'ir_property', 'value', 'value_reference')
+
+def column_exists(cr, table, column):
+ cr.execute("SELECT count(1)"
+ " FROM pg_class c, pg_attribute a"
+ " WHERE c.relname=%s"
+ " AND c.oid=a.attrelid"
+ " AND a.attname=%s",
+ (table, column))
+ return cr.fetchone()[0] != 0
+
+def rename_column(cr, table, old, new):
+ if column_exists(cr, table, old) and not column_exists(cr, table, new):
+ cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % (table, old, new))
+
diff --git a/bin/addons/base/res/ir_property.py b/bin/addons/base/res/ir_property.py
index c7673bf4b26..40df4b2ec2a 100644
--- a/bin/addons/base/res/ir_property.py
+++ b/bin/addons/base/res/ir_property.py
@@ -21,6 +21,7 @@
from osv import osv,fields
from operator import attrgetter
+import time
# -------------------------------------------------------------------------
# Properties
# -------------------------------------------------------------------------
@@ -48,24 +49,130 @@ class ir_property(osv.osv):
_columns = {
'name': fields.char('Name', 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)
+ 'fields_id': fields.many2one('ir.model.fields', 'Fields', ondelete='cascade', required=True),
+
+ 'value_float' : fields.float('Value'),
+ 'value_integer' : fields.integer_big('Value'), # will contain (int, bigint)
+ 'value_text' : fields.text('Value'), # will contain (char, text)
+ 'value_binary' : fields.binary('Value'),
+ 'value_reference': fields.reference('Value', selection=_models_get2, size=128),
+ 'value_datetime' : fields.datetime('Value'),
+
+ 'type' : fields.selection([('char', 'Char'),
+ ('float', 'Float'),
+ ('integer', 'Integer'),
+ ('integer_big', 'Integer Big'),
+ ('text', 'Text'),
+ ('binary', 'Binary'),
+ ('many2one', 'Many2One'),
+ ('date', 'Date'),
+ ('datetime', 'DateTime'),
+ ],
+ 'Type',
+ required=True,
+ select=1),
}
- 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))
- res = cr.fetchone()
- if res:
- ucid = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
- nid = self.search(cr, uid, [('fields_id','=',res[0]),('res_id','=',res_id),('company_id','=',ucid)])
- if nid:
- d = self.browse(cr, uid, nid[0], context).value
- return (d and int(d.split(',')[1])) or False
+ _defaults = {
+ 'type': 'many2one',
+ }
+
+ def _update_values(self, cr, uid, ids, values):
+ value = values.pop('value', None)
+ if not value:
+ return values
+ type_ = values.get('type', 'many2one')
+ type2field = {
+ 'char': 'value_text',
+ 'float': 'value_float',
+ 'integer': 'value_integer',
+ 'integer_big': 'value_integer',
+ 'text': 'value_text',
+ 'binary': 'value_binary',
+ 'many2one': 'value_reference',
+ 'date' : 'value_datetime',
+ 'datetime' : 'value_datetime',
+ }
+ field = type2field.get(type_)
+ if not field:
+ raise osv.except_osv('Error', 'Invalid type')
+
+ if field == 'value_reference':
+ if isinstance(value, osv.orm.browse_record):
+ value = '%s,%d' % (value._name, value.id)
+ elif isinstance(value, (int, long)):
+ field_id = values.get('fields_id')
+ if not field_id:
+ if not ids:
+ raise ValueError()
+ field_id = self.browse(cr, uid, ids[0]).fields_id
+ else:
+ field_id = self.pool.get('ir.model.fields').browse(cr, uid, field_id)
+
+ value = '%s,%d' % (field_id.relation, value)
+
+ values[field] = value
+ return values
+
+
+ def write(self, cr, uid, ids, values, context=None):
+ return super(ir_property, self).write(cr, uid, ids, self._update_values(cr, uid, ids, values), context=context)
+
+ def create(self, cr, uid, values, context=None):
+ return super(ir_property, self).create(cr, uid, self._update_values(cr, uid, None, values), context=context)
+
+ def get_by_id(self, cr, uid, record_ids, context=None):
+ if isinstance(record_ids, (int, long)):
+ record_ids = [record_ids]
+
+ if not record_ids:
+ return False
+
+ record = self.browse(cr, uid, record_ids[0], context=context)
+
+ if record.type in ('char', 'text'):
+ return record.value_text
+ elif record.type == 'float':
+ return record.value_float
+ elif record.type in ('integer', 'integer_big'):
+ return record.value_integer
+ elif record.type == 'binary':
+ return record.value_binary
+ elif record.type == 'many2one':
+ return record.value_reference
+ elif record.type == 'datetime':
+ return record.value_datetime
+ elif record.type == 'date':
+ return time.strftime('%Y-%m-%d', time.strptime(record.value_datetime, '%Y-%m-%d %H:%M:%S'))
+
return False
+
+ def get(self, cr, uid, name, model, res_id=False, context=None):
+ domain = self._get_domain(cr, uid, name, model, context=context)
+ if domain is not None:
+ domain = [('res_id', '=', res_id)] + domain
+ nid = self.search(cr, uid, domain, context=context)
+ return self.get_by_id(cr, uid, nid, context=context)
+ return False
+
+ def _get_domain(self, cr, uid, prop_name, model, context=None):
+ cr.execute('select id from ir_model_fields where name=%s and model=%s', (prop_name, model))
+ res = cr.fetchone()
+ if not res:
+ return None
+
+ company = self.pool.get('res.company')
+ cid = company._company_default_get(cr, uid, model, res[0],
+ context=context)
+
+ domain = ['&', ('fields_id', '=', res[0]),
+ '|', ('company_id', '=', cid), ('company_id', '=', False)]
+ return domain
+
ir_property()
diff --git a/bin/addons/base/res/ir_property_view.xml b/bin/addons/base/res/ir_property_view.xml
index 3a2f56170fa..a4dac386148 100644
--- a/bin/addons/base/res/ir_property_view.xml
+++ b/bin/addons/base/res/ir_property_view.xml
@@ -29,7 +29,13 @@
-
+
+
+
+
+
+
+
diff --git a/bin/osv/fields.py b/bin/osv/fields.py
index be1f5c2baac..a38301ba184 100644
--- a/bin/osv/fields.py
+++ b/bin/osv/fields.py
@@ -873,33 +873,25 @@ class serialized(_column):
class property(function):
- 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)
+ domain = prop._get_domain(cr, uid, prop_name, obj._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
+ return prop.get_by_id(cr, uid, ids, context=context)
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)
+ domain = prop._get_domain(cr, uid, prop_name, obj._name, context)
+ if domain is not None:
+ domain = [('res_id', 'in', vids)] + domain
+ return prop.search(cr, uid, domain, context=context)
+ else:
+ return []
- 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:
@@ -910,7 +902,6 @@ class property(function):
cr.execute('DELETE FROM ir_property WHERE id IN %s', (tuple(nids),))
default_val = self._get_default(obj, cr, uid, prop_name, context)
- id_val = "%s,%d" % (obj_dest, id_val)
if id_val and id_val != default_val:
def_id = self._field_get(cr, uid, obj._name, prop_name)
@@ -926,7 +917,7 @@ class property(function):
'res_id': obj._name+','+str(id),
'company_id': cid,
'fields_id': def_id,
- #'type': self._type,
+ 'type': self._type,
}, context=context)
return False
@@ -950,7 +941,7 @@ class property(function):
for id in ids:
res[id] = default_val
for prop in property.browse(cr, uid, nids):
- value = prop.value
+ value = prop.get_by_id(context=context)
if isinstance(value, browse_record):
if not value.exists():
cr.execute('DELETE FROM ir_property WHERE id=%s', (prop.id,))
@@ -970,7 +961,7 @@ class property(function):
return self.field_id[cr.dbname]
def __init__(self, obj_prop, **args):
- #assert obj_prop
+ # TODO remove obj_prop parameter (use many2one type)
self.field_id = {}
function.__init__(self, self._fnct_read, False, self._fnct_write,
obj_prop, **args)
diff --git a/bin/osv/orm.py b/bin/osv/orm.py
index 161364a13bc..133f6cdda68 100644
--- a/bin/osv/orm.py
+++ b/bin/osv/orm.py
@@ -2587,19 +2587,14 @@ class orm(orm_template):
or False
if isinstance(fld_def, fields.property):
property_obj = self.pool.get('ir.property')
- definition_id = fld_def._field_get(cr, uid, self._name, f)
- nid = property_obj.search(cr, uid, [('fields_id', '=',
- definition_id), ('res_id', '=', False)])
- if nid:
- prop_value = property_obj.browse(cr, uid, nid[0],
- context=context).value
- 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])
+ prop_value = property_obj.get(cr, uid, f, self._name, context=context)
+ if prop_value:
+ if isinstance(prop_value, (browse_record, browse_null)):
+ value[f] = prop_value.id
else:
- value[f] = False
+ value[f] = prop_value
+ else:
+ value[f] = False
# get the default values set by the user and override the default
# values defined in the object
@@ -2991,7 +2986,7 @@ class orm(orm_template):
properties = self.pool.get('ir.property')
domain = [('res_id', '=', False),
- ('value', 'in', ['%s,%s' % (self._name, i) for i in ids]),
+ ('value_reference', 'in', ['%s,%s' % (self._name, i) for i in ids]),
]
if properties.search(cr, uid, domain, context=context):
raise except_orm(_('Error'), _('Unable to delete this document because it is used as a default property'))