[MERGE] Merged Dhruti's branch for the fix of avoiding crash when reservation is...
[odoo/odoo.git] / addons / audittrail / audittrail.py
index 58d3dd8..ee6f34a 100644 (file)
@@ -1,8 +1,34 @@
 # -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+#    $Id$
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
 
-from osv import osv, fields
-import time, pooler, copy
 import ir
+from osv import fields, osv
+import netsvc
+import pooler
+import time
+from tools.translate import _
+
+
 class audittrail_rule(osv.osv):
     _name = 'audittrail.rule'
     _columns = {
@@ -29,217 +55,41 @@ class audittrail_rule(osv.osv):
     ]
     __functions = {}
 
-    def __init__(self,pool,cr=None):
-        for obj_name in pool.obj_list():
-            obj=pool.get(obj_name)
-            for field in ('read','write','create','unlink'):
-                setattr(obj, field, self.logging_fct(getattr(obj,field), obj))
-        super(audittrail_rule, self).__init__(pool,cr)
-
     def subscribe(self, cr, uid, ids, *args):
         for thisrule in self.browse(cr, uid, ids):
             obj = self.pool.get(thisrule.object_id.model)
             if not obj:
                 raise osv.except_osv(
-                        'WARNING:audittrail is not part of the pool',
-                        'Change audittrail depends -- Setting rule as DRAFT')
+                        _('WARNING:audittrail is not part of the pool'),
+                        _('Change audittrail depends -- Setting rule as DRAFT'))
                 self.write(cr, uid, [thisrule.id], {"state": "draft"})
-        val={
-             "name":'View Log',
-             "res_model":'audittrail.log',
-             "src_model":thisrule.object_id.model,
-             "domain":"[('res_id', '=', active_id)]"
-
-        }
-        id=self.pool.get('ir.actions.act_window').create(cr, uid, val)
-        self.write(cr, uid, ids, {"state": "subscribed","action_id":id})
-        keyword = 'client_action_relate'
-        value = 'ir.actions.act_window,'+str(id)
-        res=self.pool.get('ir.model.data').ir_set(cr, uid, 'action', keyword,'View_log_'+thisrule.object_id.model, [thisrule.object_id.model], value, replace=True, isobject=True, xml_id=False)
+            val={
+                 "name":'View Log',
+                 "res_model":'audittrail.log',
+                 "src_model":thisrule.object_id.model,
+                 "domain":"[('object_id','=',"+str(thisrule.object_id.id)+"),('res_id', '=', active_id)]"
+
+            }
+            id=self.pool.get('ir.actions.act_window').create(cr, uid, val)
+            self.write(cr, uid, [thisrule.id], {"state": "subscribed","action_id":id})
+            keyword = 'client_action_relate'
+            value = 'ir.actions.act_window,'+str(id)
+            res=self.pool.get('ir.model.data').ir_set(cr, uid, 'action', keyword,'View_log_'+thisrule.object_id.model, [thisrule.object_id.model], value, replace=True, isobject=True, xml_id=False)
         return True
 
-
-    def logging_fct(self, fct_src, obj):
-        object_name=obj._name
-        object=None
-        logged_uids = []
-        def get_value_text(cr, uid, field_name,values,object, context={}):
-            f_id= self.pool.get('ir.model.fields').search(cr, uid,[('name','=',field_name),('model_id','=',object.id)])
-            if f_id:
-                field=self.pool.get('ir.model.fields').read(cr, uid,f_id)[0]
-                model=field['relation']
-
-                if field['ttype']=='many2one':
-                    if values:
-                        if type(values)==tuple:
-                            values=values[0]
-                        val=self.pool.get(model).read(cr,uid,[values],['name'])
-                        if len(val):
-                            return val[0]['name']
-
-                elif field['ttype'] == 'many2many':
-                    value=[]
-                    if values:
-                        for id in values:
-                            val=self.pool.get(model).read(cr,uid,[id],['name'])
-                            if len(val):
-                                value.append(val[0]['name'])
-                    return value
-
-                elif field['ttype'] == 'one2many':
-
-                    if values:
-                        value=[]
-                        for id in values:
-                            val=self.pool.get(model).read(cr,uid,[id],['name'])
-                            if len(val):
-                                value.append(val[0]['name'])
-                        return value
-            return values
-
-        def create_log_line(cr,uid,id,object,lines=[]):
-            for line in lines:
-                f_id= self.pool.get('ir.model.fields').search(cr, uid,[('name','=',line['name']),('model_id','=',object.id)])
-                if len(f_id):
-                    fields=self.pool.get('ir.model.fields').read(cr, uid,f_id)
-                    old_value='old_value' in line and  line['old_value'] or ''
-                    new_value='new_value' in line and  line['new_value'] or ''
-                    old_value_text='old_value_text' in line and  line['old_value_text'] or ''
-                    new_value_text='new_value_text' in line and  line['new_value_text'] or ''
-
-                    if fields[0]['ttype']== 'many2one':
-                        if type(old_value)==tuple:
-                            old_value=old_value[0]
-                        if type(new_value)==tuple:
-                            new_value=new_value[0]
-                    self.pool.get('audittrail.log.line').create(cr, uid, {"log_id": id, "field_id": f_id[0] ,"old_value":old_value ,"new_value":new_value,"old_value_text":old_value_text ,"new_value_text":new_value_text,"field_description":fields[0]['field_description']})
-            return True
-
-        def my_fct( cr, uid, *args, **args2):
-            obj_ids= self.pool.get('ir.model').search(cr, uid,[('model','=',object_name)])
-            if not len(obj_ids):
-                return fct_src(cr, uid, *args, **args2)
-            object=self.pool.get('ir.model').browse(cr,uid,obj_ids)[0]
-            rule_ids=self.search(cr, uid, [('object_id','=',obj_ids[0]),('state','=','subscribed')])
-            if not len(rule_ids):
-                return fct_src(cr, uid, *args, **args2)
-
-            field=fct_src.__name__
-            for thisrule in self.browse(cr, uid, rule_ids):
-                if not getattr(thisrule, 'log_'+field):
-                    return fct_src(cr, uid, *args, **args2)
-                self.__functions.setdefault(thisrule.id, [])
-                self.__functions[thisrule.id].append( (obj,field, getattr(obj,field)) )
-                for user in thisrule.user_id:
-                    logged_uids.append(user.id)
-
-            if fct_src.__name__ in ('create'):
-                res_id =fct_src( cr, uid, *args, **args2)
-                new_value=self.pool.get(object.model).read(cr,uid,[res_id],args[0].keys())[0]
-                if 'id' in new_value:
-                    del new_value['id']
-                if not len(logged_uids) or uid in logged_uids:
-                    id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
-                    lines=[]
-                    for field in new_value:
-                        if new_value[field]:
-                            line={
-                                  'name':field,
-                                  'new_value':new_value[field],
-                                  'new_value_text':get_value_text(cr,uid,field,new_value[field],object)
-                                  }
-                            lines.append(line)
-                    create_log_line(cr,uid,id,object,lines)
-                return res_id
-
-            if fct_src.__name__ in ('write'):
-                res_ids=args[0]
-                for res_id in res_ids:
-                    old_values=self.pool.get(object.model).read(cr,uid,res_id,args[1].keys())
-                    old_values_text={}
-                    for field in args[1].keys():
-                        old_values_text[field]=get_value_text(cr,uid,field,old_values[field],object)
-                    res =fct_src( cr, uid, *args, **args2)
-                    if res:
-                        new_values=self.pool.get(object.model).read(cr,uid,res_ids,args[1].keys())[0]
-                        if not len(logged_uids) or uid in logged_uids:
-                            id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
-                            lines=[]
-                            for field in args[1].keys():
-                                if args[1].keys():
-                                    line={
-                                          'name':field,
-                                          'new_value':field in new_values and new_values[field] or '',
-                                          'old_value':field in old_values and old_values[field] or '',
-                                          'new_value_text':get_value_text(cr,uid,field,new_values[field],object),
-                                          'old_value_text':old_values_text[field]
-                                          }
-                                    lines.append(line)
-                            create_log_line(cr,uid,id,object,lines)
-                    return res
-
-            if fct_src.__name__ in ('read'):
-                res_ids=args[0]
-                old_values={}
-                res =fct_src( cr, uid,*args, **args2)
-                if type(res)==list:
-
-                    for v in res:
-                        old_values[v['id']]=v
-                else:
-
-                    old_values[res['id']]=res
-                for res_id in old_values:
-                    if not len(logged_uids) or uid in logged_uids:
-                        id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
-                        lines=[]
-                        for field in old_values[res_id]:
-                            if old_values[res_id][field]:
-                                line={
-                                          'name':field,
-                                          'old_value':old_values[res_id][field],
-                                          'old_value_text':get_value_text(cr,uid,field,old_values[res_id][field],object)
-                                          }
-                                lines.append(line)
-                    create_log_line(cr,uid,id,object,lines)
-                return res
-            if fct_src.__name__ in ('unlink'):
-                res_ids=args[0]
-                old_values={}
-                for res_id in res_ids:
-                    old_values[res_id]=self.pool.get(object.model).read(cr,uid,res_id,[])
-
-                for res_id in res_ids:
-                    if not len(logged_uids) or uid in logged_uids:
-                        id=self.pool.get('audittrail.log').create(cr, uid, {"method": fct_src.__name__, "object_id": object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (fct_src.__name__, object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
-                        lines=[]
-                        for field in old_values[res_id]:
-                            if old_values[res_id][field]:
-                                line={
-                                      'name':field,
-                                      'old_value':old_values[res_id][field],
-                                      'old_value_text':get_value_text(cr,uid,field,old_values[res_id][field],object)
-                                      }
-                                lines.append(line)
-                        create_log_line(cr,uid,id,object,lines)
-                res =fct_src( cr, uid,*args, **args2)
-                return res
-
-        return my_fct
-
     def unsubscribe(self, cr, uid, ids, *args):
         for thisrule in self.browse(cr, uid, ids):
             if thisrule.id in self.__functions :
                 for function in self.__functions[thisrule.id]:
                     setattr(function[0], function[1], function[2])
-        w_id=self.pool.get('ir.actions.act_window').search(cr, uid, [('name','=','View Log'),('res_model','=','audittrail.log'),('src_model','=',thisrule.object_id.model)])
-        self.pool.get('ir.actions.act_window').unlink(cr, uid,w_id )
-        val_obj=self.pool.get('ir.values')
-        value="ir.actions.act_window"+','+str(w_id[0])
-        val_id=val_obj.search(cr, uid, [('model','=',thisrule.object_id.model),('value','=',value)])
-        if val_id:
-            res = ir.ir_del(cr, uid, val_id[0])
-        self.write(cr, uid, ids, {"state": "draft"})
+            w_id=self.pool.get('ir.actions.act_window').search(cr, uid, [('name','=','View Log'),('res_model','=','audittrail.log'),('src_model','=',thisrule.object_id.model)])
+            self.pool.get('ir.actions.act_window').unlink(cr, uid,w_id )
+            val_obj=self.pool.get('ir.values')
+            value="ir.actions.act_window"+','+str(w_id[0])
+            val_id=val_obj.search(cr, uid, [('model','=',thisrule.object_id.model),('value','=',value)])
+            if val_id:
+                res = ir.ir_del(cr, uid, val_id[0])
+            self.write(cr, uid, [thisrule.id], {"state": "draft"})
         return True
 
 audittrail_rule()
@@ -260,9 +110,11 @@ class audittrail_log(osv.osv):
     _defaults = {
         "timestamp": lambda *a: time.strftime("%Y-%m-%d %H:%M:%S")
     }
+    _order = "timestamp desc"
 
 audittrail_log()
 
+
 class audittrail_log_line(osv.osv):
     _name='audittrail.log.line'
     _columns={
@@ -277,5 +129,229 @@ class audittrail_log_line(osv.osv):
               }
 
 audittrail_log_line()
+
+
+objects_proxy = netsvc.SERVICES['object'].__class__
+
+
+class audittrail_objects_proxy(objects_proxy):
+    def get_value_text(self, cr, uid, field_name, values, object, context=None):
+        if context is None:
+            context = {}
+
+        pool = pooler.get_pool(cr.dbname)
+        obj=pool.get(object.model)
+        object_name=obj._name
+        obj_ids= pool.get('ir.model').search(cr, uid,[('model','=',object_name)])
+        model_object=pool.get('ir.model').browse(cr,uid,obj_ids)[0]
+        f_id= pool.get('ir.model.fields').search(cr, uid,[('name','=',field_name),('model_id','=',object.id)])
+        if f_id:
+            field=pool.get('ir.model.fields').read(cr, uid,f_id)[0]
+            model=field['relation']
+
+            if field['ttype']=='many2one':
+                if values:
+                    if type(values)==tuple:
+                        values=values[0]
+                    val=pool.get(model).read(cr,uid,[values],[pool.get(model)._rec_name])
+                    if len(val):
+                        return val[0][pool.get(model)._rec_name]
+            elif field['ttype'] == 'many2many':
+                value=[]
+                if values:
+                    for id in values:
+                        val=pool.get(model).read(cr,uid,[id],[pool.get(model)._rec_name])
+                        if len(val):
+                            value.append(val[0][pool.get(model)._rec_name])
+                return value
+
+            elif field['ttype'] == 'one2many':
+
+                if values:
+                    value=[]
+                    for id in values:
+                        val=pool.get(model).read(cr,uid,[id],[pool.get(model)._rec_name])
+
+                        if len(val):
+                            value.append(val[0][pool.get(model)._rec_name])
+                    return value
+        return values
+
+    def create_log_line(self, cr, uid, id, object, lines=[]):
+        pool = pooler.get_pool(cr.dbname)
+        obj=pool.get(object.model)
+        object_name=obj._name
+        obj_ids= pool.get('ir.model').search(cr, uid,[('model','=',object_name)])
+        model_object=pool.get('ir.model').browse(cr,uid,obj_ids)[0]
+        for line in lines:
+            f_id= pool.get('ir.model.fields').search(cr, uid,[('name','=',line['name']),('model_id','=',object.id)])
+            if len(f_id):
+                fields=pool.get('ir.model.fields').read(cr, uid,f_id)
+                old_value='old_value' in line and  line['old_value'] or ''
+                new_value='new_value' in line and  line['new_value'] or ''
+                old_value_text='old_value_text' in line and  line['old_value_text'] or ''
+                new_value_text='new_value_text' in line and  line['new_value_text'] or ''
+
+                if fields[0]['ttype']== 'many2one':
+                    if type(old_value)==tuple:
+                        old_value=old_value[0]
+                    if type(new_value)==tuple:
+                        new_value=new_value[0]
+                log_line_id = pool.get('audittrail.log.line').create(cr, uid, {"log_id": id, "field_id": f_id[0] ,"old_value":old_value ,"new_value":new_value,"old_value_text":old_value_text ,"new_value_text":new_value_text,"field_description":fields[0]['field_description']})
+                cr.commit()
+        return True
+
+    def log_fct(self, db, uid, passwd, object, method, fct_src, *args):
+        logged_uids = []
+        pool = pooler.get_pool(db)
+        cr = pooler.get_db(db).cursor()
+        obj=pool.get(object)
+        object_name=obj._name
+        obj_ids= pool.get('ir.model').search(cr, uid,[('model','=',object_name)])
+        model_object=pool.get('ir.model').browse(cr,uid,obj_ids)[0]
+        if method in ('create'):
+            res_id = fct_src( db, uid, passwd, object, method, *args)
+            cr.commit()
+            new_value=pool.get(model_object.model).read(cr,uid,[res_id],args[0].keys())[0]
+            if 'id' in new_value:
+                del new_value['id']
+            if not len(logged_uids) or uid in logged_uids:
+                id=pool.get('audittrail.log').create(cr, uid, {"method": method , "object_id": model_object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (method , model_object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
+                lines=[]
+                for field in new_value:
+                    if new_value[field]:
+                        line={
+                              'name':field,
+                              'new_value':new_value[field],
+                              'new_value_text': self.get_value_text(cr,uid,field,new_value[field],model_object)
+                              }
+                        lines.append(line)
+                self.create_log_line(cr,uid,id,model_object,lines)
+            cr.commit()
+            cr.close()
+            return res_id
+
+        if method in ('write'):
+            res_ids=args[0]
+            for res_id in res_ids:
+                old_values=pool.get(model_object.model).read(cr,uid,res_id,args[1].keys())
+                old_values_text={}
+                for field in args[1].keys():
+                    old_values_text[field] = self.get_value_text(cr,uid,field,old_values[field],model_object)
+                res =fct_src( db, uid, passwd, object, method, *args)
+                cr.commit()
+                if res:
+                    new_values=pool.get(model_object.model).read(cr,uid,res_ids,args[1].keys())[0]
+                    if not len(logged_uids) or uid in logged_uids:
+                        id=pool.get('audittrail.log').create(cr, uid, {"method": method, "object_id": model_object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (method , model_object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
+                        lines=[]
+                        for field in args[1].keys():
+                            if args[1].keys():
+                                line={
+                                      'name':field,
+                                      'new_value':field in new_values and new_values[field] or '',
+                                      'old_value':field in old_values and old_values[field] or '',
+                                      'new_value_text': self.get_value_text(cr,uid,field,new_values[field],model_object),
+                                      'old_value_text':old_values_text[field]
+                                      }
+                                lines.append(line)
+                        cr.commit()
+                        self.create_log_line(cr,uid,id,model_object,lines)
+                cr.close()
+                return res
+
+        if method in ('read'):
+            res_ids=args[0]
+            old_values={}
+            res =fct_src( db, uid, passwd, object, method, *args)
+            if type(res)==list:
+
+                for v in res:
+                    old_values[v['id']]=v
+            else:
+                old_values[res['id']]=res
+            for res_id in old_values:
+                if not len(logged_uids) or uid in logged_uids:
+                    id=pool.get('audittrail.log').create(cr, uid, {"method": method , "object_id": model_object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (method , model_object.id, time.strftime("%Y-%m-%d %H:%M:%S"))})
+                    lines=[]
+                    for field in old_values[res_id]:
+                        if old_values[res_id][field]:
+                            line={
+                                      'name':field,
+                                      'old_value':old_values[res_id][field],
+                                      'old_value_text': self.get_value_text(cr,uid,field,old_values[res_id][field],model_object)
+                                      }
+                            lines.append(line)
+                cr.commit()
+                self.create_log_line(cr,uid,id,model_object,lines)
+            cr.close()
+            return res
+
+        if method in ('unlink'):
+            res_ids=args[0]
+            old_values={}
+            for res_id in res_ids:
+                old_values[res_id]=pool.get(model_object.model).read(cr,uid,res_id,[])
+
+            for res_id in res_ids:
+                if not len(logged_uids) or uid in logged_uids:
+                    id=pool.get('audittrail.log').create(cr, uid, {"method": method , "object_id": model_object.id, "user_id": uid, "res_id": res_id,"name": "%s %s %s" % (method, model_object,  time.strftime("%Y-%m-%d %H:%M:%S"))})
+                    lines=[]
+                    for field in old_values[res_id]:
+                        if old_values[res_id][field]:
+                            line={
+                                  'name':field,
+                                  'old_value':old_values[res_id][field],
+                                  'old_value_text': self.get_value_text(cr,uid,field,old_values[res_id][field],model_object)
+                                  }
+                            lines.append(line)
+                    cr.commit()
+                    self.create_log_line(cr,uid,id,model_object,lines)
+            res =fct_src( db, uid, passwd, object, method, *args)
+            cr.close()
+            return res
+        cr.close()
+
+    def execute(self, db, uid, passwd, model, method, *args):
+        pool = pooler.get_pool(db)
+        cr = pooler.get_db(db).cursor()
+        cr.autocommit(True)
+        try:
+            proxy = pool.get(model)
+            if proxy is None:
+                raise Exception('Unknown model: %r' % (model,))
+
+            logged_uids = []
+            model_name = proxy._name
+
+            fct_src = super(audittrail_objects_proxy, self).execute
+
+            field = method
+            rule = False
+            obj_ids= pool.get('ir.model').search(cr, uid,[('model','=',model_name)])
+            for obj_name in pool.obj_list():
+                if obj_name == 'audittrail.rule':
+                    rule = True
+            if not rule:
+                return fct_src(db, uid, passwd, model, method, *args)
+            if not len(obj_ids):
+                return fct_src(db, uid, passwd, model, method, *args)
+            rule_ids = pool.get('audittrail.rule').search(cr, uid, [('object_id','=',obj_ids[0]),('state','=','subscribed')])
+            if not len(rule_ids):
+                return fct_src(db, uid, passwd, model, method, *args)
+
+            for thisrule in pool.get('audittrail.rule').browse(cr, uid, rule_ids):
+                for user in thisrule.user_id:
+                    logged_uids.append(user.id)
+                if not len(logged_uids) or uid in logged_uids:
+                    if field in ('read','write','create','unlink'):
+                        if getattr(thisrule, 'log_'+field):
+                            return self.log_fct(db, uid, passwd, model, method, fct_src, *args)
+                return fct_src(db, uid, passwd, model, method, *args)
+        finally:
+            cr.close()
+
+audittrail_objects_proxy()
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: