Followers
Invite others
diff --git a/addons/project/project.py b/addons/project/project.py
index 817258bba07..bcde18df786 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -317,9 +317,7 @@ class project(osv.osv):
task_obj = self.pool.get('project.task')
task_ids = task_obj.search(cr, uid, [('project_id', 'in', ids), ('state', '!=', 'done')])
task_obj.case_cancel(cr, uid, task_ids, context=context)
- self.write(cr, uid, ids, {'state':'cancelled'}, context=context)
- self.set_cancel_send_note(cr, uid, ids, context=context)
- return True
+ return self.write(cr, uid, ids, {'state':'cancelled'}, context=context)
def set_pending(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state':'pending'}, context=context)
@@ -565,9 +563,6 @@ def Project():
def set_pending_send_note(self, cr, uid, ids, context=None):
return self.message_post(cr, uid, ids, body=_("Project is now
pending."), context=context)
- def set_cancel_send_note(self, cr, uid, ids, context=None):
- return self.message_post(cr, uid, ids, body=_("Project has been
canceled."), context=context)
-
def set_close_send_note(self, cr, uid, ids, context=None):
return self.message_post(cr, uid, ids, body=_("Project has been
closed."), context=context)
@@ -993,7 +988,6 @@ class task(base_stage, osv.osv):
self._check_child_task(cr, uid, ids, context=context)
for task in tasks:
self.case_set(cr, uid, [task.id], 'cancelled', {'remaining_hours': 0.0}, context=context)
- self.case_cancel_send_note(cr, uid, [task.id], context=context)
return True
def do_open(self, cr, uid, ids, context=None):
@@ -1085,11 +1079,13 @@ class task(base_stage, osv.osv):
def set_kanban_state_blocked(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'kanban_state': 'blocked'}, context=context)
- return False
+ self.case_block_send_note(cr, uid, ids, context=context)
+ return True
def set_kanban_state_normal(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'kanban_state': 'normal'}, context=context)
- return False
+ self.case_open_send_note(cr, uid, ids, context=context)
+ return True
def set_kanban_state_done(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'kanban_state': 'done'}, context=context)
@@ -1109,35 +1105,12 @@ class task(base_stage, osv.osv):
}, context=context)
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')
- 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)
- # subscribe project followers to the task
- self._subscribe_project_followers_to_task(cr, uid, task_id, context=context)
+ project_id = self.browse(cr, uid, task_id, context=context).project_id
+ if project_id:
+ # subscribe project followers to the task
+ self._subscribe_followers_subtype(cr, uid, [task_id], project_id, 'project.project', context=context)
self._store_history(cr, uid, [task_id], context=context)
return task_id
@@ -1147,6 +1120,11 @@ class task(base_stage, osv.osv):
def write(self, cr, uid, ids, vals, context=None):
if isinstance(ids, (int, long)):
ids = [ids]
+ if vals.get('project_id'):
+ project_id = self.pool.get('project.project').browse(cr, uid, vals.get('project_id'), context=context)
+ if project_id:
+ vals.setdefault('message_follower_ids', [])
+ vals['message_follower_ids'] += [(6, 0,[follower.id]) for follower in project_id.message_follower_ids]
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')
@@ -1165,8 +1143,7 @@ class task(base_stage, osv.osv):
# 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)
+ self._subscribe_followers_subtype(cr, uid, ids, vals.get('project_id'), 'project.project', context=context)
return result
def unlink(self, cr, uid, ids, context=None):
@@ -1266,24 +1243,33 @@ class task(base_stage, osv.osv):
res = super(task, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
return res + ['user_id', 'manager_id']
+ def create_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Task
created."), subtype="project.mt_task_new", context=context)
+
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
return self.message_post(cr, uid, ids, body=_("Stage changed to
%s.") % (stage_name),
context=context)
- def create_send_note(self, cr, uid, ids, context=None):
- return self.message_post(cr, uid, ids, body=_("Task has been
created."), context=context)
+ def case_open_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Task
started."), subtype="project.mt_task_started", context=context)
+
+ def case_close_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Task
closed."), subtype="project.mt_task_closed", context=context)
+
+ def case_block_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Task
blocked."), subtype="project.mt_task_blocked", context=context)
def case_draft_send_note(self, cr, uid, ids, context=None):
- return self.message_post(cr, uid, ids, body=_('Task has been set as
draft.'), context=context)
+ return self.message_post(cr, uid, ids, body=_('Task set as
draft.'), context=context)
def do_delegation_send_note(self, cr, uid, ids, context=None):
for task in self.browse(cr, uid, ids, context=context):
msg = _('Task has been
delegated to
%s.') % (task.user_id.name)
self.message_post(cr, uid, [task.id], body=msg, context=context)
return True
-
+
def project_task_reevaluate(self, cr, uid, ids, context=None):
if self.pool.get('res.users').has_group(cr, uid, 'project.group_time_work_estimation_tasks'):
return {
diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml
index 2fcb49c3894..cde0cdff974 100644
--- a/addons/project/project_data.xml
+++ b/addons/project/project_data.xml
@@ -78,39 +78,42 @@
-
-
- New
+
+
+ Task Created
project.project
-
- Closed
+
+ Task Started
+ project.project
+
+
+
+ Task Blocked
project.project
-
- Canceled
+
+ Task Done
project.project
-
- Stage Changed
- project.project
-
-
+
- New
+ Task Created
+ project.task
+
+
+
+ Task Started
+ project.task
+
+
+
+ Task Blocked
project.task
- Closed
- project.task
-
-
- Canceled
- project.task
-
-
- Stage Changed
+ Task Done
project.task
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 499ebc3e2c5..587faf295a1 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -115,7 +115,7 @@
-
+
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index e256f263caf..26d58928907 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -233,6 +233,12 @@ class project_issue(base_stage, osv.osv):
When the case is over, the status is set to \'Done\'.\
If the case needs to be reviewed then the status is \
set to \'Pending\'.'),
+ 'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready for next stage')], 'Kanban State',
+ help="A Issue's kanban state indicates special situations affecting it:\n"
+ " * Normal is the default situation\n"
+ " * Blocked indicates something is preventing the progress of this issue\n"
+ " * Ready for next stage indicates the issue is ready to be pulled to the next stage",
+ readonly=True, required=False),
'email_from': fields.char('Email', size=128, help="These people will receive email.", select=1),
'email_cc': fields.char('Watchers Emails', size=256, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
'date_open': fields.datetime('Opened', readonly=True,select=True),
@@ -279,6 +285,7 @@ class project_issue(base_stage, osv.osv):
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': crm.AVAILABLE_PRIORITIES[2][0],
+ 'kanban_state': 'normal',
}
_group_by_full = {
@@ -359,31 +366,6 @@ 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):
- """ 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')
- 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']
@@ -392,11 +374,14 @@ class project_issue(base_stage, osv.osv):
# subscribe new project followers to the issue
if vals.get('project_id'):
- 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)
-
+ project_id = self.pool.get('project.project').browse(cr, uid, vals.get('project_id'), context=context)
+ vals.setdefault('message_follower_ids', [])
+ vals['message_follower_ids'] += [(6, 0,[follower.id]) for follower in project_id.message_follower_ids]
+ res = super(project_issue, self).write(cr, uid, ids, vals, context)
+ if vals.get('project_id'):
+ self._subscribe_followers_subtype(cr, uid, ids, vals.get('project_id'), 'project.project', context=context)
+ return res
+
def onchange_task_id(self, cr, uid, ids, task_id, context=None):
if not task_id:
return {'value': {}}
@@ -413,8 +398,10 @@ class project_issue(base_stage, osv.osv):
def create(self, cr, uid, vals, context=None):
obj_id = super(project_issue, self).create(cr, uid, vals, context=context)
- # subscribe project follower to the issue
- self._subscribe_project_followers_to_issue(cr, uid, obj_id, context=context)
+ project_id = self.browse(cr, uid, obj_id, context=context).project_id
+ if project_id:
+ # subscribe project follower to the issue
+ self._subscribe_followers_subtype(cr, uid, [obj_id], project_id, 'project.project', context=context)
self.create_send_note(cr, uid, [obj_id], context=context)
return obj_id
@@ -455,7 +442,6 @@ class project_issue(base_stage, osv.osv):
def case_cancel(self, cr, uid, ids, context=None):
""" Cancels case """
self.case_set(cr, uid, ids, 'cancelled', {'active': True}, context=context)
- self.case_cancel_send_note(cr, uid, ids, context=context)
return True
def case_escalate(self, cr, uid, ids, context=None):
@@ -536,7 +522,7 @@ class project_issue(base_stage, osv.osv):
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
- return self.message_post(cr, uid, ids, body= _("Stage changed to %s.") % (stage_name), subtype="mt_issue_new", context=context)
+ return self.message_post(cr, uid, ids, body=_("Stage changed to %s.") % (stage_name), context=context)
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
""" Override of default prefix for notifications. """
@@ -548,7 +534,10 @@ class project_issue(base_stage, osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
message = _("Project issue created.")
- return self.message_post(cr, uid, ids, body=message, subtype="mt_issue_new", context=context)
+ return self.message_post(cr, uid, ids, body=message, subtype="project_issue.mt_issue_new", context=context)
+
+ def case_open_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Issue started."), subtype="project_issue.mt_issue_started", context=context)
def case_escalate_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
@@ -560,6 +549,25 @@ class project_issue(base_stage, osv.osv):
obj.message_post(body=message)
return True
+ def case_block_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Issue blocked."), subtype="project_issue.mt_issue_blocked", context=context)
+
+ def case_close_send_note(self, cr, uid, ids, context=None):
+ return self.message_post(cr, uid, ids, body=_("Project issue closed."), subtype="project_issue.mt_issue_closed", context=context)
+
+ def set_kanban_state_blocked(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'kanban_state': 'blocked'}, context=context)
+ self.case_block_send_note(cr, uid, ids, context=context)
+ return True
+
+ def set_kanban_state_normal(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'kanban_state': 'normal'}, context=context)
+ self.case_open_send_note(cr, uid, ids, context=context)
+ return True
+
+ def set_kanban_state_done(self, cr, uid, ids, context=None):
+ self.write(cr, uid, ids, {'kanban_state': 'done'}, context=context)
+ return False
project_issue()
class project(osv.osv):
diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml
index c1460167097..395f81e3c3a 100644
--- a/addons/project_issue/project_issue_data.xml
+++ b/addons/project_issue/project_issue_data.xml
@@ -43,23 +43,46 @@ You can record issues, assign them to a responsible person, and keep track of th
Access all issues from the top Project menu, and access the issues of a specific project via the projects gallery view.]]>
-
-
- New
+
+
+ Issue Created
+ project.issue
+
+
+
+ Issue Started
+ project.issue
+
+
+
+ Issue Blocked
+ project.issue
+
+
+
+ Issue Closed
project.issue
-
- Closed
- project.issue
+
+
+ Issue Created
+ project.project
+
-
- Canceled
- project.issue
+
+ Issue Started
+ project.project
+
-
- Stage Changed
- project.issue
+
+ Issue Blocked
+ project.project
+
-
+
+ Issue Closed
+ project.project
+
+
diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml
index 279fec28411..bb7bca59c51 100644
--- a/addons/project_issue/project_issue_view.xml
+++ b/addons/project_issue/project_issue_view.xml
@@ -203,6 +203,7 @@
+