From 1a8baa044a9a88e645c42f282821ae99203dbd19 Mon Sep 17 00:00:00 2001 From: Quality Team <> Date: Wed, 5 May 2010 12:02:41 +0200 Subject: [PATCH] [IMP] Add the capabilities to store a datetime, date, integer, float and char in a field.property lp bug: https://launchpad.net/bugs/562356 fixed bzr revid: stephane@openerp.com-20100505100241-o5w0twdccrs7ppx2 --- bin/addons/base/__terp__.py | 2 +- .../1.2/pre-10-ir_property_rename_column.py | 20 +++ bin/addons/base/res/ir_property.py | 131 ++++++++++++++++-- bin/addons/base/res/ir_property_view.xml | 8 +- bin/osv/fields.py | 31 ++--- bin/osv/orm.py | 21 ++- 6 files changed, 166 insertions(+), 47 deletions(-) create mode 100644 bin/addons/base/migrations/1.2/pre-10-ir_property_rename_column.py 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'))