From cfbb548717f23eb09e96f685085c412a6bd3b498 Mon Sep 17 00:00:00 2001 From: "Nimesh (Open ERP)" Date: Wed, 3 Oct 2012 15:57:18 +0530 Subject: [PATCH 1/6] [ADD] add suptype in task of the related project. bzr revid: nco@tinyerp.com-20121003102718-vycgkv7y4odup01q --- addons/project/project.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/addons/project/project.py b/addons/project/project.py index 6b02a018293..5d0a665deea 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -1097,7 +1097,16 @@ class task(base_stage, osv.osv): def create(self, cr, uid, vals, context=None): task_id = super(task, self).create(cr, uid, vals, context=context) task_record = self.browse(cr, uid, task_id, context=context) + project_obj = self.pool.get("project.project") + subtype_obj = self.pool.get('mail.message.subtype') if task_record.project_id: + poject_id = self.browse(cr, uid, task_id, context=context).project_id.id + pro_subtype = project_obj.browse(cr, uid, poject_id, context=context).message_subtype_data + for key in pro_subtype: + subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', '=', key)], context=context) + if subtype_ids: + for subtype_id in subtype_ids: + subtype_obj.write(cr,uid, subtype_id, {'default': pro_subtype[key]['default']},context=context) project_follower_ids = [follower.id for follower in task_record.project_id.message_follower_ids] self.message_subscribe(cr, uid, [task_id], project_follower_ids, context=context) @@ -1110,9 +1119,17 @@ class task(base_stage, osv.osv): def write(self, cr, uid, ids, vals, context=None): if isinstance(ids, (int, long)): ids = [ids] + project_obj = self.pool.get("project.project") + subtype_obj = self.pool.get('mail.message.subtype') if vals.get('project_id'): project_id = self.pool.get('project.project').browse(cr, uid, vals.get('project_id'), context=context) vals['message_follower_ids'] = [(4, follower.id) for follower in project_id.message_follower_ids] + pro_subtype = project_obj.browse(cr, uid, project_id.id, context=context).message_subtype_data + for key in pro_subtype: + subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', '=', key)], context=context) + if subtype_ids: + for subtype_id in subtype_ids: + subtype_obj.write(cr,uid, subtype_id, {'default': pro_subtype[key]['default']},context=context) if vals and not 'kanban_state' in vals and 'stage_id' in vals: new_stage = vals.get('stage_id') vals_reset_kstate = dict(vals, kanban_state='normal') From 74cfb3db106da08342e2ce2449311659d0623ee7 Mon Sep 17 00:00:00 2001 From: "Atul Patel (OpenERP)" Date: Wed, 3 Oct 2012 23:34:17 +0530 Subject: [PATCH 2/6] [IMP]: Improve subtype state mapping in project bzr revid: atp@tinyerp.com-20121003180417-wi7jy1veyj5fxygl --- addons/project/project.py | 3 ++- addons/project_issue/project_issue.py | 25 ++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/addons/project/project.py b/addons/project/project.py index 587da5623e4..22d24660010 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -1099,6 +1099,7 @@ class task(base_stage, osv.osv): task_record = self.browse(cr, uid, task_id, context=context) project_obj = self.pool.get("project.project") subtype_obj = self.pool.get('mail.message.subtype') + subtype_ids = [] if task_record.project_id: project_subtype = task_record.project_id.message_subtype_data for key in project_subtype: @@ -1106,7 +1107,7 @@ class task(base_stage, osv.osv): if subtype_ids: subtype_obj.write(cr,uid, subtype_ids, {'default': project_subtype[key]['default']},context=context) project_follower_ids = [follower.id for follower in task_record.project_id.message_follower_ids] - self.message_subscribe(cr, uid, [task_id], project_follower_ids, + self.message_subscribe(cr, uid, [task_id], project_follower_ids, subtype_ids = subtype_ids, context=context) self._store_history(cr, uid, [task_id], context=context) self.create_send_note(cr, uid, [task_id], context=context) diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index c3d5f647d8d..2c8d5f8c529 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -363,14 +363,18 @@ class project_issue(base_stage, osv.osv): #Update last action date every time the user change the stage, the state or send a new email logged_fields = ['stage_id', 'state', 'message_ids'] subtype_obj = self.pool.get('mail.message.subtype') + name = False if any([field in vals for field in logged_fields]): vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S') if vals.get('project_id'): project_id = self.pool.get('project.project').browse(cr, uid, vals.get('project_id'), context=context) for key in project_id.message_subtype_data: - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', '=', key)], context=context) - if subtype_ids: - subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) + if key == 'New Task' and project_id.message_subtype_data[key]['default'] == True: + name = 'created' + if key == 'Task Closed' and project_id.message_subtype_data[key]['default'] == True: + name = 'closed' + subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', name)], context=context) + subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) vals['message_follower_ids'] = [(4, follower.id) for follower in project_id.message_follower_ids] return super(project_issue, self).write(cr, uid, ids, vals, context) @@ -392,14 +396,17 @@ class project_issue(base_stage, osv.osv): subtype_obj = self.pool.get('mail.message.subtype') obj_id = super(project_issue, self).create(cr, uid, vals, context=context) project_id = self.browse(cr, uid, obj_id, context=context).project_id - project_subtype = project_id.message_subtype_data - for key in project_subtype: - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', key)], context=context) - if subtype_ids: - subtype_obj.write(cr,uid, subtype_ids, {'default': project_subtype[key]['default']},context=context) + name = False if project_id: + for key in project_id.message_subtype_data: + if key == 'New Task' and project_id.message_subtype_data[key]['default'] == True: + name = 'created' + if key == 'Task Closed' and project_id.message_subtype_data[key]['default'] == True: + name = 'closed' + subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', name)], context=context) + subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) followers = [follower.id for follower in project_id.message_follower_ids] - self.message_subscribe(cr, uid, [obj_id], followers, context=context) + self.message_subscribe(cr, uid, [obj_id], followers, subtype_ids= subtype_ids, context=context) self.create_send_note(cr, uid, [obj_id], context=context) return obj_id From d8a67f02f8de6888ac0ece2437b0b8f9656bbdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 2 Nov 2012 16:24:30 +0100 Subject: [PATCH 3/6] [FIX] project: fixed auto-follow for task and cleaned code. Also fixed subtype name and related models, as well as comment, now Discussions. bzr revid: tde@openerp.com-20121102152430-mww1cqcjiluuhtvv --- addons/mail/data/mail_data.xml | 2 +- addons/project/project.py | 50 +++++++++++++++++---------------- addons/project/project_data.xml | 6 ++-- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index 522cbe8c7a7..9b91c519348 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -28,7 +28,7 @@ - comment + Discussions diff --git a/addons/project/project.py b/addons/project/project.py index 59f34fa9599..95348bdede3 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -1129,21 +1129,29 @@ class task(base_stage, osv.osv): }, context=context) return True + def _subscribe_project_followers_to_task(self, cr, uid, task_id, context=None): + # task followers are project followers, with matching subtypes + task_record = self.browse(cr, uid, task_id, context=context) + subtype_obj = self.pool.get('mail.message.subtype') + follower_obj = self.pool.get('mail.followers') + if task_record.project_id: + # create mapping + task_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('res_model', '=', self._name)], context=context) + task_subtypes = subtype_obj.browse(cr, uid, task_subtype_ids, context=context) + # fetch subscriptions + follower_ids = follower_obj.search(cr, uid, [('res_model', '=', 'project.project'), ('res_id', '=', task_record.project_id.id)], context=context) + # copy followers + for follower in follower_obj.browse(cr, uid, follower_ids, context=context): + if not follower.subtype_ids: + continue + project_subtype_names = [project_subtype.name for project_subtype in follower.subtype_ids] + task_subtype_ids = [task_subtype.id for task_subtype in task_subtypes if task_subtype.name in project_subtype_names] + self.message_subscribe(cr, uid, [task_id], [follower.partner_id.id], + subtype_ids=task_subtype_ids, context=context) + def create(self, cr, uid, vals, context=None): task_id = super(task, self).create(cr, uid, vals, context=context) - task_record = self.browse(cr, uid, task_id, context=context) - project_obj = self.pool.get("project.project") - subtype_obj = self.pool.get('mail.message.subtype') - subtype_ids = [] - if task_record.project_id: - project_subtype = task_record.project_id.message_subtype_data - for key in project_subtype: - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', key)], context=context) - if subtype_ids: - subtype_obj.write(cr,uid, subtype_ids, {'default': project_subtype[key]['default']},context=context) - project_follower_ids = [follower.id for follower in task_record.project_id.message_follower_ids] - self.message_subscribe(cr, uid, [task_id], project_follower_ids, subtype_ids = subtype_ids, - context=context) + self._subscribe_project_followers_to_task(cr, uid, task_id, context=context) self._store_history(cr, uid, [task_id], context=context) self.create_send_note(cr, uid, [task_id], context=context) return task_id @@ -1153,15 +1161,6 @@ class task(base_stage, osv.osv): def write(self, cr, uid, ids, vals, context=None): if isinstance(ids, (int, long)): ids = [ids] - project_obj = self.pool.get("project.project") - subtype_obj = self.pool.get('mail.message.subtype') - if vals.get('project_id'): - project_id = project_obj.browse(cr, uid, vals.get('project_id'), context=context) - vals['message_follower_ids'] = [(4, follower.id) for follower in project_id.message_follower_ids] - for key in project_id.message_subtype_data: - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', '=', key)], context=context) - if subtype_ids: - subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) if vals and not 'kanban_state' in vals and 'stage_id' in vals: new_stage = vals.get('stage_id') vals_reset_kstate = dict(vals, kanban_state='normal') @@ -1171,13 +1170,16 @@ class task(base_stage, osv.osv): #if new_stage not in stages: #raise osv.except_osv(_('Warning!'), _('Stage is not defined in the project.')) write_vals = vals_reset_kstate if t.stage_id != new_stage else vals - super(task,self).write(cr, uid, [t.id], write_vals, context=context) + super(task, self).write(cr, uid, [t.id], write_vals, context=context) self.stage_set_send_note(cr, uid, [t.id], new_stage, context=context) result = True else: - result = super(task,self).write(cr, uid, ids, vals, context=context) + result = super(task, self).write(cr, uid, ids, vals, context=context) if ('stage_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals): self._store_history(cr, uid, ids, context=context) + if vals.get('project_id'): + for id in ids: + self._subscribe_project_followers_to_task(cr, uid, id, context=context) return result def unlink(self, cr, uid, ids, context=None): diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml index 560c1c3552a..49c33c8e3a4 100644 --- a/addons/project/project_data.xml +++ b/addons/project/project_data.xml @@ -96,11 +96,11 @@ Task Canceled - project.task + project.project Task Stage Changed - project.task + project.project @@ -112,7 +112,7 @@ project.task - Task canceled + Task Canceled project.task From 3450efc109afd6425bcc5ce805a17b8305bcaaa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 2 Nov 2012 16:41:54 +0100 Subject: [PATCH 4/6] [FIX] project_issue: fixed subtype implementation, about followers of project automatically following issues. Updated subtype names. bzr revid: tde@openerp.com-20121102154154-o8dpil045ub2spbd --- addons/project/project.py | 4 ++ addons/project/project_data.xml | 16 +++--- addons/project_issue/project_issue.py | 56 +++++++++++---------- addons/project_issue/project_issue_data.xml | 18 ++++--- 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/addons/project/project.py b/addons/project/project.py index 95348bdede3..b358616508f 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -1151,7 +1151,9 @@ class task(base_stage, osv.osv): def create(self, cr, uid, vals, context=None): task_id = super(task, self).create(cr, uid, vals, context=context) + # subscribe project followers to the task self._subscribe_project_followers_to_task(cr, uid, task_id, context=context) + self._store_history(cr, uid, [task_id], context=context) self.create_send_note(cr, uid, [task_id], context=context) return task_id @@ -1177,6 +1179,8 @@ class task(base_stage, osv.osv): result = super(task, self).write(cr, uid, ids, vals, context=context) if ('stage_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals): self._store_history(cr, uid, ids, context=context) + + # subscribe new project followers to the task if vals.get('project_id'): for id in ids: self._subscribe_project_followers_to_task(cr, uid, id, context=context) diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml index 49c33c8e3a4..4f467c89a29 100644 --- a/addons/project/project_data.xml +++ b/addons/project/project_data.xml @@ -86,37 +86,37 @@ - New Task + New project.project - Task Closed + Closed project.project - Task Canceled + Canceled project.project - Task Stage Changed + Stage Changed project.project - New Task + New project.task - Task Closed + Closed project.task - Task Canceled + Canceled project.task - Task Stage Changed + Stage Changed project.task diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 88013ad225c..720e6e8c2dd 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -359,31 +359,44 @@ class project_issue(base_stage, osv.osv): return super(project_issue, self).copy(cr, uid, id, default=default, context=context) + def _subscribe_project_followers_to_issue(self, cr, uid, task_id, context=None): + # task followers are project followers, with matching subtypes + task_record = self.browse(cr, uid, task_id, context=context) + subtype_obj = self.pool.get('mail.message.subtype') + follower_obj = self.pool.get('mail.followers') + if task_record.project_id: + # create mapping + task_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('res_model', '=', self._name)], context=context) + task_subtypes = subtype_obj.browse(cr, uid, task_subtype_ids, context=context) + # fetch subscriptions + follower_ids = follower_obj.search(cr, uid, [('res_model', '=', 'project.project'), ('res_id', '=', task_record.project_id.id)], context=context) + # copy followers + for follower in follower_obj.browse(cr, uid, follower_ids, context=context): + if not follower.subtype_ids: + continue + project_subtype_names = [project_subtype.name for project_subtype in follower.subtype_ids] + task_subtype_ids = [task_subtype.id for task_subtype in task_subtypes if task_subtype.name in project_subtype_names] + self.message_subscribe(cr, uid, [task_id], [follower.partner_id.id], + subtype_ids=task_subtype_ids, context=context) + def write(self, cr, uid, ids, vals, context=None): #Update last action date every time the user change the stage, the state or send a new email logged_fields = ['stage_id', 'state', 'message_ids'] - subtype_obj = self.pool.get('mail.message.subtype') - name = False if any([field in vals for field in logged_fields]): vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S') + + # subscribe new project followers to the issue if vals.get('project_id'): - project_id = self.pool.get('project.project').browse(cr, uid, vals.get('project_id'), context=context) - for key in project_id.message_subtype_data: - if key == 'New Task' and project_id.message_subtype_data[key]['default'] == True: - name = 'created' - if key == 'Task Closed' and project_id.message_subtype_data[key]['default'] == True: - name = 'closed' - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', name)], context=context) - subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) - vals['message_follower_ids'] = [(4, follower.id) for follower in project_id.message_follower_ids] + for id in ids: + self._subscribe_project_followers_to_issue(cr, uid, id, context=context) return super(project_issue, self).write(cr, uid, ids, vals, context) def onchange_task_id(self, cr, uid, ids, task_id, context=None): if not task_id: - return {'value':{}} + return {'value': {}} task = self.pool.get('project.task').browse(cr, uid, task_id, context=context) - return {'value':{'user_id': task.user_id.id,}} + return {'value': {'user_id': task.user_id.id, }} def case_reset(self, cr, uid, ids, context=None): """Resets case as draft @@ -393,21 +406,12 @@ class project_issue(base_stage, osv.osv): return res def create(self, cr, uid, vals, context=None): - subtype_obj = self.pool.get('mail.message.subtype') obj_id = super(project_issue, self).create(cr, uid, vals, context=context) - project_id = self.browse(cr, uid, obj_id, context=context).project_id - name = False - if project_id: - for key in project_id.message_subtype_data: - if key == 'New Task' and project_id.message_subtype_data[key]['default'] == True: - name = 'created' - if key == 'Task Closed' and project_id.message_subtype_data[key]['default'] == True: - name = 'closed' - subtype_ids = subtype_obj.search(cr, uid, [('res_model', '=', self._name), ('name', 'ilike', name)], context=context) - subtype_obj.write(cr,uid, subtype_ids, {'default': project_id.message_subtype_data[key]['default']},context=context) - followers = [follower.id for follower in project_id.message_follower_ids] - self.message_subscribe(cr, uid, [obj_id], followers, subtype_ids= subtype_ids, context=context) + + # subscribe project follower to the issue + self._subscribe_project_followers_to_issue(cr, uid, obj_id, context=context) self.create_send_note(cr, uid, [obj_id], context=context) + return obj_id # ------------------------------------------------------- diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml index edd44e52dd2..72f824715a8 100644 --- a/addons/project_issue/project_issue_data.xml +++ b/addons/project_issue/project_issue_data.xml @@ -44,17 +44,19 @@ Access all issues from the top Project menu, and access the issues of a specific - created + New project.issue - - - - stage change - project.issue - - closed + Closed + project.issue + + + Canceled + project.issue + + + Stage Changed project.issue From 0573d1fb4067227cca8f47d6b2d91e716c3b1029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 2 Nov 2012 16:45:48 +0100 Subject: [PATCH 5/6] [FIX] mail: fixed tests, with comment that became Discussions. bzr revid: tde@openerp.com-20121102154548-5ayn6ns89xz54o70 --- addons/mail/tests/test_mail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index 85cfdca578c..6af0aba633c 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -334,8 +334,8 @@ class test_mail(TestMailMockups): # ---------------------------------------- subtype_data = group_pigs._get_subscription_data(None, None)[group_pigs.id]['message_subtype_data'] - self.assertEqual(set(subtype_data.keys()), set(['comment', 'mt_mg_def', 'mt_all_def', 'mt_mg_nodef', 'mt_all_nodef']), 'mail.group available subtypes incorrect') - self.assertFalse(subtype_data['comment']['followed'], 'Admin should not follow comments in pigs') + self.assertEqual(set(subtype_data.keys()), set(['Discussions', 'mt_mg_def', 'mt_all_def', 'mt_mg_nodef', 'mt_all_nodef']), 'mail.group available subtypes incorrect') + self.assertFalse(subtype_data['Discussions']['followed'], 'Admin should not follow Discussions in pigs') self.assertTrue(subtype_data['mt_mg_nodef']['followed'], 'Admin should follow mt_mg_nodef in pigs') self.assertTrue(subtype_data['mt_all_nodef']['followed'], 'Admin should follow mt_all_nodef in pigs') From 93976b33f9897c2f9a8d6aed54fa390070a62eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 2 Nov 2012 17:07:34 +0100 Subject: [PATCH 6/6] [DOC] Added some comments. bzr revid: tde@openerp.com-20121102160734-gbh3iox0zb9hign7 --- addons/project/project.py | 5 +++++ addons/project_issue/project_issue.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/addons/project/project.py b/addons/project/project.py index b358616508f..06d75eae0e9 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -1130,6 +1130,11 @@ class task(base_stage, osv.osv): return True def _subscribe_project_followers_to_task(self, cr, uid, task_id, context=None): + """ TDE note: not the best way to do this, we could override _get_followers + of task, and perform a better mapping of subtypes than a mapping + based on names. + However we will keep this implementation, maybe to be refactored + in 7.1 of future versions. """ # task followers are project followers, with matching subtypes task_record = self.browse(cr, uid, task_id, context=context) subtype_obj = self.pool.get('mail.message.subtype') diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 720e6e8c2dd..90640363906 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -360,6 +360,11 @@ class project_issue(base_stage, osv.osv): context=context) def _subscribe_project_followers_to_issue(self, cr, uid, task_id, context=None): + """ TDE note: not the best way to do this, we could override _get_followers + of issue, and perform a better mapping of subtypes than a mapping + based on names. + However we will keep this implementation, maybe to be refactored + in 7.1 of future versions. """ # task followers are project followers, with matching subtypes task_record = self.browse(cr, uid, task_id, context=context) subtype_obj = self.pool.get('mail.message.subtype')