From 07881a0c50b00635f5becbb7c0c3b416f34e1263 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Fri, 2 Sep 2011 17:18:53 +0530 Subject: [PATCH 001/134] [REF]:execute method in audittrail_objects_proxy bzr revid: nch@tinyerp.com-20110902114853-z7f1uofjgh8poq0z --- addons/audittrail/audittrail.py | 39 +++++++++++++-------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index bfa6bca8f34..ffb44502ba4 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -292,7 +292,7 @@ class audittrail_objects_proxy(object_proxy): def log_fct(self, db, uid, model, method, fct_src, *args): """ - Logging function: This function is performs logging oprations according to method + Logging function: This function is performs logging operations according to method @param db: the current database @param uid: the current user’s ID for security checks, @param object: Object who's values are being changed @@ -482,41 +482,32 @@ class audittrail_objects_proxy(object_proxy): cr = pooler.get_db(db).cursor() cr.autocommit(True) logged_uids = [] + rule = False + ignore_methods = ['default_get','read','fields_view_get','fields_get','search', + 'search_count','name_search','name_get','get','request_get', + 'get_sc', 'unlink', 'write', 'create'] fct_src = super(audittrail_objects_proxy, self).execute - - def my_fct(db, uid, model, method, *args): - rule = False + try: model_ids = model_pool.search(cr, uid, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False - - for model_name in pool.obj_list(): - if model_name == 'audittrail.rule': - rule = True - if not rule: - return fct_src(db, uid_orig, model, method, *args) - if not model_id: - return fct_src(db, uid_orig, model, method, *args) - + if 'audittrail.rule' in pool.obj_list(): + rule = True + if not rule or not model_id: + return fct_src(db, uid_orig, model, method, *args) rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) if not rule_ids: return fct_src(db, uid_orig, model, method, *args) - for thisrule in rule_pool.browse(cr, uid, rule_ids): - for user in thisrule.user_id: - logged_uids.append(user.id) + for model_rule in rule_pool.browse(cr, uid, rule_ids): + logged_uids += map(lambda x:x.id, model_rule.user_id) if not logged_uids or uid in logged_uids: if method in ('read', 'write', 'create', 'unlink'): - if getattr(thisrule, 'log_' + method): + if getattr(model_rule, 'log_' + method): return self.log_fct(db, uid_orig, model, method, fct_src, *args) - - elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'): - if thisrule.log_action: + elif method not in ignore_methods: + if model_rule.log_action: return self.log_fct(db, uid_orig, model, method, fct_src, *args) - return fct_src(db, uid_orig, model, method, *args) - try: - res = my_fct(db, uid, model, method, *args) - return res finally: cr.close() From 2fef7cd890150c20b4cb9835d601263de1ba5632 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Mon, 5 Sep 2011 14:39:26 +0530 Subject: [PATCH 002/134] [IMP]:refactored with speed improvement:get_value_text method bzr revid: nch@tinyerp.com-20110905090926-jjklwr3p12sbjzl2 --- addons/audittrail/audittrail.py | 50 +++++++++++---------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index ffb44502ba4..0780679f49c 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -203,37 +203,22 @@ class audittrail_objects_proxy(object_proxy): if field_name in('__last_update','id'): return values pool = pooler.get_pool(cr.dbname) - field_pool = pool.get('ir.model.fields') - model_pool = pool.get('ir.model') obj_pool = pool.get(model.model) - if obj_pool._inherits: - inherits_ids = model_pool.search(cr, uid, [('model', '=', obj_pool._inherits.keys()[0])]) - field_ids = field_pool.search(cr, uid, [('name', '=', field_name), ('model_id', 'in', (model.id, inherits_ids[0]))]) - else: - field_ids = field_pool.search(cr, uid, [('name', '=', field_name), ('model_id', '=', model.id)]) - field_id = field_ids and field_ids[0] or False - assert field_id, _("'%s' field does not exist in '%s' model" %(field_name, model.model)) - - field = field_pool.read(cr, uid, field_id) - relation_model = field['relation'] - relation_model_pool = relation_model and pool.get(relation_model) or False - - if field['ttype'] == 'many2one': - res = False - relation_id = False - if values and type(values) == tuple: - relation_id = values[0] - if relation_id and relation_model_pool: - relation_model_object = relation_model_pool.read(cr, uid, relation_id, [relation_model_pool._rec_name]) - res = relation_model_object[relation_model_pool._rec_name] - return res - - elif field['ttype'] in ('many2many','one2many'): - res = [] - for relation_model_object in relation_model_pool.read(cr, uid, values, [relation_model_pool._rec_name]): - res.append(relation_model_object[relation_model_pool._rec_name]) - return res - + field_obj = obj_pool._all_columns.get(field_name, False) + assert field_obj, _("'%s' field does not exist in '%s' model" %(field_name, model.model)) + field_obj = field_obj.column + if field_obj._obj: + relation_model_pool = pool.get(field_obj._obj) + relational_rec_name = relation_model_pool._rec_name + if field_obj._type == 'many2one': + if values and isinstance(values, tuple): + if values[0]: + relation_model_object = relation_model_pool.read(cr, uid, values[0], [relational_rec_name]) + return relation_model_object.get(relational_rec_name) + return False + elif field_obj._type in ('many2many','one2many'): + data = relation_model_pool.read(cr, uid, values, [relational_rec_name]) + return map(lambda x:x.get(relational_rec_name, False), data) return values def create_log_line(self, cr, uid, log_id, model, lines=[]): @@ -482,7 +467,6 @@ class audittrail_objects_proxy(object_proxy): cr = pooler.get_db(db).cursor() cr.autocommit(True) logged_uids = [] - rule = False ignore_methods = ['default_get','read','fields_view_get','fields_get','search', 'search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'] @@ -490,9 +474,7 @@ class audittrail_objects_proxy(object_proxy): try: model_ids = model_pool.search(cr, uid, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False - if 'audittrail.rule' in pool.obj_list(): - rule = True - if not rule or not model_id: + if not ('audittrail.rule' in pool.obj_list()) or not model_id: return fct_src(db, uid_orig, model, method, *args) rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) if not rule_ids: From 9ebdf040f574d1da0697435fdc4acae864085aec Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Mon, 5 Sep 2011 15:08:41 +0530 Subject: [PATCH 003/134] [IMP]:refactored create_log_line method bzr revid: nch@tinyerp.com-20110905093841-uk7nke7e36gsf4ig --- addons/audittrail/audittrail.py | 39 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 0780679f49c..99382797d72 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -235,43 +235,36 @@ class audittrail_objects_proxy(object_proxy): model_pool = pool.get('ir.model') field_pool = pool.get('ir.model.fields') log_line_pool = pool.get('audittrail.log.line') - #start Loop for line in lines: - if line['name'] in('__last_update','id'): + if line['name'] in ('__last_update','id'): continue + field_obj = obj_pool._all_columns.get(line['name'], False) + assert field_obj, _("'%s' field does not exist in '%s' model" %(line['name'], model.model)) + field_obj = field_obj.column + old_value = line.get('old_value', '') + new_value = line.get('new_value', '') + old_value_text = line.get('old_value_text', '') + new_value_text = line.get('new_value_text', '') + search_models = [ model.id ] if obj_pool._inherits: - inherits_ids = model_pool.search(cr, uid, [('model', '=', obj_pool._inherits.keys()[0])]) - field_ids = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', (model.id, inherits_ids[0]))]) - else: - field_ids = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', '=', model.id)]) - field_id = field_ids and field_ids[0] or False - assert field_id, _("'%s' field does not exist in '%s' model" %(line['name'], model.model)) - - field = field_pool.read(cr, uid, field_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 '' - + search_models += model_pool.search(cr, uid, [('model', 'in', obj_pool._inherits.keys())]) + field_id = field_pool.search(cr, uid, [('name', '=', line['name']), ('model_id', 'in', search_models)]) if old_value_text == new_value_text: continue - if field['ttype'] == 'many2one': - if type(old_value) == tuple: - old_value = old_value[0] - if type(new_value) == tuple: - new_value = new_value[0] + if field_obj._type == 'many2one': + old_value = isinstance(old_value, tuple) and old_value[0] or old_value + new_value = isinstance(new_value, tuple) and new_value[0] or new_value vals = { "log_id": log_id, - "field_id": field_id, + "field_id": field_id and field_id[0] or False, "old_value": old_value, "new_value": new_value, "old_value_text": old_value_text, "new_value_text": new_value_text, - "field_description": field['field_description'] + "field_description": field_obj.string } line_id = log_line_pool.create(cr, uid, vals) cr.commit() - #End Loop return True From 2a828b8f5e86ce16bce6a114a34a8f893bed7c6e Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Mon, 5 Sep 2011 17:38:46 +0530 Subject: [PATCH 004/134] [IMP]:refactored log_fct to include create for o2m, m2m method bzr revid: nch@tinyerp.com-20110905120846-sletd1fvcfloqdxy --- addons/audittrail/audittrail.py | 55 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 99382797d72..841eda00d29 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -292,31 +292,38 @@ class audittrail_objects_proxy(object_proxy): model_id = model_ids and model_ids[0] or False assert model_id, _("'%s' Model does not exist..." %(model)) model = model_pool.browse(cr, uid, model_id) - + relational_table_log = args and args[-1] == 'child_relation_log' or False if method in ('create'): - res_id = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() - resource = resource_pool.read(cr, uid, res_id, args[0].keys()) - vals = { - "method": method, - "object_id": model.id, - "user_id": uid_orig, - "res_id": resource['id'], - } - if 'id' in resource: - del resource['id'] - log_id = log_pool.create(cr, uid, vals) - lines = [] - for field in resource: - line = { - 'name': field, - 'new_value': resource[field], - 'new_value_text': self.get_value_text(cr, uid, field, resource[field], model) - } - lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) - - cr.commit() + fields_to_read = [] + if relational_table_log: + res_id = args[0] + else: + res_id = fct_src(db, uid_orig, model.model, method, *args) + cr.commit() + fields_to_read = args[0].keys() + resource = resource_pool.read(cr, uid, res_id, fields_to_read) + if not isinstance(resource, list): + resource = [resource] + vals = { 'method': method, 'object_id': model.id,'user_id': uid_orig} + for resource_data in resource: + vals.update({'res_id': resource_data['id']}) + if 'id' in resource_data: + del resource_data['id'] + log_id = log_pool.create(cr, uid, vals) + lines = [] + for field in resource_data: + field_obj = resource_pool._all_columns.get(field, False) + field_obj = field_obj.column + if field_obj._type in ('one2many','many2many'): + self.log_fct(db, uid, field_obj._obj, method, None, resource_data[field], 'child_relation_log') + line = { + 'name': field, + 'new_value': resource_data[field], + 'new_value_text': self.get_value_text(cr, uid, field, resource_data[field], model) + } + lines.append(line) + self.create_log_line(cr, uid, log_id, model, lines) + cr.commit() cr.close() return res_id From 43ff15c84d7f6f674e0201a2674b2a5a4e3c7082 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 11:01:24 +0530 Subject: [PATCH 005/134] [IMP]:get_value_text to use name_get for x2m and simply return [1] arg for m2o tuple bzr revid: nch@tinyerp.com-20110906053124-a3kw3j2g3weln60q --- addons/audittrail/audittrail.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 841eda00d29..1d42000488d 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -204,21 +204,19 @@ class audittrail_objects_proxy(object_proxy): return values pool = pooler.get_pool(cr.dbname) obj_pool = pool.get(model.model) - field_obj = obj_pool._all_columns.get(field_name, False) + field_obj = obj_pool._all_columns.get(field_name) assert field_obj, _("'%s' field does not exist in '%s' model" %(field_name, model.model)) field_obj = field_obj.column if field_obj._obj: relation_model_pool = pool.get(field_obj._obj) relational_rec_name = relation_model_pool._rec_name if field_obj._type == 'many2one': - if values and isinstance(values, tuple): - if values[0]: - relation_model_object = relation_model_pool.read(cr, uid, values[0], [relational_rec_name]) - return relation_model_object.get(relational_rec_name) - return False + if values: + return values[1] + return values elif field_obj._type in ('many2many','one2many'): - data = relation_model_pool.read(cr, uid, values, [relational_rec_name]) - return map(lambda x:x.get(relational_rec_name, False), data) + data = relation_model_pool.name_get(cr, uid, values) + return map(lambda x:x[1], data) return values def create_log_line(self, cr, uid, log_id, model, lines=[]): @@ -312,7 +310,7 @@ class audittrail_objects_proxy(object_proxy): log_id = log_pool.create(cr, uid, vals) lines = [] for field in resource_data: - field_obj = resource_pool._all_columns.get(field, False) + field_obj = resource_pool._all_columns.get(field) field_obj = field_obj.column if field_obj._type in ('one2many','many2many'): self.log_fct(db, uid, field_obj._obj, method, None, resource_data[field], 'child_relation_log') From 1947eed2df667bfd59b7c42306e19ab390170e96 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 11:24:31 +0530 Subject: [PATCH 006/134] [IMP]:support for x2m log unlink bzr revid: nch@tinyerp.com-20110906055431-a87bvbm0o7p1hts5 --- addons/audittrail/audittrail.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 1d42000488d..3f4417a15bb 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -359,33 +359,31 @@ class audittrail_objects_proxy(object_proxy): elif method in ('unlink'): res_ids = args[0] + res = False old_values = {} for res_id in res_ids: old_values[res_id] = resource_pool.read(cr, uid, res_id) - + vals = {'method': method,'object_id': model.id,'user_id': uid_orig} for res_id in res_ids: - vals = { - "method": method, - "object_id": model.id, - "user_id": uid_orig, - "res_id": res_id, - - } + vals.update({'res_id': res_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in old_values[res_id]: - if field in ('id'): - continue + if field == 'id': continue + field_obj = resource_pool._all_columns.get(field) + field_obj = field_obj.column + if field_obj._type in ('one2many','many2many'): + self.log_fct(db, uid, field_obj._obj, method, None, old_values[res_id][field], 'child_relation_log') 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) } lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) - res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + if not relational_table_log: + res = fct_src(db, uid_orig, model.model, method, *args) + cr.commit() cr.close() return res else: From d213821ea0dc2b000f95df025be8f45cefa63330 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 11:52:41 +0530 Subject: [PATCH 007/134] [IMP]:x2m logging when there is any action execute like on_change,copy etc bzr revid: nch@tinyerp.com-20110906062241-373t8wqelc9jsyk9 --- addons/audittrail/audittrail.py | 46 +++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 3f4417a15bb..ed4fc5a551d 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -236,7 +236,7 @@ class audittrail_objects_proxy(object_proxy): for line in lines: if line['name'] in ('__last_update','id'): continue - field_obj = obj_pool._all_columns.get(line['name'], False) + field_obj = obj_pool._all_columns.get(line['name']) assert field_obj, _("'%s' field does not exist in '%s' model" %(line['name'], model.model)) field_obj = field_obj.column old_value = line.get('old_value', '') @@ -250,8 +250,8 @@ class audittrail_objects_proxy(object_proxy): if old_value_text == new_value_text: continue if field_obj._type == 'many2one': - old_value = isinstance(old_value, tuple) and old_value[0] or old_value - new_value = isinstance(new_value, tuple) and new_value[0] or new_value + old_value = old_value[0] + new_value = new_value[0] vals = { "log_id": log_id, "field_id": field_id and field_id[0] or False, @@ -305,8 +305,7 @@ class audittrail_objects_proxy(object_proxy): vals = { 'method': method, 'object_id': model.id,'user_id': uid_orig} for resource_data in resource: vals.update({'res_id': resource_data['id']}) - if 'id' in resource_data: - del resource_data['id'] + del resource_data['id'] log_id = log_pool.create(cr, uid, vals) lines = [] for field in resource_data: @@ -393,38 +392,36 @@ class audittrail_objects_proxy(object_proxy): res_ids = args[0] old_values = {} fields = [] - if len(args)>1 and type(args[1]) == dict: + if len(args) > 1 and isinstance(args[1], dict): fields = args[1].keys() - if type(res_ids) in (long, int): + if isinstance(res_ids, (long, int)): res_ids = [res_ids] if res_ids: - for resource in resource_pool.read(cr, uid, res_ids): + resource_data = resource_pool.read(cr, uid, res_ids) + for resource in resource_data: resource_id = resource['id'] - if 'id' in resource: - del resource['id'] + del resource['id'] old_values_text = {} old_value = {} for field in resource.keys(): + field_obj = resource_pool._all_columns.get(field) + field_obj = field_obj.column + if field_obj._type in ('one2many','many2many'): + self.log_fct(db, uid, field_obj._obj, method, None, resource[field], 'child_relation_log') old_value[field] = resource[field] old_values_text[field] = self.get_value_text(cr, uid, field, resource[field], model) old_values[resource_id] = {'text':old_values_text, 'value': old_value} - - res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + if not relational_table_log: + res = fct_src(db, uid_orig, model.model, method, *args) + cr.commit() if res_ids: - for resource in resource_pool.read(cr, uid, res_ids): + resource_data = resource_pool.read(cr, uid, res_ids) + vals = {'method': method,'object_id': model.id,'user_id': uid_orig } + for resource in resource_data: resource_id = resource['id'] - if 'id' in resource: - del resource['id'] - vals = { - "method": method, - "object_id": model.id, - "user_id": uid_orig, - "res_id": resource_id, - } - - + del resource['id'] + vals.update({'res_id': resource_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in resource.keys(): @@ -436,7 +433,6 @@ class audittrail_objects_proxy(object_proxy): 'old_value_text': old_values[resource_id]['text'][field] } lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) cr.commit() cr.close() From c70d21b6227dac93a0765e80f80a80a3718c532e Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 12:24:16 +0530 Subject: [PATCH 008/134] [IMP]:refactored: removed code duplication bzr revid: nch@tinyerp.com-20110906065416-33abo0zg1e6n55v5 --- addons/audittrail/audittrail.py | 85 +++++++++++---------------------- 1 file changed, 28 insertions(+), 57 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index ed4fc5a551d..4fd99d7bba3 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -250,8 +250,8 @@ class audittrail_objects_proxy(object_proxy): if old_value_text == new_value_text: continue if field_obj._type == 'many2one': - old_value = old_value[0] - new_value = new_value[0] + old_value = old_value and old_value[0] or old_value + new_value = new_value and new_value[0] or new_value vals = { "log_id": log_id, "field_id": field_id and field_id[0] or False, @@ -439,90 +439,61 @@ class audittrail_objects_proxy(object_proxy): return res return True - - - def execute(self, db, uid, model, method, *args, **kw): + def audit_log_call(self, db, uid, model, method, action_type, *args, **argv): """ Overrides Object Proxy execute method @param db: the current database @param uid: the current user's ID for security checks, @param object: Object who's values are being changed @param method: get any method and create log - + @param action_type: either 'execute' or 'workflow' @return: Returns result as per method of Object proxy """ uid_orig = uid uid = 1 pool = pooler.get_pool(db) + logged_uids = [] model_pool = pool.get('ir.model') rule_pool = pool.get('audittrail.rule') cr = pooler.get_db(db).cursor() cr.autocommit(True) - logged_uids = [] - ignore_methods = ['default_get','read','fields_view_get','fields_get','search', - 'search_count','name_search','name_get','get','request_get', - 'get_sc', 'unlink', 'write', 'create'] - fct_src = super(audittrail_objects_proxy, self).execute + if action_type == 'execute': + ignore_methods = ['default_get','read','fields_view_get','fields_get','search', + 'search_count','name_search','name_get','get','request_get', + 'get_sc', 'unlink', 'write', 'create'] + fct_src = super(audittrail_objects_proxy, self).execute + else: + fct_src = super(audittrail_objects_proxy, self).exec_workflow try: model_ids = model_pool.search(cr, uid, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False if not ('audittrail.rule' in pool.obj_list()) or not model_id: - return fct_src(db, uid_orig, model, method, *args) + return fct_src(db, uid_orig, model, method, *args, **argv) rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) if not rule_ids: - return fct_src(db, uid_orig, model, method, *args) - + return fct_src(db, uid_orig, model, method, *args, **argv) for model_rule in rule_pool.browse(cr, uid, rule_ids): logged_uids += map(lambda x:x.id, model_rule.user_id) if not logged_uids or uid in logged_uids: - if method in ('read', 'write', 'create', 'unlink'): - if getattr(model_rule, 'log_' + method): + if action_type == 'execute': + if method in ('read', 'write', 'create', 'unlink'): + if getattr(model_rule, 'log_' + method): + return self.log_fct(db, uid_orig, model, method, fct_src, *args) + elif method not in ignore_methods: + if model_rule.log_action: + return self.log_fct(db, uid_orig, model, method, fct_src, *args) + else: + if model_rule.log_workflow: return self.log_fct(db, uid_orig, model, method, fct_src, *args) - elif method not in ignore_methods: - if model_rule.log_action: - return self.log_fct(db, uid_orig, model, method, fct_src, *args) - return fct_src(db, uid_orig, model, method, *args) + return fct_src(db, uid_orig, model, method, *args, **argv) finally: cr.close() + def execute(self, db, uid, model, method, *args, **argv): + return self.audit_log_call(db, uid, model, method, 'execute', *args, **argv) + def exec_workflow(self, db, uid, model, method, *args, **argv): - uid_orig = uid - uid = 1 - - pool = pooler.get_pool(db) - logged_uids = [] - fct_src = super(audittrail_objects_proxy, self).exec_workflow - field = method - rule = False - model_pool = pool.get('ir.model') - rule_pool = pool.get('audittrail.rule') - cr = pooler.get_db(db).cursor() - cr.autocommit(True) - try: - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) - for obj_name in pool.obj_list(): - if obj_name == 'audittrail.rule': - rule = True - if not rule: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - if not model_ids: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - rule_ids = rule_pool.search(cr, uid, [('object_id', 'in', model_ids), ('state', '=', 'subscribed')]) - if not rule_ids: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - for thisrule in rule_pool.browse(cr, uid, rule_ids): - for user in thisrule.user_id: - logged_uids.append(user.id) - if not logged_uids or uid in logged_uids: - if thisrule.log_workflow: - return self.log_fct(db, uid_orig, model, method, fct_src, *args) - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - return True - finally: - cr.close() + return self.audit_log_call(db, uid, model, method, 'workflow', *args, **argv) audittrail_objects_proxy() From b8596288a8c793c7e1b176d570f291668ab22a1a Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 15:04:53 +0530 Subject: [PATCH 009/134] [IMP]:removedget_value_text to refactore the code..more improvements coming bzr revid: nch@tinyerp.com-20110906093453-c6z7wj8178w6o75g --- addons/audittrail/audittrail.py | 112 +++++++++++++++----------------- 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 4fd99d7bba3..41205982101 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -187,38 +187,6 @@ audittrail_log_line() class audittrail_objects_proxy(object_proxy): """ Uses Object proxy for auditing changes on object of subscribed Rules""" - def get_value_text(self, cr, uid, field_name, values, model, context=None): - """ - Gets textual values for the fields - e.g.: For field of type many2one it gives its name value instead of id - - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param field_name: List of fields for text values - @param values: Values for field to be converted into textual values - @return: values: List of textual values for given fields - """ - if not context: - context = {} - if field_name in('__last_update','id'): - return values - pool = pooler.get_pool(cr.dbname) - obj_pool = pool.get(model.model) - field_obj = obj_pool._all_columns.get(field_name) - assert field_obj, _("'%s' field does not exist in '%s' model" %(field_name, model.model)) - field_obj = field_obj.column - if field_obj._obj: - relation_model_pool = pool.get(field_obj._obj) - relational_rec_name = relation_model_pool._rec_name - if field_obj._type == 'many2one': - if values: - return values[1] - return values - elif field_obj._type in ('many2many','one2many'): - data = relation_model_pool.name_get(cr, uid, values) - return map(lambda x:x[1], data) - return values - def create_log_line(self, cr, uid, log_id, model, lines=[]): """ Creates lines for changed fields with its old and new values @@ -234,8 +202,6 @@ class audittrail_objects_proxy(object_proxy): field_pool = pool.get('ir.model.fields') log_line_pool = pool.get('audittrail.log.line') for line in lines: - if line['name'] in ('__last_update','id'): - continue field_obj = obj_pool._all_columns.get(line['name']) assert field_obj, _("'%s' field does not exist in '%s' model" %(line['name'], model.model)) field_obj = field_obj.column @@ -279,7 +245,6 @@ class audittrail_objects_proxy(object_proxy): """ uid_orig = uid uid = 1 - res2 = args pool = pooler.get_pool(db) cr = pooler.get_db(db).cursor() resource_pool = pool.get(model) @@ -303,6 +268,7 @@ class audittrail_objects_proxy(object_proxy): if not isinstance(resource, list): resource = [resource] vals = { 'method': method, 'object_id': model.id,'user_id': uid_orig} + new_value_text = '' for resource_data in resource: vals.update({'res_id': resource_data['id']}) del resource_data['id'] @@ -311,12 +277,18 @@ class audittrail_objects_proxy(object_proxy): for field in resource_data: field_obj = resource_pool._all_columns.get(field) field_obj = field_obj.column + new_value_text = resource_data[field] + if field in ('__last_update', 'id'):continue if field_obj._type in ('one2many','many2many'): self.log_fct(db, uid, field_obj._obj, method, None, resource_data[field], 'child_relation_log') + data = pool.get(field_obj._obj).name_get(cr, uid, resource_data[field]) + new_value_text = map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + new_value_text = resource_data[field] and resource_data[field][1] or resource_data[field] line = { 'name': field, 'new_value': resource_data[field], - 'new_value_text': self.get_value_text(cr, uid, field, resource_data[field], model) + 'new_value_text': new_value_text } lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) @@ -328,29 +300,29 @@ class audittrail_objects_proxy(object_proxy): res_ids = args[0] old_values = {} res = fct_src(db, uid_orig, model.model, method, *args) - if type(res) == list: - for v in res: - old_values[v['id']] = v - else: - old_values[res['id']] = res + map(lambda x:old_values.setdefault(x['id'], x), res) + vals = {'method': method,'object_id': model.id,'user_id': uid_orig} + old_value_text = '' for res_id in old_values: - vals = { - "method": method, - "object_id": model.id, - "user_id": uid_orig, - "res_id": res_id, - - } + vals.update({'res_id': res_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in old_values[res_id]: + if field in ('__last_update', 'id'):continue + field_obj = resource_pool._all_columns.get(field) + field_obj = field_obj.column + old_value_text = old_values[res_id][field] + if field_obj._type in ('one2many','many2many'): + data = pool.get(field_obj._obj).name_get(cr, uid, old_values[res_id][field]) + old_value_text = map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + old_value_text = old_values[res_id][field] and old_values[res_id][field][1] or 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) - } + 'name': field, + 'old_value': old_values[res_id][field], + 'old_value_text': old_value_text + } lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) cr.commit() cr.close() @@ -363,20 +335,26 @@ class audittrail_objects_proxy(object_proxy): for res_id in res_ids: old_values[res_id] = resource_pool.read(cr, uid, res_id) vals = {'method': method,'object_id': model.id,'user_id': uid_orig} + old_value_text = '' for res_id in res_ids: vals.update({'res_id': res_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in old_values[res_id]: - if field == 'id': continue + if field in ('__last_update', 'id'):continue field_obj = resource_pool._all_columns.get(field) field_obj = field_obj.column + old_value_text = old_values[res_id][field] if field_obj._type in ('one2many','many2many'): self.log_fct(db, uid, field_obj._obj, method, None, old_values[res_id][field], 'child_relation_log') + data = pool.get(field_obj._obj).name_get(cr, uid, old_values[res_id][field]) + old_value_text = map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + old_value_text = old_values[res_id][field] and old_values[res_id][field][1] or 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) + 'old_value_text': old_value_text } lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) @@ -398,26 +376,33 @@ class audittrail_objects_proxy(object_proxy): res_ids = [res_ids] if res_ids: resource_data = resource_pool.read(cr, uid, res_ids) + old_text = '' for resource in resource_data: resource_id = resource['id'] del resource['id'] old_values_text = {} old_value = {} for field in resource.keys(): + if field in ('__last_update', 'id'):continue field_obj = resource_pool._all_columns.get(field) field_obj = field_obj.column + old_text = resource[field] if field_obj._type in ('one2many','many2many'): - self.log_fct(db, uid, field_obj._obj, method, None, resource[field], 'child_relation_log') + self.log_fct(db, uid, field_obj._obj, method, None, resource[field], 'child_relation_log') + data = pool.get(field_obj._obj).name_get(cr, uid, resource[field]) + old_text = map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + old_text = resource[field] and resource[field][1] or resource[field] old_value[field] = resource[field] - old_values_text[field] = self.get_value_text(cr, uid, field, resource[field], model) + old_values_text[field] = old_text old_values[resource_id] = {'text':old_values_text, 'value': old_value} if not relational_table_log: res = fct_src(db, uid_orig, model.model, method, *args) cr.commit() - if res_ids: resource_data = resource_pool.read(cr, uid, res_ids) vals = {'method': method,'object_id': model.id,'user_id': uid_orig } + old_value_text = '' for resource in resource_data: resource_id = resource['id'] del resource['id'] @@ -425,11 +410,20 @@ class audittrail_objects_proxy(object_proxy): log_id = log_pool.create(cr, uid, vals) lines = [] for field in resource.keys(): + if field in ('__last_update', 'id'):continue + field_obj = resource_pool._all_columns.get(field) + field_obj = field_obj.column + old_value_text = resource[field] + if field_obj._type in ('one2many','many2many'): + data = pool.get(field_obj._obj).name_get(cr, uid, resource[field]) + old_value_text = map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + old_value_text = resource[field] and resource[field][1] or resource[field] line = { 'name': field, 'new_value': resource[field], 'old_value': old_values[resource_id]['value'][field], - 'new_value_text': self.get_value_text(cr, uid, field, resource[field], model), + 'new_value_text': old_value_text, 'old_value_text': old_values[resource_id]['text'][field] } lines.append(line) From dbd40832d51837844fbf0a94e842c41defbc56dc Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 16:19:49 +0530 Subject: [PATCH 010/134] [REF]:more refactoring bzr revid: nch@tinyerp.com-20110906104949-i6uxzcdden0pq71a --- addons/audittrail/audittrail.py | 75 +++++++++------------------------ 1 file changed, 21 insertions(+), 54 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 41205982101..625d4d46072 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -231,7 +231,17 @@ class audittrail_objects_proxy(object_proxy): cr.commit() return True - + def get_x2m_m2o_values(self, cr, db, uid, pool, resource_pool, method, field, value, recursive=True): + field_obj = (resource_pool._all_columns.get(field)).column + if field_obj._type in ('one2many','many2many'): + if recursive: + self.log_fct(db, uid, field_obj._obj, method, None, value, 'child_relation_log') + data = pool.get(field_obj._obj).name_get(cr, uid, value) + return map(lambda x:x[1], data) + elif field_obj._type == 'many2one': + return value and value[1] or value + return False + def log_fct(self, db, uid, model, method, fct_src, *args): """ Logging function: This function is performs logging operations according to method @@ -268,27 +278,18 @@ class audittrail_objects_proxy(object_proxy): if not isinstance(resource, list): resource = [resource] vals = { 'method': method, 'object_id': model.id,'user_id': uid_orig} - new_value_text = '' for resource_data in resource: vals.update({'res_id': resource_data['id']}) del resource_data['id'] log_id = log_pool.create(cr, uid, vals) lines = [] for field in resource_data: - field_obj = resource_pool._all_columns.get(field) - field_obj = field_obj.column - new_value_text = resource_data[field] if field in ('__last_update', 'id'):continue - if field_obj._type in ('one2many','many2many'): - self.log_fct(db, uid, field_obj._obj, method, None, resource_data[field], 'child_relation_log') - data = pool.get(field_obj._obj).name_get(cr, uid, resource_data[field]) - new_value_text = map(lambda x:x[1], data) - elif field_obj._type == 'many2one': - new_value_text = resource_data[field] and resource_data[field][1] or resource_data[field] + ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource_data[field]) line = { 'name': field, 'new_value': resource_data[field], - 'new_value_text': new_value_text + 'new_value_text': ret_val and ret_val or resource_data[field] } lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) @@ -302,25 +303,17 @@ class audittrail_objects_proxy(object_proxy): res = fct_src(db, uid_orig, model.model, method, *args) map(lambda x:old_values.setdefault(x['id'], x), res) vals = {'method': method,'object_id': model.id,'user_id': uid_orig} - old_value_text = '' for res_id in old_values: vals.update({'res_id': res_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in old_values[res_id]: if field in ('__last_update', 'id'):continue - field_obj = resource_pool._all_columns.get(field) - field_obj = field_obj.column - old_value_text = old_values[res_id][field] - if field_obj._type in ('one2many','many2many'): - data = pool.get(field_obj._obj).name_get(cr, uid, old_values[res_id][field]) - old_value_text = map(lambda x:x[1], data) - elif field_obj._type == 'many2one': - old_value_text = old_values[res_id][field] and old_values[res_id][field][1] or old_values[res_id][field] + ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, old_values[res_id][field], False) line = { 'name': field, 'old_value': old_values[res_id][field], - 'old_value_text': old_value_text + 'old_value_text': ret_val and ret_val or old_values[res_id][field] } lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) @@ -335,26 +328,17 @@ class audittrail_objects_proxy(object_proxy): for res_id in res_ids: old_values[res_id] = resource_pool.read(cr, uid, res_id) vals = {'method': method,'object_id': model.id,'user_id': uid_orig} - old_value_text = '' for res_id in res_ids: vals.update({'res_id': res_id}) log_id = log_pool.create(cr, uid, vals) lines = [] for field in old_values[res_id]: if field in ('__last_update', 'id'):continue - field_obj = resource_pool._all_columns.get(field) - field_obj = field_obj.column - old_value_text = old_values[res_id][field] - if field_obj._type in ('one2many','many2many'): - self.log_fct(db, uid, field_obj._obj, method, None, old_values[res_id][field], 'child_relation_log') - data = pool.get(field_obj._obj).name_get(cr, uid, old_values[res_id][field]) - old_value_text = map(lambda x:x[1], data) - elif field_obj._type == 'many2one': - old_value_text = old_values[res_id][field] and old_values[res_id][field][1] or old_values[res_id][field] + ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, old_values[res_id][field]) line = { 'name': field, 'old_value': old_values[res_id][field], - 'old_value_text': old_value_text + 'old_value_text': ret_val and ret_val or old_values[res_id][field] } lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) @@ -376,7 +360,6 @@ class audittrail_objects_proxy(object_proxy): res_ids = [res_ids] if res_ids: resource_data = resource_pool.read(cr, uid, res_ids) - old_text = '' for resource in resource_data: resource_id = resource['id'] del resource['id'] @@ -384,17 +367,9 @@ class audittrail_objects_proxy(object_proxy): old_value = {} for field in resource.keys(): if field in ('__last_update', 'id'):continue - field_obj = resource_pool._all_columns.get(field) - field_obj = field_obj.column - old_text = resource[field] - if field_obj._type in ('one2many','many2many'): - self.log_fct(db, uid, field_obj._obj, method, None, resource[field], 'child_relation_log') - data = pool.get(field_obj._obj).name_get(cr, uid, resource[field]) - old_text = map(lambda x:x[1], data) - elif field_obj._type == 'many2one': - old_text = resource[field] and resource[field][1] or resource[field] + ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource[field]) old_value[field] = resource[field] - old_values_text[field] = old_text + old_values_text[field] = ret_val and ret_val or resource[field] old_values[resource_id] = {'text':old_values_text, 'value': old_value} if not relational_table_log: res = fct_src(db, uid_orig, model.model, method, *args) @@ -402,7 +377,6 @@ class audittrail_objects_proxy(object_proxy): if res_ids: resource_data = resource_pool.read(cr, uid, res_ids) vals = {'method': method,'object_id': model.id,'user_id': uid_orig } - old_value_text = '' for resource in resource_data: resource_id = resource['id'] del resource['id'] @@ -411,19 +385,12 @@ class audittrail_objects_proxy(object_proxy): lines = [] for field in resource.keys(): if field in ('__last_update', 'id'):continue - field_obj = resource_pool._all_columns.get(field) - field_obj = field_obj.column - old_value_text = resource[field] - if field_obj._type in ('one2many','many2many'): - data = pool.get(field_obj._obj).name_get(cr, uid, resource[field]) - old_value_text = map(lambda x:x[1], data) - elif field_obj._type == 'many2one': - old_value_text = resource[field] and resource[field][1] or resource[field] + ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource[field], False) line = { 'name': field, 'new_value': resource[field], 'old_value': old_values[resource_id]['value'][field], - 'new_value_text': old_value_text, + 'new_value_text': ret_val and ret_val or resource[field], 'old_value_text': old_values[resource_id]['text'][field] } lines.append(line) From 1dce682a32d0d20092553933921056df42a8d145 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Tue, 6 Sep 2011 17:57:35 +0530 Subject: [PATCH 011/134] [REF] bzr revid: nch@tinyerp.com-20110906122735-4ikr703mpzbiav5b --- addons/audittrail/audittrail.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 625d4d46072..244f26fba3f 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -266,7 +266,7 @@ class audittrail_objects_proxy(object_proxy): assert model_id, _("'%s' Model does not exist..." %(model)) model = model_pool.browse(cr, uid, model_id) relational_table_log = args and args[-1] == 'child_relation_log' or False - if method in ('create'): + if method == 'create': fields_to_read = [] if relational_table_log: res_id = args[0] @@ -297,7 +297,7 @@ class audittrail_objects_proxy(object_proxy): cr.close() return res_id - elif method in ('read'): + elif method == 'read': res_ids = args[0] old_values = {} res = fct_src(db, uid_orig, model.model, method, *args) @@ -321,7 +321,7 @@ class audittrail_objects_proxy(object_proxy): cr.close() return res - elif method in ('unlink'): + elif method == 'unlink': res_ids = args[0] res = False old_values = {} From 044e4f4c1a6c3be56d8efc581bb4520f6fedf251 Mon Sep 17 00:00:00 2001 From: "Naresh (OpenERP)" Date: Wed, 7 Sep 2011 18:08:13 +0530 Subject: [PATCH 012/134] [IMP/REF]:allowed entires to be logged when doing different actions/workflow/on_change/write etc...and removed and refactored the code bzr revid: nch@tinyerp.com-20110907123813-4thzx4y3e9vic7uq --- addons/audittrail/audittrail.py | 231 ++++++++++++++++---------------- 1 file changed, 114 insertions(+), 117 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 244f26fba3f..579ba005ba3 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -231,7 +231,7 @@ class audittrail_objects_proxy(object_proxy): cr.commit() return True - def get_x2m_m2o_values(self, cr, db, uid, pool, resource_pool, method, field, value, recursive=True): + def get_value_text(self, cr, db, uid, pool, resource_pool, method, field, value, recursive=True): field_obj = (resource_pool._all_columns.get(field)).column if field_obj._type in ('one2many','many2many'): if recursive: @@ -242,6 +242,27 @@ class audittrail_objects_proxy(object_proxy): return value and value[1] or value return False + def start_log_process(self, cr, db, user_id, model, method, resource_data, pool, resource_pool): + key1 = '%s_value'%(method == 'create' and 'new' or 'old') + key2 = '%s_value_text'%(method == 'create' and 'new' or 'old') + uid = 1 + vals = { 'method': method, 'object_id': model.id,'user_id': user_id} + for resource, fields in resource_data.iteritems(): + vals.update({'res_id': resource}) + log_id = pool.get('audittrail.log').create(cr, uid, vals) + lines = [] + for field_key, value in fields.iteritems(): + if field_key in ('__last_update', 'id'):continue + ret_val = self.get_value_text(cr, db, uid, pool, resource_pool, method, field_key, value, method != 'read') + line = { + 'name': field_key, + key1: value, + key2: ret_val and ret_val or value + } + lines.append(line) + self.create_log_line(cr, uid, log_id, model, lines) + return True + def log_fct(self, db, uid, model, method, fct_src, *args): """ Logging function: This function is performs logging operations according to method @@ -259,14 +280,12 @@ class audittrail_objects_proxy(object_proxy): cr = pooler.get_db(db).cursor() resource_pool = pool.get(model) log_pool = pool.get('audittrail.log') - model_pool = pool.get('ir.model') - - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) - model_id = model_ids and model_ids[0] or False - assert model_id, _("'%s' Model does not exist..." %(model)) - model = model_pool.browse(cr, uid, model_id) + model = self.check_rule_subscription(cr, uid, pool, model, False) + assert model, _("'%s' Model does not exist..." %(model)) + relational_table_log = args and args[-1] == 'child_relation_log' or False if method == 'create': + resource_data = {} fields_to_read = [] if relational_table_log: res_id = args[0] @@ -274,77 +293,29 @@ class audittrail_objects_proxy(object_proxy): res_id = fct_src(db, uid_orig, model.model, method, *args) cr.commit() fields_to_read = args[0].keys() - resource = resource_pool.read(cr, uid, res_id, fields_to_read) - if not isinstance(resource, list): - resource = [resource] - vals = { 'method': method, 'object_id': model.id,'user_id': uid_orig} - for resource_data in resource: - vals.update({'res_id': resource_data['id']}) - del resource_data['id'] - log_id = log_pool.create(cr, uid, vals) - lines = [] - for field in resource_data: - if field in ('__last_update', 'id'):continue - ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource_data[field]) - line = { - 'name': field, - 'new_value': resource_data[field], - 'new_value_text': ret_val and ret_val or resource_data[field] - } - lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) - cr.commit() + if res_id: + resource = resource_pool.read(cr, uid, res_id, fields_to_read) + if not isinstance(resource,list): + resource = [resource] + map(lambda x: resource_data.setdefault(x['id'], x), resource) + self.start_log_process(cr, db, uid_orig, model, method, resource_data, pool, resource_pool) + cr.commit() cr.close() return res_id - elif method == 'read': + elif method in('read', 'unlink'): res_ids = args[0] old_values = {} - res = fct_src(db, uid_orig, model.model, method, *args) - map(lambda x:old_values.setdefault(x['id'], x), res) - vals = {'method': method,'object_id': model.id,'user_id': uid_orig} - for res_id in old_values: - vals.update({'res_id': res_id}) - log_id = log_pool.create(cr, uid, vals) - lines = [] - for field in old_values[res_id]: - if field in ('__last_update', 'id'):continue - ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, old_values[res_id][field], False) - line = { - 'name': field, - 'old_value': old_values[res_id][field], - 'old_value_text': ret_val and ret_val or old_values[res_id][field] - } - lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) - cr.commit() - cr.close() - return res - - elif method == 'unlink': - res_ids = args[0] - res = False - old_values = {} - for res_id in res_ids: - old_values[res_id] = resource_pool.read(cr, uid, res_id) - vals = {'method': method,'object_id': model.id,'user_id': uid_orig} - for res_id in res_ids: - vals.update({'res_id': res_id}) - log_id = log_pool.create(cr, uid, vals) - lines = [] - for field in old_values[res_id]: - if field in ('__last_update', 'id'):continue - ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, old_values[res_id][field]) - line = { - 'name': field, - 'old_value': old_values[res_id][field], - 'old_value_text': ret_val and ret_val or old_values[res_id][field] - } - lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) - if not relational_table_log: + if method == 'read': res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + map(lambda x: old_values.setdefault(x['id'], x), res) + else: + res = resource_pool.read(cr, uid, res_ids) + map(lambda x:old_values.setdefault(x['id'], x), res) + self.start_log_process(cr, db, uid_orig, model, method, old_values, pool, resource_pool) + if not relational_table_log and method == 'unlink': + res = fct_src(db, uid_orig, model.model, method, *args) + cr.commit() cr.close() return res else: @@ -359,47 +330,79 @@ class audittrail_objects_proxy(object_proxy): if isinstance(res_ids, (long, int)): res_ids = [res_ids] if res_ids: - resource_data = resource_pool.read(cr, uid, res_ids) - for resource in resource_data: - resource_id = resource['id'] - del resource['id'] - old_values_text = {} - old_value = {} - for field in resource.keys(): - if field in ('__last_update', 'id'):continue - ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource[field]) - old_value[field] = resource[field] - old_values_text[field] = ret_val and ret_val or resource[field] - old_values[resource_id] = {'text':old_values_text, 'value': old_value} - if not relational_table_log: - res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + x2m_old_values = {} + old_values = {} + def inline_process_old_data(res_ids, model, model_id=False): + resource_pool = pool.get(model) + resource_data = resource_pool.read(cr, uid, res_ids) + _old_values = {} + for resource in resource_data: + _old_values_text = {} + _old_value = {} + resource_id = resource['id'] + for field in resource.keys(): + if field in ('__last_update', 'id'):continue + field_obj = (resource_pool._all_columns.get(field)).column + if field_obj._type in ('one2many','many2many'): + x2m_rule_ids, x2m_model = self.check_rule_subscription(cr, uid, pool, field_obj._obj) + if x2m_rule_ids: + x2m_old_values.update(inline_process_old_data(resource[field], field_obj._obj, x2m_model)) + ret_val = self.get_value_text(cr, db, uid, pool, resource_pool, method, field, resource[field], False) + _old_value[field] = resource[field] + _old_values_text[field] = ret_val and ret_val or resource[field] + _old_values[resource_id] = {'text':_old_values_text, 'value': _old_value} + if model_id: + _old_values[resource_id].update({'model_id':model_id}) + return _old_values + old_values.update(inline_process_old_data(res_ids, model.model)) + res = fct_src(db, uid_orig, model.model, method, *args) + cr.commit() if res_ids: - resource_data = resource_pool.read(cr, uid, res_ids) - vals = {'method': method,'object_id': model.id,'user_id': uid_orig } - for resource in resource_data: - resource_id = resource['id'] - del resource['id'] - vals.update({'res_id': resource_id}) - log_id = log_pool.create(cr, uid, vals) - lines = [] - for field in resource.keys(): - if field in ('__last_update', 'id'):continue - ret_val = self.get_x2m_m2o_values(cr, db, uid, pool, resource_pool, method, field, resource[field], False) - line = { - 'name': field, - 'new_value': resource[field], - 'old_value': old_values[resource_id]['value'][field], - 'new_value_text': ret_val and ret_val or resource[field], - 'old_value_text': old_values[resource_id]['text'][field] - } - lines.append(line) - self.create_log_line(cr, uid, log_id, model, lines) + def inline_process_new_data(res_ids, model, dict_to_use={}): + resource_pool = pool.get(model.model) + resource_data = resource_pool.read(cr, uid, res_ids) + vals = {'method': method,'object_id': model.id,'user_id': uid_orig } + for resource in resource_data: + resource_id = resource['id'] + vals.update({'res_id': resource_id}) + log_id = log_pool.create(cr, uid, vals) + lines = [] + for field in resource.keys(): + if field in ('__last_update', 'id'):continue + field_obj = (resource_pool._all_columns.get(field)).column + if field_obj._type in ('one2many','many2many'): + x2m_rule_ids, x2m_model = self.check_rule_subscription(cr, uid, pool, field_obj._obj) + if x2m_rule_ids: + inline_process_new_data(resource[field], x2m_model, x2m_old_values) + ret_val = self.get_value_text(cr, db, uid, pool, resource_pool, method, field, resource[field], False) + line = { + 'name': field, + 'new_value': resource[field], + 'old_value': resource_id in dict_to_use and dict_to_use[resource_id]['value'].get(field), + 'new_value_text': ret_val and ret_val or resource[field], + 'old_value_text': resource_id in dict_to_use and dict_to_use[resource_id]['text'].get(field) + } + lines.append(line) + self.create_log_line(cr, uid, log_id, model, lines) + return True + inline_process_new_data(res_ids, model, old_values) cr.commit() cr.close() return res return True - + + def check_rule_subscription(self, cr, uid, pool, model, rule_check=True): + ''' + Test if the model has been subscribed to the audit rule + if yes then return the rule_ids also return the model browse_record object. + ''' + model_ids = pool.get('ir.model').search(cr, uid, [('model', '=', model)]) + model_obj = model_ids and model_ids[0] and pool.get('ir.model').browse(cr, uid, model_ids[0]) or False + if rule_check: + rule_ids = pool.get('audittrail.rule').search(cr, uid, [('object_id', '=', model_obj.id), ('state', '=', 'subscribed')]) + return rule_ids, model_obj + return model_obj + def audit_log_call(self, db, uid, model, method, action_type, *args, **argv): """ Overrides Object Proxy execute method @@ -414,8 +417,6 @@ class audittrail_objects_proxy(object_proxy): uid = 1 pool = pooler.get_pool(db) logged_uids = [] - model_pool = pool.get('ir.model') - rule_pool = pool.get('audittrail.rule') cr = pooler.get_db(db).cursor() cr.autocommit(True) if action_type == 'execute': @@ -426,14 +427,10 @@ class audittrail_objects_proxy(object_proxy): else: fct_src = super(audittrail_objects_proxy, self).exec_workflow try: - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) - model_id = model_ids and model_ids[0] or False - if not ('audittrail.rule' in pool.obj_list()) or not model_id: + rule_ids, model_obj = self.check_rule_subscription(cr, uid, pool, model) + if not ('audittrail.rule' in pool.obj_list() and model_obj and rule_ids): return fct_src(db, uid_orig, model, method, *args, **argv) - rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) - if not rule_ids: - return fct_src(db, uid_orig, model, method, *args, **argv) - for model_rule in rule_pool.browse(cr, uid, rule_ids): + for model_rule in pool.get('audittrail.rule').browse(cr, uid, rule_ids): logged_uids += map(lambda x:x.id, model_rule.user_id) if not logged_uids or uid in logged_uids: if action_type == 'execute': From e21d4b3e42cb66abf93595e406909d3f9fb6bdee Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Tue, 13 Sep 2011 14:24:34 +0530 Subject: [PATCH 013/134] [ADD] add basic structure of web_process module. bzr revid: ysa@tinyerp.com-20110913085434-z2a2615i2jpwdhmy --- addons/web_process/__init__.py | 0 addons/web_process/__openerp__.py | 11 +++++++++ .../static/src/img/iconset-a-help.gif | Bin 0 -> 379 bytes addons/web_process/static/src/js/process.js | 22 ++++++++++++++++++ .../static/src/xml/web_process.xml | 11 +++++++++ 5 files changed, 44 insertions(+) create mode 100644 addons/web_process/__init__.py create mode 100644 addons/web_process/__openerp__.py create mode 100644 addons/web_process/static/src/img/iconset-a-help.gif create mode 100644 addons/web_process/static/src/js/process.js create mode 100644 addons/web_process/static/src/xml/web_process.xml diff --git a/addons/web_process/__init__.py b/addons/web_process/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/web_process/__openerp__.py b/addons/web_process/__openerp__.py new file mode 100644 index 00000000000..6b6886eae52 --- /dev/null +++ b/addons/web_process/__openerp__.py @@ -0,0 +1,11 @@ +{ + "name" : "Process", + "version" : "2.0", + "depends" : ["web"], + "js": [ + "static/src/js/process.js" + ], + "css": [ + ], + 'active': True +} diff --git a/addons/web_process/static/src/img/iconset-a-help.gif b/addons/web_process/static/src/img/iconset-a-help.gif new file mode 100644 index 0000000000000000000000000000000000000000..5400acec57bd30ea50c05765808d2d20684a6f90 GIT binary patch literal 379 zcmV->0fhcXNk%w1VGaNe0M$MK@$m5T^Yiuf_4D%b_xJbd=jZF|>)qSi|NsBt-{11_ z@#^X6-rU^r@$u~H>h10A?d$96=;+wj*W%#dt*x!**wa??(FRA>FMa^=JxjX{r&y)^z`N9gww5?(XpL@cjJz?Ck9C?d@Dy zSpWb4A^8LW002G!EC2ui01f~S000J^fY5NrK7qlY#sZD<0W&f-H9Cem6ev80H8wU1IgvRb9FUO! zHWe=qJe{7M4=)u3A_h38CKRVQ1|9_v69)@7H#IY~3kMSrJrNce2`{uS2^kg + + + + + + + +

Process View

+
+ From bc35b1250e0f8483f0301e2e121f82c3ef45f685 Mon Sep 17 00:00:00 2001 From: "Yogesh (OpenERP)" Date: Tue, 13 Sep 2011 16:32:27 +0530 Subject: [PATCH 014/134] [IMP] Improve process task. bzr revid: ysa@tinyerp.com-20110913110227-lnnw3e72hjtrsqaw --- addons/web_process/__openerp__.py | 1 + addons/web_process/static/src/css/process.css | 58 ++++++++++++++++++ addons/web_process/static/src/img/cta-a.gif | Bin 0 -> 108 bytes addons/web_process/static/src/img/sep-a.gif | Bin 0 -> 43 bytes .../static/src/xml/web_process.xml | 35 ++++++++++- 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 addons/web_process/static/src/css/process.css create mode 100644 addons/web_process/static/src/img/cta-a.gif create mode 100644 addons/web_process/static/src/img/sep-a.gif diff --git a/addons/web_process/__openerp__.py b/addons/web_process/__openerp__.py index 6b6886eae52..fd1a48a3a0d 100644 --- a/addons/web_process/__openerp__.py +++ b/addons/web_process/__openerp__.py @@ -6,6 +6,7 @@ "static/src/js/process.js" ], "css": [ + "static/src/css/process.css" ], 'active': True } diff --git a/addons/web_process/static/src/css/process.css b/addons/web_process/static/src/css/process.css new file mode 100644 index 00000000000..6522932a39a --- /dev/null +++ b/addons/web_process/static/src/css/process.css @@ -0,0 +1,58 @@ + +a.cta-a { + float: left; + padding: 5px 10px; + border: 1px solid #ccc; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #eeeded url(/web_process/static/src/img/cta-a.gif) repeat-x; + box-shadow: 0 1px 0 #fff; + -moz-box-shadow: 0 1px 0 #fff; + -webkit-box-shadow: 0 1px 0 #fff; + color: #8c8c8c; + font-size: 0.9em; + text-transform: uppercase; + font-weight: bold; + text-shadow: #fff 0 1px 0; + margin: 2px; +} + +a.cta-a span { + float: left; + padding: 7px 0 5px 5px; + background-position: 0 50%; + background-repeat: no-repeat; + cursor: pointer; +} + +a.cta-a strong { + display: block; + color: #393939; +} + +.process_h1 { + background:url("/web_process/static/src/img/sep-a.gif") repeat-x scroll 0 90% transparent; + font-size:2em; + font-weight:normal; + padding:0 0 5px 5px; + line-height: 1.2; +} + +.process-links { + padding: 5px 10px; + text-align: center; + display: table; + margin: auto; +} + +.process-links a.cta-a { + display: table-cell; +} + +.process-help-text { + float: left; + padding:5px 10px; + min-height:56px; + font-size: 120%; +} \ No newline at end of file diff --git a/addons/web_process/static/src/img/cta-a.gif b/addons/web_process/static/src/img/cta-a.gif new file mode 100644 index 0000000000000000000000000000000000000000..daa561e29f58d52f0806ada27a6ad25c1e30f24a GIT binary patch literal 108 zcmZ?wbhEHbWMt4`*v!E2_3PJ0dKfZtW z?lTa4`t;??mk;mXzkB;u@h1xd28j~(|&5Rgd;v{>OR;HAys JFXPT&4FG9+IZXfn literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/sep-a.gif b/addons/web_process/static/src/img/sep-a.gif new file mode 100644 index 0000000000000000000000000000000000000000..5a064f21e89f03e8e6ffd1b898fa51b2fae272e0 GIT binary patch literal 43 scmZ?wbhEHbWMp7sXkcKtd;9jUpFb6UvM_*v4u}BBFfcK>a4}c|00`s>g#Z8m literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 76a281b911b..a37709ed3e6 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -6,6 +6,39 @@ -

Process View

+ + + + +
From 6c17995fb7145e3b555e7004dc6fd5d7f1b8f4d9 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Mon, 19 Sep 2011 15:27:30 +0530 Subject: [PATCH 015/134] [FIX] Extend with ViewManager. bzr revid: vda@tinyerp.com-20110919095730-toavlykgeokcg4d0 --- addons/web_process/static/src/js/process.js | 99 ++++++-------- .../static/src/xml/web_process.xml | 128 +++++++++--------- 2 files changed, 106 insertions(+), 121 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 40f4663c08a..b1665e44a7a 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -2,77 +2,69 @@ openerp.web_process = function (openerp) { var QWeb = openerp.web.qweb; QWeb.add_template('/web_process/static/src/xml/web_process.xml'); - openerp.web.ViewManagerAction.include({ - on_mode_switch: function (view_type) { + openerp.web.ViewManager.include({ + start: function() { + this._super(); var self = this; + + this.process_check(); + }, + process_check: function() { + var self = this, + grandparent = this.widget_parent && this.widget_parent.widget_parent, + view = this.views[this.views_src[0].view_type], + $process_view = this.$element.find('.oe-process-view'); + this.process_model = this.model; - return $.when( - this._super(view_type), - this.process_check(this.views[view_type])).then(function () { - }); - }, - process_check: function(view) { - var self = this; - var grandparent = this.widget_parent && this.widget_parent.widget_parent; - // display shortcuts if on the first view for the action - var $process_toggle = this.$element.find('.oe-process-toggle'); - if (!(grandparent instanceof openerp.web.WebClient) || + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { - $process_toggle.hide(); + $process_view.hide(); return; } - $process_toggle.show(); - $process_toggle - .unbind("click") - .click(function(){ - $.when(self.load_process()).then(self.get_process_id()); - }); - }, - - load_process: function() { -// this.widget_parent.$element.html(QWeb.render("ProcessView",this)); - this.$element.html(QWeb.render("ProcessView",this)); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset - .call( - "search_by_model", - [self.process_model,self.session.context], - function(res) { - self.renderer(res); - } - ); - }, - - renderer: function(res) { + $process_view.click(function() { + $.when(self.load_process()).then(self.get_process_id()); + }); + }, + + load_process: function() { + this.$element.html(QWeb.render("ProcessView",this)); + }, + + get_process_id: function() { + var self = this; + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset + .call( + "search_by_model", + [self.process_model,self.session.context], + function(res) {self.process_renderer(res)} + ); + }, + + process_renderer: function(res) { var self = this; if(!res.length) { this.process_model = false; this.get_process_id(); } else { - if(res.length > 1) { this.selection = res; - $.when(this.load_process()).then(function() { - self.widget_parent.$element.find('#change_process').click(function(){ - - self.p_id = self.widget_parent.$element.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - + $.when(this.load_process()) + .then(function(){ + var $parent = self.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.selection = false; + self.p_id = $parent.find('#select_process').val(); + $.when(self.load_process()).then(self.render_process_view()); + }); }); - }); - } - else { + } else { this.p_id = res[0][0]; $.when(this.load_process()).then(this.render_process_view()); } } }, - render_process_view: function() { var self = this; this.p_id = parseInt(this.p_id, 10); @@ -150,7 +142,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .push(process_node) .push(process_node_text) .push(process_node_desc); - process_node.mousedown(function(){ + process_node.mousedown(function() { return false; }) return process_set; @@ -189,7 +181,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); } ); } - }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 6634f6d8446..11037671e01 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -1,73 +1,67 @@ From 83ad47b00373c87a459c29ca3d542e90b3030e90 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 22:38:19 +0530 Subject: [PATCH 016/134] [ADD] node images. bzr revid: vda@tinyerp.com-20110920170819-kn0a3uwa32m610v7 --- addons/web_process/static/src/img/ToolOval.jpg | Bin 0 -> 650 bytes .../web_process/static/src/img/ToolShowGrid.jpg | Bin 0 -> 635 bytes .../web_process/static/src/img/ToolShowGrid.png | Bin 0 -> 810 bytes addons/web_process/static/src/img/button-a-a.png | Bin 0 -> 6595 bytes addons/web_process/static/src/img/grid_10.jpg | Bin 0 -> 4530 bytes .../web_process/static/src/img/node-current.png | Bin 0 -> 2472 bytes addons/web_process/static/src/img/node-gray.png | Bin 0 -> 2445 bytes .../static/src/img/node-subflow-gray.png | Bin 0 -> 5105 bytes .../web_process/static/src/img/node-subflow.png | Bin 0 -> 5153 bytes addons/web_process/static/src/img/node.png | Bin 0 -> 2503 bytes addons/web_process/static/src/img/port.gif | Bin 0 -> 166 bytes addons/web_process/static/src/img/window_bg.png | Bin 0 -> 128 bytes .../static/src/img/window_toolbar.png | Bin 0 -> 200 bytes 13 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/web_process/static/src/img/ToolOval.jpg create mode 100644 addons/web_process/static/src/img/ToolShowGrid.jpg create mode 100644 addons/web_process/static/src/img/ToolShowGrid.png create mode 100644 addons/web_process/static/src/img/button-a-a.png create mode 100644 addons/web_process/static/src/img/grid_10.jpg create mode 100644 addons/web_process/static/src/img/node-current.png create mode 100644 addons/web_process/static/src/img/node-gray.png create mode 100644 addons/web_process/static/src/img/node-subflow-gray.png create mode 100644 addons/web_process/static/src/img/node-subflow.png create mode 100644 addons/web_process/static/src/img/node.png create mode 100644 addons/web_process/static/src/img/port.gif create mode 100644 addons/web_process/static/src/img/window_bg.png create mode 100644 addons/web_process/static/src/img/window_toolbar.png diff --git a/addons/web_process/static/src/img/ToolOval.jpg b/addons/web_process/static/src/img/ToolOval.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c30f15a07d27df0d0e0b9baf91a444f74f00482c GIT binary patch literal 650 zcmex=PKLX?fy#VwC z5@2KJUZf(oWdIz%Q+VDQP)%Q^J;!30MZp(R4sLSK9@_^NqH?lZ^D)bA0g*Qb}n zO5Q#e_FW?W>~7tETP~T0X%{Ur5B|2>gs=S2i=8gsMpr$zzYA3KShdKt;LvfAsr+}D zW!7+Q_}s1MThX~!=}Ft%#mk@FP7xAJRJbvBqy28F*_q2)_8pPnk(!dc#Csp}p|Uzj z_fWYzUrkF(H+{Pne$8sHt0T*UHK$fFEwEU%f`NN>?2Ku%vNm~Ir5s>LnE(GK0H}(` AdH?_b literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/ToolShowGrid.jpg b/addons/web_process/static/src/img/ToolShowGrid.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8285acc8aaca324c30f67748dec386d635ff9ba5 GIT binary patch literal 635 zcmex=PKLX?fy#VwC z5@2Cv;{eL&3NSD-0|65YJ5-X15$FdtK?WgVMI}d(M0PR5g`&!;M$UmjAcGhgm{HAP zVrF3gSs^KiF2xA6Uy=F$Ee0ND5R+Mu!JgsEl`mUwe}3WQ#A03eP{!1Mf7s2LofCIx zbTlPTdE+mCZ@Fajg@qbV{>JX!wlczn-{YJ6gqFHJ`^;;%&Mwmb;ou6@yJg zP918fD|dBuIraPH(kjV}`{vmu@4UU@oIYkf?A;k;;ntEVvsBA2p_nbDW%Zu=`(5%dxgOlE%-&H~m(-KB;N?%t@2yN2aUnDC=MP d&`ogfU*SEQy7%9fxa?~pwmCh*flc`TO#pL)yWao+ literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/ToolShowGrid.png b/addons/web_process/static/src/img/ToolShowGrid.png new file mode 100644 index 0000000000000000000000000000000000000000..ea530671b97bb7e150e4a8cf5097f2bd0d2a073f GIT binary patch literal 810 zcmbV}?N3s16vuB_p>EoGVK!M0qSJgRUexBAFU)2buFMQ`EjP`WT9#UCYt?2-rI96q z8f2}qk)};+u$oy$2s%eNpQX$Mf#ULTFZW*H-av$Y{tKP$JnZv5=fydPpO>2*5gro` zK~MzyNLD_`+txfZ1VmlWxCVmON%M|!4hMt5V%X=K{>9w{kV5X zGYd$)P&%TW4Fm$zUtilR8Af;l0f2+*$p!yvz(aYRxZCd!I0-jNc}FG}fTZ{~?zCPPw4y*QsBEa=N#vh3F4B)+ zl*Nt{{0 zuAgRf-e8+E*kr01z~7I|nH-b}p_X9chZ!|GsPATU$wC0>#)FqK#l*6mT>OLUjEK&( zw#)UVmvZ&oJLPoWmx(^b1R(!y`Kmp|;BD)!=I5S-4*vOG2I~FntW3^s;kl9*$t7HF zDGN$qv9=CuNTH|G66th$A}yVs5*HWE;qjj|iUq}W;=;VT=K^u#6Lx5_GBuUK&@dDB zG8jr`5`!_48qwM!Y;Uy`wzL;;3}SJ6LFuUmb`2I65?K}{xzpP*xJl8~@#sUOqQ9df zS-yjFNdI+mOrlrM&T60Phqco=`WUo`ekQ&4CXGhRu1%!TS*&tNWOQNLwc5?cnbkXM zi>otktwNIR^_iJUe{5#w*;xN_XXh5JaG)q^W9z+U{zH>Mz~{3Kf+jwjo6BRzcT2nQ z?s6`dOO(Ho#_uav4JRk2F`p}TF_~{$GBTKHjXk00qEVFJEE9=DSDL3qrL58LBK$;H x`|IBRp1wEL6&Ej5oxfD+gdMhoq-SC4Au{Jc{fSR!u7hJj?8CWP{fA0;{{She3Df`p literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/button-a-a.png b/addons/web_process/static/src/img/button-a-a.png new file mode 100644 index 0000000000000000000000000000000000000000..bd046bbbef7da60895536a7a18323abbbe21e7fb GIT binary patch literal 6595 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 AIsgCw literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/grid_10.jpg b/addons/web_process/static/src/img/grid_10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5254207b96407a79195cd541dfb145417e8bdb30 GIT binary patch literal 4530 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node-gray.png b/addons/web_process/static/src/img/node-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..2334abbc2fef44e2c9577a94f19e3baed713a8d0 GIT binary patch literal 2445 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node-subflow-gray.png b/addons/web_process/static/src/img/node-subflow-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..7703eedd2f0c9252ddc69d4a0437bf24c91915ca GIT binary patch literal 5105 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 literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/node.png b/addons/web_process/static/src/img/node.png new file mode 100644 index 0000000000000000000000000000000000000000..4ed3681fa8d10986952d531dfa9838dc0b8d9d3d GIT binary patch literal 2503 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 a`J7+mD_7u#+WR#?tqh*7elF{r5}E+Ip)ZjD literal 0 HcmV?d00001 diff --git a/addons/web_process/static/src/img/window_toolbar.png b/addons/web_process/static/src/img/window_toolbar.png new file mode 100644 index 0000000000000000000000000000000000000000..77c30b79d828448d0d87b6654424e77b19375de7 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQB!2~4x+s^U*D&i&7I%`2HW3thI00 sEMM&1Ed7LmVYegSF$o|yPFBV4Z=>e6lX{}sKvyt$y85}Sb4q9e0HWbZS^xk5 literal 0 HcmV?d00001 From 8ab9a5ecf946d87a0bf6673de7ead6438c1aa879 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 22:43:15 +0530 Subject: [PATCH 017/134] [FIX] typo. bzr revid: vda@tinyerp.com-20110920171315-k1aambijdl9ih04n --- addons/web_process/static/src/js/process.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index b1665e44a7a..a9cd506bc57 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -83,6 +83,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); }, draw_process_graph: function(res) { + var self = this; var process_graph = new Graph(); var process_renderer = function(r, n) { From d05651bebe85660224b97c05c70c6e215651cde8 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Tue, 20 Sep 2011 23:00:31 +0530 Subject: [PATCH 018/134] [FIX] Does not allowed drag&drop. bzr revid: vda@tinyerp.com-20110920173031-ialtmcpub2c24k04 --- addons/web_process/static/src/js/process.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index a9cd506bc57..b6642a7980b 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -105,7 +105,11 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); bg = n.node.gray ? bg + "-gray" : bg; img_src = '/web_process/static/src/img/'+ bg + '.png'; - r['image'](img_src, n.node.x, n.node.y,150, 100).attr({"clip-rect": clip_rect}); + r['image'](img_src, n.node.x, n.node.y,150, 100) + .attr({"clip-rect": clip_rect}) + .mousedown(function(){ + return false; + }); //Node process_node = r['rect'](n.node.x, n.node.y, 150, 100); @@ -143,9 +147,9 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .push(process_node) .push(process_node_text) .push(process_node_desc); - process_node.mousedown(function() { + process_set.mousedown(function() { return false; - }) + }); return process_set; }; From e070274115ad2c87a16353c08e2d3d3725476bd3 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 12:16:40 +0530 Subject: [PATCH 019/134] [FIX] subflow id. bzr revid: vda@tinyerp.com-20110921064640-0j7ikcpvuaivicc7 --- addons/web_process/static/src/js/process.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index b6642a7980b..67bb8791441 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -120,7 +120,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); if(n.node.subflow) { process_node_text.click(function() { - self.p_id = n.node.id; + self.p_id = n.node.subflow[0]; $.when(self.load_process()).then(self.render_process_view()); }); } From 1aa8f369002c762441d409839581d94817ca2015 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 13:07:29 +0530 Subject: [PATCH 020/134] [FIX] do not show border on rect.background image.desc node does not need to add in set. bzr revid: vda@tinyerp.com-20110921073729-zqjijfseuz4ipc1h --- addons/web_process/static/src/js/process.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 67bb8791441..11b44e87d93 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -112,7 +112,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); }); //Node - process_node = r['rect'](n.node.x, n.node.y, 150, 100); + process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); // Node text process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) @@ -128,7 +128,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); //Node Description process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); - r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": "Help"}) .click(function(){ @@ -139,14 +138,13 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) .attr({"cursor": "pointer", "title": n.node.menu.name}) .click(function() { - self.jump_to_view(n.node.res_model, n.node.menu.id) + self.jump_to_view(n.node.res_model, n.node.menu.id); }); } process_set = r.set() .push(process_node) - .push(process_node_text) - .push(process_node_desc); + .push(process_node_text); process_set.mousedown(function() { return false; }); From 6ca5e79d89e8e56b15955c4795f1f955a3673315 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 13:34:18 +0530 Subject: [PATCH 021/134] [FIX] node text not in set. bzr revid: vda@tinyerp.com-20110921080418-vlfezcpkcrj84tbe --- addons/web_process/static/src/js/process.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 11b44e87d93..362bbd8e108 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -116,7 +116,7 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); // Node text process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) - .attr({"fill": "#fff", "font-weight": "bold"}); + .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); if(n.node.subflow) { process_node_text.click(function() { @@ -144,7 +144,6 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); process_set = r.set() .push(process_node) - .push(process_node_text); process_set.mousedown(function() { return false; }); From a7a256454283f4b6a1241abd9df335a23ef16785 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 21 Sep 2011 15:18:23 +0530 Subject: [PATCH 022/134] [FIX] Load subflow actions. bzr revid: vda@tinyerp.com-20110921094823-4rrqbdov4s0csk0t --- addons/web_process/static/src/js/process.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 362bbd8e108..67c62efbcd4 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -176,10 +176,16 @@ QWeb.add_template('/web_process/static/src/xml/web_process.xml'); .call('get', ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], function(res) { + self.$element.empty(); var action = res[0][res[0].length - 1]; - var action_manager = new openerp.web.ActionManager(self); - action_manager.appendTo(self.widget_parent.$element); - action_manager.do_action(action); + self.rpc("/web/action/load", { + action_id: action.id, + context: dataset.context + }, function(result) { + var action_manager = new openerp.web.ActionManager(self); + action_manager.appendTo(self.widget_parent.$element); + action_manager.do_action(result.result); + }); } ); } From 78eb1e13e5a5284854a17cd90d14174b5702be79 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Wed, 28 Sep 2011 14:17:39 +0530 Subject: [PATCH 023/134] [FIX] Indentation.Show help. bzr revid: vda@tinyerp.com-20110928084739-cd0tnajmulohp0k8 --- addons/web_process/static/src/js/process.js | 387 +++++++++--------- .../static/src/xml/web_process.xml | 134 +++--- 2 files changed, 269 insertions(+), 252 deletions(-) diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 67c62efbcd4..d8d178ae63d 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -1,195 +1,208 @@ - openerp.web_process = function (openerp) { -var QWeb = openerp.web.qweb; -QWeb.add_template('/web_process/static/src/xml/web_process.xml'); - openerp.web.ViewManager.include({ - start: function() { - this._super(); - var self = this; - - this.process_check(); - }, - process_check: function() { - var self = this, - grandparent = this.widget_parent && this.widget_parent.widget_parent, - view = this.views[this.views_src[0].view_type], - $process_view = this.$element.find('.oe-process-view'); - - this.process_model = this.model; - if (!(grandparent instanceof openerp.web.WebClient) || + var QWeb = openerp.web.qweb; + QWeb.add_template('/web_process/static/src/xml/web_process.xml'); + openerp.web.ViewManager.include({ + start: function() { + this._super(); + var self = this; + this.process_check(); + this.process_help = this.action.help || 'Help: Not Defined'; + }, + process_check: function() { + var self = this, + grandparent = this.widget_parent && this.widget_parent.widget_parent, + view = this.views[this.views_src[0].view_type], + $process_view = this.$element.find('.oe-process-view'); + + this.process_model = this.model; + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { - $process_view.hide(); - return; + $process_view.hide(); + return; } - $process_view.click(function() { - $.when(self.load_process()).then(self.get_process_id()); - }); - }, - - load_process: function() { - this.$element.html(QWeb.render("ProcessView",this)); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset - .call( - "search_by_model", - [self.process_model,self.session.context], - function(res) {self.process_renderer(res)} - ); - }, - - process_renderer: function(res) { - var self = this; - if(!res.length) { - this.process_model = false; - this.get_process_id(); - } else { - if(res.length > 1) { - this.selection = res; - $.when(this.load_process()) - .then(function(){ - var $parent = self.widget_parent.$element; - $parent.find('#change_process').click(function() { - self.selection = false; - self.p_id = $parent.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - }); - }); - } else { - this.p_id = res[0][0]; - $.when(this.load_process()).then(this.render_process_view()); - } - } - }, - render_process_view: function() { - var self = this; - this.p_id = parseInt(this.p_id, 10); - this.process_dataset - .call( - "graph_get", - [self.p_id, self.model, false, [80,80,150,100]], - function(res) { - res['title'] = res.resource ? res.resource : res.name; - self.process_dataset.call("search_by_model",[self.model,self.session.context],function(r){ - res['related'] = r; - }); - self.draw_process_graph(res); - } - ); - }, - - draw_process_graph: function(res) { - var self = this; - var process_graph = new Graph(); - - var process_renderer = function(r, n) { - var process_node, - process_node_text, - process_node_desc, - process_set; - - var node_button, - node_menu, - img_src; - - var bg = "node"; - var clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"); - var text_position_x = n.node.kind == "subflow" ? n.node.x+88 : n.node.x+75; - - //Image part - bg = n.node.kind == "subflow" ? "node-subflow" : "node"; - bg = n.node.gray ? bg + "-gray" : bg; - img_src = '/web_process/static/src/img/'+ bg + '.png'; - - r['image'](img_src, n.node.x, n.node.y,150, 100) - .attr({"clip-rect": clip_rect}) - .mousedown(function(){ - return false; - }); - - //Node - process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); - - // Node text - process_node_text = r.text(text_position_x, n.node.y+10, (n.node.name)) - .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); - - if(n.node.subflow) { - process_node_text.click(function() { - self.p_id = n.node.subflow[0]; - $.when(self.load_process()).then(self.render_process_view()); - }); - } - - //Node Description - process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); - - r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) - .attr({"cursor": "pointer", "title": "Help"}) - .click(function(){ - window.open(n.node.url || "http://doc.openerp.com/v6.0/index.php?model=" + n.node.model); - }); - - if(n.node.menu) { - r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) - .attr({"cursor": "pointer", "title": n.node.menu.name}) - .click(function() { - self.jump_to_view(n.node.res_model, n.node.menu.id); - }); - } - - process_set = r.set() - .push(process_node) + $process_view.click(function() { + $.when(self.load_process()).then(self.get_process_id()); + }); + }, + + process_subflow : function() { + var self = this; + new openerp.web.DataSetSearch(this, + "ir.actions.act_window",this.session.context,[]) + .read_slice(['help'], + { domain: + [ + ['res_model','=',this.process_action_model], + ['name','ilike', this.process_action_name] + ] + }, + function(res) { + if (res.length) { + self.process_help = res[0]['help'] || 'Help: Not Defined'; + } + $.when(self.load_process()).then(self.render_process_view()); + + }); + }, + + load_process: function() { + this.$element.html(QWeb.render("ProcessView", this)); + }, + + get_process_id: function() { + var self = this; + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset.call("search_by_model", + [self.process_model,self.session.context], + function(res) {self.process_renderer(res)}); + }, + process_renderer: function(res) { + var self = this; + if(!res.length) { + this.process_model = false; + this.get_process_id(); + } else { + if(res.length > 1) { + this.selection = res; + $.when(this.load_process()).then(function() { + var $parent = self.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.selection = false; + self.p_id = $parent.find('#select_process').val(); + $.when(self.load_process()).then(self.render_process_view()); + }); + }); + } else { + this.p_id = res[0][0]; + $.when(this.load_process()).then(this.render_process_view()); + } + } + }, + + render_process_view: function() { + var self = this; + this.p_id = parseInt(this.p_id, 10); + this.process_dataset.call("graph_get", + [self.p_id, self.model, false, [80,80,150,100]], + function(res) { + res['title'] = res.resource ? res.resource : res.name; + self.process_dataset.call("search_by_model", + [self.model,self.session.context], + function(r) { + res['related'] = r; + }); + self.draw_process_graph(res); + } + ); + }, + + draw_process_graph: function(res) { + var self = this; + var process_graph = new Graph(); + + var process_renderer = function(r, n) { + var process_node, + process_node_text, + process_node_desc, + process_set; + + var node_button, + node_menu, + img_src; + + var bg = "node", + clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"), +// text_position_x = n.node.x + (n.node.y/2) + + //Image part + bg = n.node.kind == "subflow" ? "node-subflow" : "node"; + bg = n.node.gray ? bg + "-gray" : bg; + img_src = '/web_process/static/src/img/'+ bg + '.png'; + + r['image'](img_src, n.node.x, n.node.y,150, 100) + .attr({"clip-rect": clip_rect}) + .mousedown(function(){ + return false; + }); + + //Node + process_node = r['rect'](n.node.x, n.node.y, 150, 100).attr({stroke: "none"}); + // Node text + process_node_text = r.text(n.node.x, n.node.y, (n.node.name)) + .attr({"fill": "#fff", "font-weight": "bold", "cursor": "pointer"}); + process_node_text.translate(n.node.x / 2, 10) + if(n.node.subflow) { + process_node_text.click(function() { + self.p_id = n.node.subflow[0]; + self.process_action_model = n.node.model; + self.process_action_name = n.node.name; + self.process_subflow(); + }); + } + + //Node Description + process_node_desc = r.text(n.node.x+75, n.node.y+50, (n.node.notes)); + + r['image']('/web/static/src/img/icons/gtk-info.png', n.node.x+20, n.node.y+70, 16, 16) + .attr({"cursor": "pointer", "title": "Help"}) + .click(function() { + window.open(n.node.url || "http://doc.openerp.com/v6.0/index.php?model=" + n.node.model); + }); + + if(n.node.menu) { + r['image']('/web/static/src/img/icons/gtk-jump-to.png', n.node.x+115, n.node.y+70, 16, 16) + .attr({"cursor": "pointer", "title": n.node.menu.name}) + .click(function() { + self.jump_to_view(n.node.res_model, n.node.menu.id); + }); + } + + process_set = r.set().push(process_node); process_set.mousedown(function() { - return false; - }); - return process_set; - }; - - _.each(res['nodes'],function(node, node_id) { - node['res_model'] = self.model, - node['res_id'] = false, - node['id'] = node_id; - process_graph.addNode(node['name'], {node: node,render: process_renderer}); - }); - - _.each(res['transitions'], function(transitions) { - - var src = res['nodes'][transitions['source']]; - var dst = res['nodes'][transitions['target']]; - // make active - transitions['active'] = src.active && !dst.gray; - process_graph.addEdge(src['name'], dst['name'], {directed : true, label: transitions['name']}) - }); - var layouter = new Graph.Layout.Ordered(process_graph); - var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); - }, - - jump_to_view: function(model, id) { - var self = this; - var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); - dataset - .call('get', - ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], - function(res) { - self.$element.empty(); - var action = res[0][res[0].length - 1]; - self.rpc("/web/action/load", { - action_id: action.id, - context: dataset.context - }, function(result) { - var action_manager = new openerp.web.ActionManager(self); - action_manager.appendTo(self.widget_parent.$element); - action_manager.do_action(result.result); - }); - } - ); - } - }); + return false; + }); + return process_set; + }; + + _.each(res['nodes'],function(node, node_id) { + node['res_model'] = self.model, + node['res_id'] = false, + node['id'] = node_id; + process_graph.addNode(node['name'], {node: node,render: process_renderer}); + }); + + _.each(res['transitions'], function(transitions) { + var src = res['nodes'][transitions['source']]; + var dst = res['nodes'][transitions['target']]; + // make active + transitions['active'] = src.active && !dst.gray; + process_graph.addEdge(src['name'], dst['name'], {directed : true}); + }); + + var layouter = new Graph.Layout.Ordered(process_graph); + var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); + }, + + jump_to_view: function(model, id) { + var self = this; + var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); + dataset.call('get', + ['action', 'tree_but_open',[['ir.ui.menu', id]], dataset.context], + function(res) { + self.$element.empty(); + var action = res[0][res[0].length - 1]; + self.rpc("/web/action/load", { + action_id: action.id, + context: dataset.context + }, function(result) { + var action_manager = new openerp.web.ActionManager(self); + action_manager.appendTo(self.widget_parent.$element); + action_manager.do_action(result.result); + }); + }); + } + }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 11037671e01..94ab8e870f2 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -1,67 +1,71 @@ From ad61a880bf166d953d38774c437ec8b69bde7b3e Mon Sep 17 00:00:00 2001 From: "ARA (OpenERP)" Date: Wed, 28 Sep 2011 17:43:31 +0530 Subject: [PATCH 024/134] [FIX] hr-expense : incmplete handling of canceld and reopened invoices lp bug: https://launchpad.net/bugs/808704 fixed bzr revid: ara@tinyerp.com-20110928121331-p3x76mmel6ity9fs --- addons/hr_expense/hr_expense.py | 5 +++++ addons/hr_expense/hr_expense_view.xml | 1 + addons/hr_expense/hr_expense_workflow.xml | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py index 2dc6ad090ac..b671705d769 100644 --- a/addons/hr_expense/hr_expense.py +++ b/addons/hr_expense/hr_expense.py @@ -82,6 +82,7 @@ class hr_expense_expense(osv.osv): ('accepted', 'Approved'), ('invoiced', 'Invoiced'), ('paid', 'Reimbursed'), + ('invoice_except', 'Invoice Exception'), ('cancelled', 'Refused')], 'State', readonly=True, help='When the expense request is created the state is \'Draft\'.\n It is confirmed by the user and request is sent to admin, the state is \'Waiting Confirmation\'.\ \nIf the admin accepts it, the state is \'Accepted\'.\n If an invoice is made for the expense request, the state is \'Invoiced\'.\n If the expense is paid to user, the state is \'Reimbursed\'.'), @@ -224,6 +225,10 @@ class hr_expense_expense(osv.osv): res = inv_id return res + def action_invoice_cancel(self, cr, uid, ids, context=None): + self.write(cr, uid, ids, {'state': 'invoice_except'}, context=context) + return True + hr_expense_expense() class product_product(osv.osv): diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml index 786dc6beee2..a832191bb90 100644 --- a/addons/hr_expense/hr_expense_view.xml +++ b/addons/hr_expense/hr_expense_view.xml @@ -106,6 +106,7 @@ + + + From f516936e1c4976fc44e7c6b108ffbf2398ca8833 Mon Sep 17 00:00:00 2001 From: "Vaibhav (OpenERP)" Date: Thu, 29 Sep 2011 12:44:48 +0530 Subject: [PATCH 028/134] [FIX] Changed images for node text align. bzr revid: vda@tinyerp.com-20110929071448-119c8glmi4q6ol3z --- .../static/src/img/node-current.png | Bin 2472 -> 3143 bytes .../web_process/static/src/img/node-gray.png | Bin 2445 -> 3128 bytes .../static/src/img/node-subflow-gray.png | Bin 5105 -> 6837 bytes .../static/src/img/node-subflow.png | Bin 5153 -> 6851 bytes addons/web_process/static/src/img/node.png | Bin 2503 -> 3205 bytes addons/web_process/static/src/js/process.js | 4 ++-- 6 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_process/static/src/img/node-current.png b/addons/web_process/static/src/img/node-current.png index 2126e45dfd24ee944232a34b754b081eb9affdcf..51f86b04c786e91411168f858503553f1469f4e8 100644 GIT binary patch delta 3127 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 H{U`qefqoyj literal 2472 zcmd6p`9BkmAIAxEq};*~J{e;%*GL(k+|-;o#@r!CBW5f^QNq$kIV#60IZ|`aP?pRQ zEBp9}XtJDhHb*&H`0Bs-{_uJ|ACKqz@p%9Cemve;&IsFMA_^irJUqwj?W|l6S$LQb zA;6#Z>0dj9aEzUI91qWN+Mn?Dp{qj<9n#+FZ}-HK)h|9#iX%#C>*&y}X_S&d)rge5iRNe! z*QS2`H1x;FAfR3!p7I9pdU*^nbEd;tec3kn0eVx$`TiJ78n@=vtId|XKrAtm)l_zO zPs}X7R7wh=U>@*n`fPztoXB@!I zqZ;QB?1J3mHZ9TRPum{{Xu7W)+<~+L3)?xQuE1&JUBIp(Q^lH{K$dn75Q3L z3*4|{5&tEonls2P`r4(S0A|>4Z1=4|CX6R{M*MgtILAgflh#^h`|+4@Jad!H!ZG3) zJ%~w8e*M-&YHE{==ze5!$ZTagcWa2nbTln64HH+m!;AOy>zAtQm`72W}YnPE8$hnM*^fNx-OkEuJVhskL+H z0T3tiZfGFQf*wqhwqwzKZ(5i}Cg}KM|k-`1d zM!}2aY>g!@Ap!eVC?FcuTn$#tN;Zh!sUK#27E~vABziMXgvu;YUkk0lrn(fy&NfSG3 zwB-6E18-uCUr|xLqnka+OJ+nJr zV}p0$hwUct0T6LRLF8TO75BDgNW$4r|Jab@gXALk9N%7@}w#f>p#6=h%+{l_(B3Tn#8Z%1za{pEsVw736>m4%`u5dBGZ_H{Ce4m` z+ACr`t-2(KgZv`3&5>{S#~6}@4`EodEx824?DP!vN*8Oq*-=hgrploYHTRI;h*{p z3CTj}`7TKtJFhMwVMjUDK;ggs&xc)G1+K{D``G4Ocr&Mn+SD3yg*1fJ_Lxs8!ZooB`yTO5uxxocUryG7e~i1&h2_HwvK{ZS zlL)!F&&d0o$~P(ZYkhwC3h}2+Vp%;O=R)2~K6eG%*xD8>x7RTb(x?(+^El-#X`9ox zZ|`u5(ORtSsspioUZ_@VnR*4KqAEhnunnM!%>|7U0`0XzWBKNY~eG#w6ELMf{(N zJB|c)lBk$iQy4=zSMkh7o9j|8W_eTzo>J@vs1UxxxRshcVD4Uh@KN{vX zlV17eei|%AK#GR_qDca`jC7bS4beb)8^&0Vljj*acA8_-3Mi-@{ diff --git a/addons/web_process/static/src/img/node-gray.png b/addons/web_process/static/src/img/node-gray.png index 2334abbc2fef44e2c9577a94f19e3baed713a8d0..972013540cf00d5e379f9c9136b11499ab2e93f7 100644 GIT binary patch literal 3128 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 literal 2445 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 diff --git a/addons/web_process/static/src/img/node-subflow-gray.png b/addons/web_process/static/src/img/node-subflow-gray.png index 7703eedd2f0c9252ddc69d4a0437bf24c91915ca..ffafe1bd681f01d622bcb371dea2488a7d724868 100644 GIT binary patch literal 6837 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 diff --git a/addons/web_process/static/src/img/node.png b/addons/web_process/static/src/img/node.png index 4ed3681fa8d10986952d531dfa9838dc0b8d9d3d..853ac85cd566516bf18e7e4532ecf28610b25e0d 100644 GIT binary patch literal 3205 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 A Date: Thu, 29 Sep 2011 16:31:45 +0530 Subject: [PATCH 029/134] [IMP] show Fields.Changed Mechanism. bzr revid: vda@tinyerp.com-20110929110145-z5fgyg84acx3nuyl --- addons/web_process/static/src/css/process.css | 4 + addons/web_process/static/src/js/process.js | 288 +++++++++++------- .../static/src/xml/web_process.xml | 36 ++- 3 files changed, 207 insertions(+), 121 deletions(-) diff --git a/addons/web_process/static/src/css/process.css b/addons/web_process/static/src/css/process.css index 6522932a39a..364c3788b11 100644 --- a/addons/web_process/static/src/css/process.css +++ b/addons/web_process/static/src/css/process.css @@ -55,4 +55,8 @@ a.cta-a strong { padding:5px 10px; min-height:56px; font-size: 120%; +} + +td.process_fields,button.toggle_fields span:last-child { + display: none; } \ No newline at end of file diff --git a/addons/web_process/static/src/js/process.js b/addons/web_process/static/src/js/process.js index 9fd6606fdc6..faff7d7bb8e 100644 --- a/addons/web_process/static/src/js/process.js +++ b/addons/web_process/static/src/js/process.js @@ -7,141 +7,156 @@ openerp.web_process = function (openerp) { var self = this; this.process_check(); this.process_help = this.action ? this.action.help : 'Help: Not Defined'; + this.process_model = this.model; }, process_check: function() { var self = this, grandparent = this.widget_parent && this.widget_parent.widget_parent, view = this.views[this.views_src[0].view_type], $process_view = this.$element.find('.oe-process-view'); - - this.process_model = this.model; + if (!(grandparent instanceof openerp.web.WebClient) || !(view.view_type === this.views_src[0].view_type && view.view_id === this.views_src[0].view_id)) { $process_view.hide(); return; } + $process_view.click(function() { - $.when(self.load_process()).then(self.get_process_id()); + self.initialize_process_view(); }); + }, - - process_subflow : function() { + + initialize_process_view: function() { var self = this; - new openerp.web.DataSetSearch(this, - "ir.actions.act_window",this.session.context,[]) - .read_slice(['help'], - { domain: - [ - ['res_model','=',this.process_action_model], - ['name','ilike', this.process_action_name] - ] - }, - function(res) { - if (res.length) { - self.process_help = res[0]['help'] || 'Help: Not Defined'; + var is_ready = $.Deferred(); + $.when(this.fields_get(), this.help(), this.get_process_object()).pipe(function(fields, help, process) { + self.process_fields = fields; + self.process_help = help; + if(process && process.length) { + if(process.length > 1) { + self.process_selection = process; + } else { + self.process_id = process[0][0]; } - $.when(self.load_process()).then(self.render_process_view()); - + } + return $.Deferred().resolve(); + }).done(function() { + self.render_process_view(); + }).done(function() { + if(self.process_id) { + self.graph_get().done(function(res) { + self.draw_process_graph(res); + }); + } }); + }, - - load_process: function() { + + graph_get: function() { var self = this; + var def = $.Deferred(); + this.process_id = parseInt(this.process_id, 10); + + this.process_dataset + .call("graph_get",[this.process_id, this.model, false, [80,80,150,100]]) + .done(function(res) { + self.process_dataset + .call("search_by_model",[self.model,self.session.context]) + .done( + function(r) { + res['related'] = r; + def.resolve(res); + }); + + }); + return def.promise(); + }, + + fields_get : function() { + var self = this, + def = $.Deferred(), + dataset = new openerp.web.DataSetStatic(this, this.model, this.session.context); + + dataset + .call('fields_get',[]) + .done(function(fields) { + def.resolve(fields); + }).fail(def.reject); + return def.promise(); + }, + + help : function() { + var self = this, + def = $.Deferred(); + if(!this.subflow_model) { + def.resolve(this.action ? this.action.help : 'Help: Not Defined'); + } else { + var dataset = new openerp.web.DataSetSearch(this, "ir.actions.act_window", this.session.context, []); + dataset + .read_slice(['help'], + { + domain: [ + ['res_model', '=', this.subflow_model], + ['name', 'ilike', this.subflow_name] + ] + } + ).done(function(res) { + def.resolve(res && res.records.length ? res.records[0].help : 'Help: Not Defined'); + }); + + } + return def.promise(); + }, + + get_process_object : function() { + var self = this, + def = $.Deferred(); + if(this.process_id) + return def.resolve().promise(); + this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); + this.process_dataset + .call("search_by_model", [self.process_model,self.session.context]) + .done(function(res) { + if (!res.length) { + self.process_model = false; + self.get_process_object().done(def.resolve); + } + else { + def.resolve(res); + } + }) + .fail(def.reject); + return def.promise(); + }, + + render_process_view : function() { this.$element.html(QWeb.render("ProcessView", this)); + var self = this; this.$element.find('#edit_process').click(function() { self.edit_process_view(); }); + + var $parent = this.widget_parent.$element; + $parent.find('#change_process').click(function() { + self.process_selection = false; + self.process_id = $parent.find('#select_process').val(); + self.initialize_process_view(); + }); + + + this.$element.find(".toggle_fields").click(function() { + $(this).children().toggle(); + self.$element.find('.process_fields').toggle(); + + }) }, - edit_process_view: function() { - var self = this; - var action_manager = new openerp.web.ActionManager(this); - var dialog = new openerp.web.Dialog(this, { - width: 800, - height: 600, - buttons : { - Cancel : function() { - $(this).dialog('destroy'); - }, - Save : function() { - var form_view = action_manager.inner_viewmanager.views.form.controller; - - form_view.do_save(function() { - self.process_renderer([[self.process_id]]); - }); - $(this).dialog('destroy'); - } - } - }).start().open(); + draw_process_graph : function(res) { + var self = this, + process_graph = new Graph(); - action_manager.appendTo(dialog.$element); - action_manager.do_action({ - res_model : 'process.process', - res_id: self.process_id, - views : [[false, 'form']], - type : 'ir.actions.act_window', - auto_search : false, - flags : { - search_view: false, - sidebar : false, - views_switcher : false, - action_buttons : false, - pager: false - } - }); - }, - - get_process_id: function() { - var self = this; - this.process_dataset = new openerp.web.DataSetStatic(this, "process.process", this.session.context); - this.process_dataset.call("search_by_model", - [self.process_model,self.session.context], - function(res) {self.process_renderer(res)}); - }, - process_renderer: function(res) { - var self = this; - if(!res.length) { - this.process_model = false; - this.get_process_id(); - } else { - if(res.length > 1) { - this.selection = res; - $.when(this.load_process()).then(function() { - var $parent = self.widget_parent.$element; - $parent.find('#change_process').click(function() { - self.selection = false; - self.process_id = $parent.find('#select_process').val(); - $.when(self.load_process()).then(self.render_process_view()); - }); - }); - } else { - this.process_id = res[0][0]; - $.when(this.load_process()).then(this.render_process_view()); - } - } - }, - - render_process_view: function() { - var self = this; - this.process_id = parseInt(this.process_id, 10); - this.process_dataset.call("graph_get", - [self.process_id, self.model, false, [80,80,150,100]], - function(res) { - res['title'] = res.resource ? res.resource : res.name; - self.process_dataset.call("search_by_model", - [self.model,self.session.context], - function(r) { - res['related'] = r; - }); - self.draw_process_graph(res); - } - ); - }, - draw_process_graph: function(res) { - var self = this; - var process_graph = new Graph(); - var process_renderer = function(r, n) { var process_node, process_node_text, @@ -154,7 +169,6 @@ openerp.web_process = function (openerp) { var bg = "node", clip_rect = "".concat(n.node.x,",",n.node.y,",150,100"); -// text_position_x = n.node.x + (n.node.y/2) //Image part bg = n.node.kind == "subflow" ? "node-subflow" : "node"; @@ -163,7 +177,7 @@ openerp.web_process = function (openerp) { r['image'](img_src, n.node.x, n.node.y,150, 100) .attr({"clip-rect": clip_rect}) - .mousedown(function(){ + .mousedown(function() { return false; }); @@ -176,9 +190,9 @@ openerp.web_process = function (openerp) { if(n.node.subflow) { process_node_text.click(function() { self.process_id = n.node.subflow[0]; - self.process_action_model = n.node.model; - self.process_action_name = n.node.name; - self.process_subflow(); + self.subflow_model = n.node.model; + self.subflow_name = n.node.name; + self.initialize_process_view(); }); } @@ -187,7 +201,7 @@ openerp.web_process = function (openerp) { if(n.node.notes.length > 25) { var new_notes= temp_str = ''; var from = to = 0; - while (1){ + while (1) { from = 25; temp_str = n.node.notes.substr(to ,25); if (temp_str.lastIndexOf(" ") < 25 && temp_str.length >= 25) { @@ -214,12 +228,12 @@ openerp.web_process = function (openerp) { } process_set = r.set().push(process_node); - process_set.mousedown(function() { + process_set.mousedown(function() { return false; }); return process_set; }; - + _.each(res['nodes'],function(node, node_id) { node['res_model'] = self.model, node['res_id'] = false, @@ -238,7 +252,7 @@ openerp.web_process = function (openerp) { var layouter = new Graph.Layout.Ordered(process_graph); var render_process_graph = new Graph.Renderer.Raphael('process_canvas', process_graph, $('#process_canvas').width(), $('#process_canvas').height()); }, - + jump_to_view: function(model, id) { var self = this; var dataset = new openerp.web.DataSetStatic(this, 'ir.values', this.session.context); @@ -256,7 +270,45 @@ openerp.web_process = function (openerp) { action_manager.do_action(result.result); }); }); - } + }, + + edit_process_view: function() { + var self = this; + var action_manager = new openerp.web.ActionManager(this); + var dialog = new openerp.web.Dialog(this, { + width: 800, + height: 600, + buttons : { + Cancel : function() { + $(this).dialog('destroy'); + }, + Save : function() { + var form_view = action_manager.inner_viewmanager.views.form.controller; + + form_view.do_save(function() { + self.initialize_process_view(); + }); + $(this).dialog('destroy'); + } + } + }).start().open(); + + action_manager.appendTo(dialog.$element); + action_manager.do_action({ + res_model : 'process.process', + res_id: self.process_id, + views : [[false, 'form']], + type : 'ir.actions.act_window', + auto_search : false, + flags : { + search_view: false, + sidebar : false, + views_switcher : false, + action_buttons : false, + pager: false + } + }); + }, }); }; diff --git a/addons/web_process/static/src/xml/web_process.xml b/addons/web_process/static/src/xml/web_process.xml index 29ccc623d87..5ac2c587701 100644 --- a/addons/web_process/static/src/xml/web_process.xml +++ b/addons/web_process/static/src/xml/web_process.xml @@ -44,14 +44,14 @@

- +
Select Process