[MERGE] OPW 578099: ir.filters should be translated according to the user language
[odoo/odoo.git] / bin / osv / orm.py
index 86ce081..64d24c4 100644 (file)
@@ -723,10 +723,10 @@ class orm_template(object):
             if mode=='.id':
                 id = int(id)
                 obj_model = self.pool.get(model_name)
+                dom = [('id', '=', id)]
                 if obj_model._columns.get('active'):
-                    ids = obj_model.search(cr, uid, [('id', '=', int(id)),('active','in',['True','False'])], context=context)
-                else:
-                    ids = obj_model.search(cr, uid, [('id', '=', int(id))], context=context)
+                    dom.append(('active', 'in', ['True','False']))
+                ids = obj_model.search(cr, uid, dom, context=context)
                 if not len(ids):
                     raise Exception(_("Database ID doesn't exist: %s : %s") %(model_name, id))
             elif mode=='id':
@@ -767,8 +767,6 @@ class orm_template(object):
             done = {}
             for i in range(len(fields)):
                 res = False
-                if not line[i]:
-                    continue
                 if i >= len(line):
                     raise Exception(_('Please check that all your lines have %d columns.') % (len(fields),))
 
@@ -820,7 +818,7 @@ class orm_template(object):
                         mode = False
                     else:
                         mode = field[len(prefix)+1]
-                    res = _get_id(relation, line[i], current_module, mode)
+                    res = line[i] and _get_id(relation, line[i], current_module, mode) or False
 
                 elif fields_def[field[len(prefix)]]['type']=='many2many':
                     relation = fields_def[field[len(prefix)]]['relation']
@@ -831,8 +829,9 @@ class orm_template(object):
 
                     # TODO: improve this by using csv.csv_reader
                     res = []
-                    for db_id in line[i].split(config.get('csv_internal_sep')):
-                        res.append( _get_id(relation, db_id, current_module, mode) )
+                    if line[i]:
+                        for db_id in line[i].split(config.get('csv_internal_sep')):
+                            res.append( _get_id(relation, db_id, current_module, mode) )
                     res = [(6,0,res)]
 
                 elif fields_def[field[len(prefix)]]['type'] == 'integer':
@@ -880,7 +879,7 @@ class orm_template(object):
                      current_module, res, mode=mode, xml_id=xml_id,
                      noupdate=noupdate, res_id=res_id, context=context)
             except Exception, e:
-                return (-1, res, 'Line ' + str(position) +' : ' + str(e), '')
+                return (-1, res, 'Line ' + str(position) +' : ' + tools.ustr(e), '')
 
             if config.get('import_partial', False) and filename and (not (position%100)):
                 data = pickle.load(file(config.get('import_partial')))
@@ -1621,10 +1620,13 @@ class orm_template(object):
             elif view_type == 'tree':
                 _rec_name = self._rec_name
                 if _rec_name not in self._columns:
-                    _rec_name = self._columns.keys()[0]
+                    if len(self._columns.keys()):
+                        _rec_name = self._columns.keys()[0]
+                    else:
+                        _rec_name = 'id'
                 xml = '<?xml version="1.0" encoding="utf-8"?>' \
                        '<tree string="%s"><field name="%s"/></tree>' \
-                       % (self._description, self._rec_name)
+                       % (self._description, _rec_name)
 
             elif view_type == 'calendar':
                 xml = self.__get_default_calendar_view()
@@ -1961,11 +1963,30 @@ class orm_memory(orm_template):
                 result.append(r)
                 if id in self.datas:
                     self.datas[id]['internal.date_access'] = time.time()
+            # all non inherited fields for which the attribute whose name is in load is False
             fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields_to_read)
+            todo = {}
             for f in fields_post:
-                res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result)
-                for record in result:
-                    record[f] = res2[record['id']]
+                todo.setdefault(self._columns[f]._multi, [])
+                todo[self._columns[f]._multi].append(f)
+            for key, val in todo.items():
+                if key:
+                    res2 = self._columns[val[0]].get_memory(cr, self, ids, val, user, context=context, values=result)
+                    for pos in val:
+                        for record in result:
+                            if isinstance(res2[record['id']], str): res2[record['id']] = eval(res2[record['id']]) #TOCHECK : why got string instend of dict in python2.6
+                            multi_fields = res2.get(record['id'],{})
+                            if multi_fields:
+                                record[pos] = multi_fields.get(pos,[])
+                else:
+                    for f in val:
+                        res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result)
+                        for record in result:
+                            if res2:
+                                record[f] = res2[record['id']]
+                            else:
+                                record[f] = []
+                
             if isinstance(ids_orig, (int, long)):
                 return result[0]
         return result
@@ -2061,14 +2082,13 @@ class orm_memory(orm_template):
             return self.datas.keys()
 
         res = []
-        counter = 0
+        counter = 1
         #Find the value of dict
         f = False
         if result:
             for id, data in self.datas.items():
-                counter = counter + 1
                 data['id'] = id
-                if limit and (counter > int(limit)):
+                if limit and (counter > int(limit) + int(offset)):
                     break
                 f = True
                 for arg in result:
@@ -2078,11 +2098,11 @@ class orm_memory(orm_template):
                         val = eval('data[arg[0]]'+arg[1] +' arg[2]', locals())
                     elif arg[1] in ['ilike']:
                         val = (str(data[arg[0]]).find(str(arg[2]))!=-1)
-
                     f = f and val
-
                 if f:
-                    res.append(id)
+                    if counter > offset:
+                        res.append(id)
+                    counter += 1
         if count:
             return len(res)
         return res or []
@@ -2123,6 +2143,7 @@ class orm_memory(orm_template):
 class orm(orm_template):
     _sql_constraints = []
     _table = None
+    _all_columns = {}
     _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']
     __logger = logging.getLogger('orm')
     __schema = logging.getLogger('orm.schema')
@@ -2179,10 +2200,13 @@ class orm(orm_template):
         group_count = group_by = groupby
         if groupby:
             if fget.get(groupby):
-                if fget[groupby]['type'] in ('date', 'datetime'):
-                    flist = "to_char(%s,'yyyy-mm') as %s " % (qualified_groupby_field, groupby)
-                    groupby = "to_char(%s,'yyyy-mm')" % (qualified_groupby_field)
-                    qualified_groupby_field = groupby
+                groupby_type = fget[groupby]['type']
+                if groupby_type in ('date', 'datetime'):    
+                    qualified_groupby_field = "to_char(%s,'yyyy-mm')" % qualified_groupby_field
+                    flist = "%s as %s " % (qualified_groupby_field, groupby)
+                elif groupby_type == 'boolean':
+                     qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field
+                     flist = "%s as %s " % (qualified_groupby_field, groupby)
                 else:
                     flist = qualified_groupby_field
             else:
@@ -2273,7 +2297,7 @@ class orm(orm_template):
         while field in current_table._inherit_fields and not field in current_table._columns:
             parent_model_name = current_table._inherit_fields[field][0]
             parent_table = self.pool.get(parent_model_name)
-            self._inherits_join_add(parent_model_name, query)
+            current_table._inherits_join_add(parent_model_name, query)
             current_table = parent_table
         return '"%s".%s' % (current_table._table, field)
 
@@ -2787,14 +2811,17 @@ class orm(orm_template):
             f = self._columns[store_field]
             if hasattr(f, 'digits_change'):
                 f.digits_change(cr)
+            def not_this_field(stored_func):
+                x, y, z, e, f, l = stored_func
+                return x != self._name or y != store_field
+            self.pool._store_function[self._name] = filter(not_this_field, self.pool._store_function.get(self._name, []))
             if not isinstance(f, fields.function):
                 continue
             if not f.store:
                 continue
-            if self._columns[store_field].store is True:
+            sm = f.store
+            if sm is True:
                 sm = {self._name: (lambda self, cr, uid, ids, c={}: ids, None, 10, None)}
-            else:
-                sm = self._columns[store_field].store
             for object, aa in sm.items():
                 if len(aa) == 4:
                     (fnct, fields2, order, length) = aa
@@ -2805,14 +2832,8 @@ class orm(orm_template):
                     raise except_orm('Error',
                         ('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority, time length)}.' % (store_field, self._name)))
                 self.pool._store_function.setdefault(object, [])
-                ok = True
-                for x, y, z, e, f, l in self.pool._store_function[object]:
-                    if (x==self._name) and (y==store_field) and (e==fields2):
-                        if f == order:
-                            ok = False
-                if ok:
-                    self.pool._store_function[object].append( (self._name, store_field, fnct, fields2, order, length))
-                    self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
+                self.pool._store_function[object].append((self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length))
+                self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
 
         for (key, _, msg) in self._sql_constraints:
             self.pool._sql_error[self._table+'_'+key] = msg
@@ -2875,12 +2896,24 @@ class orm(orm_template):
         for table in self._inherits:
             res.update(self.pool.get(table)._inherit_fields)
             for col in self.pool.get(table)._columns.keys():
-                res[col] = (table, self._inherits[table], self.pool.get(table)._columns[col])
+                res[col] = (table, self._inherits[table], self.pool.get(table)._columns[col], table)
             for col in self.pool.get(table)._inherit_fields.keys():
-                res[col] = (table, self._inherits[table], self.pool.get(table)._inherit_fields[col][2])
+                res[col] = (table, self._inherits[table], self.pool.get(table)._inherit_fields[col][2], self.pool.get(table)._inherit_fields[col][3])
         self._inherit_fields = res
+        self._all_columns = self._get_column_infos()
         self._inherits_reload_src()
 
+    def _get_column_infos(self):
+        """Returns a dict mapping all fields names (direct fields and
+           inherited field via _inherits) to a ``column_info`` struct
+           giving detailed columns """
+        result = {}
+        for k, (parent, m2o, col, original_parent) in self._inherit_fields.iteritems():
+            result[k] = fields.column_info(k, col, parent, m2o, original_parent)
+        for k, col in self._columns.iteritems():
+            result[k] = fields.column_info(k, col)
+        return result
+
     def _inherits_check(self):
         for table, field_name in self._inherits.items():
             if field_name not in self._columns:
@@ -3572,7 +3605,7 @@ class orm(orm_template):
         upd_todo = []
         for v in vals.keys():
             if v in self._inherit_fields:
-                (table, col, col_detail) = self._inherit_fields[v]
+                (table, col, col_detail, original_parent) = self._inherit_fields[v]
                 tocreate[table][v] = vals[v]
                 del vals[v]
             else:
@@ -3593,11 +3626,16 @@ class orm(orm_template):
                 del vals[self._inherits[table]]
 
             record_id = tocreate[table].pop('id', None)
-
+            
+            # When linking/creating parent records, force context without 'no_store_function' key that
+            # defers stored functions computing, as these won't be computed in batch at the end of create(). 
+            parent_context = dict(context)
+            parent_context.pop('no_store_function', None)
+            
             if record_id is None or not record_id:
-                record_id = self.pool.get(table).create(cr, user, tocreate[table], context=context)
+                record_id = self.pool.get(table).create(cr, user, tocreate[table], context=parent_context)
             else:
-                self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=context)
+                self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=parent_context)
 
             upd0 += ',' + self._inherits[table]
             upd1 += ',%s'
@@ -3973,7 +4011,7 @@ class orm(orm_template):
                 order_direction = order_split[1].strip() if len(order_split) == 2 else ''
                 inner_clause = None
                 if order_field == 'id':
-                    order_by_clause = '"%s"."%s"' % (self._table, order_field)
+                    inner_clause = '"%s"."%s"' % (self._table, order_field)
                 elif order_field in self._columns:
                     order_column = self._columns[order_field]
                     if order_column._classic_read:
@@ -3983,7 +4021,7 @@ class orm(orm_template):
                     else:
                         continue # ignore non-readable or "non-joinable" fields
                 elif order_field in self._inherit_fields:
-                    parent_obj = self.pool.get(self._inherit_fields[order_field][0])
+                    parent_obj = self.pool.get(self._inherit_fields[order_field][3])
                     order_column = parent_obj._columns[order_field]
                     if order_column._classic_read:
                         inner_clause = self._inherits_join_calc(order_field, query)
@@ -4127,8 +4165,13 @@ class orm(orm_template):
         for parent_column in ['parent_left', 'parent_right']:
             data.pop(parent_column, None)
 
-        for v in self._inherits:
-            del data[self._inherits[v]]
+        # remove _inherits field's from data recursively, missing parents will
+        # be created by create() (so that copy() copy everything).
+        def remove_ids(inherits_dict):
+            for parent_table in inherits_dict:
+                del data[inherits_dict[parent_table]]
+                remove_ids(self.pool.get(parent_table)._inherits)
+        remove_ids(self._inherits)
         return data
 
     def copy_translations(self, cr, uid, old_id, new_id, context=None):