diff --git a/addons/calendar/views/mail_activity_views.xml b/addons/calendar/views/mail_activity_views.xml index 53be74a3b91..d3681be20b1 100644 --- a/addons/calendar/views/mail_activity_views.xml +++ b/addons/calendar/views/mail_activity_views.xml @@ -16,7 +16,7 @@ {'invisible': ['|', ('activity_category', '=', 'meeting'), ('id', '!=', False)]} - {'invisible': ['|', ('activity_category', '=', 'meeting'), ('force_next', '=', True)]} + {'invisible': ['|', ('activity_category', '=', 'meeting'), ('chaining_type', '=', 'trigger')]} {'invisible': [('activity_category', '=', 'meeting')]} diff --git a/addons/mail/__manifest__.py b/addons/mail/__manifest__.py index 1703b1b1eb0..ad131dc15f3 100644 --- a/addons/mail/__manifest__.py +++ b/addons/mail/__manifest__.py @@ -2,7 +2,7 @@ { 'name': 'Discuss', - 'version': '1.2', + 'version': '1.3', 'category': 'Productivity/Discuss', 'sequence': 145, 'summary': 'Chat, mail gateway and private channels', diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index 6b8fdfb280b..a65777a5a4e 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -40,7 +40,7 @@ class MailActivityType(models.Model): active = fields.Boolean(default=True) create_uid = fields.Many2one('res.users', index=True) delay_count = fields.Integer( - 'Scheduled Date', default=0, + 'Schedule', default=0, help='Number of days/week/month before executing the action. It allows to plan the action deadline.') delay_unit = fields.Selection([ ('days', 'days'), @@ -48,7 +48,7 @@ class MailActivityType(models.Model): ('months', 'months')], string="Delay units", help="Unit of delay", required=True, default='days') delay_label = fields.Char(compute='_compute_delay_label') delay_from = fields.Selection([ - ('current_date', 'after validation date'), + ('current_date', 'after completion date'), ('previous_activity', 'after previous activity deadline')], string="Delay Type", help="Type of delay", required=True, default='previous_activity') icon = fields.Char('Icon', help="Font awesome icon e.g. fa-tasks") decoration_type = fields.Selection([ @@ -60,24 +60,30 @@ class MailActivityType(models.Model): domain=['&', ('is_mail_thread', '=', True), ('transient', '=', False)], help='Specify a model if the activity should be specific to a model' ' and not available when managing activities for other models.') - default_next_type_id = fields.Many2one('mail.activity.type', 'Default Next Activity', - domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", ondelete='restrict') - force_next = fields.Boolean("Trigger Next Activity", default=False) - next_type_ids = fields.Many2many( - 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id', + triggered_next_type_id = fields.Many2one( + 'mail.activity.type', string='Trigger', compute='_compute_triggered_next_type_id', + inverse='_inverse_triggered_next_type_id', store=True, readonly=False, + domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", ondelete='restrict', + help="Automatically schedule this activity once the current one is marked as done.") + chaining_type = fields.Selection([ + ('suggest', 'Suggest Next Activity'), ('trigger', 'Trigger Next Activity') + ], string="Chaining Type", required=True, default="suggest") + suggested_next_type_ids = fields.Many2many( + 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id', string='Suggest', domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", - string='Recommended Next Activities') + compute='_compute_suggested_next_type_ids', inverse='_inverse_suggested_next_type_ids', store=True, readonly=False, + help="Suggest these activities once the current one is marked as done.") previous_type_ids = fields.Many2many( 'mail.activity.type', 'mail_activity_rel', 'recommended_id', 'activity_id', domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", string='Preceding Activities') category = fields.Selection([ ('default', 'None'), ('upload_file', 'Upload Document') - ], default='default', string='Action to Perform', + ], default='default', string='Action', help='Actions may trigger specific behavior like opening calendar view or automatically mark as done when a document is uploaded') mail_template_ids = fields.Many2many('mail.template', string='Email templates') default_user_id = fields.Many2one("res.users", string="Default User") - default_description = fields.Html(string="Default Description", translate=True) + default_note = fields.Html(string="Default Note", translate=True) #Fields for display purpose only initial_res_model_id = fields.Many2one('ir.model', 'Initial model', compute="_compute_initial_res_model_id", store=False, @@ -101,6 +107,32 @@ class MailActivityType(models.Model): unit = selection_description_values[activity_type.delay_unit] activity_type.delay_label = '%s %s' % (activity_type.delay_count, unit) + @api.depends('chaining_type') + def _compute_suggested_next_type_ids(self): + """suggested_next_type_ids and triggered_next_type_id should be mutually exclusive""" + for activity_type in self: + if activity_type.chaining_type == 'trigger': + activity_type.suggested_next_type_ids = False + + def _inverse_suggested_next_type_ids(self): + for activity_type in self: + if activity_type.suggested_next_type_ids: + activity_type.chaining_type = 'suggest' + + @api.depends('chaining_type') + def _compute_triggered_next_type_id(self): + """suggested_next_type_ids and triggered_next_type_id should be mutually exclusive""" + for activity_type in self: + if activity_type.chaining_type == 'suggest': + activity_type.triggered_next_type_id = False + + def _inverse_triggered_next_type_id(self): + for activity_type in self: + if activity_type.triggered_next_type_id: + activity_type.chaining_type = 'trigger' + else: + activity_type.chaining_type = 'suggest' + class MailActivity(models.Model): """ An actual activity to perform. Activities are linked to @@ -179,20 +211,20 @@ class MailActivity(models.Model): compute='_compute_has_recommended_activities', help='Technical field for UX purpose') mail_template_ids = fields.Many2many(related='activity_type_id.mail_template_ids', readonly=True) - force_next = fields.Boolean(related='activity_type_id.force_next', readonly=True) + chaining_type = fields.Selection(related='activity_type_id.chaining_type', readonly=True) # access can_write = fields.Boolean(compute='_compute_can_write', help='Technical field to hide buttons if the current user has no access.') @api.onchange('previous_activity_type_id') def _compute_has_recommended_activities(self): for record in self: - record.has_recommended_activities = bool(record.previous_activity_type_id.next_type_ids) + record.has_recommended_activities = bool(record.previous_activity_type_id.suggested_next_type_ids) @api.onchange('previous_activity_type_id') def _onchange_previous_activity_type_id(self): for record in self: - if record.previous_activity_type_id.default_next_type_id: - record.activity_type_id = record.previous_activity_type_id.default_next_type_id + if record.previous_activity_type_id.triggered_next_type_id: + record.activity_type_id = record.previous_activity_type_id.triggered_next_type_id @api.depends('res_model', 'res_id') def _compute_res_name(self): @@ -237,8 +269,8 @@ class MailActivity(models.Model): self.summary = self.activity_type_id.summary self.date_deadline = self._calculate_date_deadline(self.activity_type_id) self.user_id = self.activity_type_id.default_user_id or self.env.user - if self.activity_type_id.default_description: - self.note = self.activity_type_id.default_description + if self.activity_type_id.default_note: + self.note = self.activity_type_id.default_note def _calculate_date_deadline(self, activity_type): # Date.context_today is correct because date_deadline is a Date and is meant to be @@ -521,7 +553,7 @@ class MailActivity(models.Model): for activity in self: # extract value to generate next activities - if activity.force_next: + if activity.chaining_type == 'trigger': Activity = self.env['mail.activity'].with_context(activity_previous_deadline=activity.date_deadline) # context key is required in the onchange to set deadline vals = Activity.default_get(Activity.fields_get()) @@ -929,7 +961,7 @@ class MailActivityMixin(models.AbstractModel): 'activity_type_id': activity_type and activity_type.id, 'summary': summary or activity_type.summary, 'automated': True, - 'note': note or activity_type.default_description, + 'note': note or activity_type.default_note, 'date_deadline': date_deadline, 'res_model_id': model_id, 'res_id': record.id, diff --git a/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover.xml b/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover.xml index 357ab59baeb..ba645cd545e 100644 --- a/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover.xml +++ b/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover.xml @@ -7,7 +7,7 @@ - + Done diff --git a/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover_tests.js b/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover_tests.js index 0c019b2b3c4..5f108735127 100644 --- a/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover_tests.js +++ b/addons/mail/static/src/components/activity_mark_done_popover/activity_mark_done_popover_tests.js @@ -93,7 +93,7 @@ QUnit.test('activity with force next mark done popover simplest layout', async f const activity = this.env.models['mail.activity'].create({ canWrite: true, category: 'not_upload_file', - force_next: true, + chaining_type: 'trigger', id: 12, thread: [['insert', { id: 42, model: 'res.partner' }]], }); diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js index ae9d914f0f7..c6f90f6f1b4 100644 --- a/addons/mail/static/src/js/activity.js +++ b/addons/mail/static/src/js/activity.js @@ -339,7 +339,7 @@ var BasicActivity = AbstractField.extend({ var $markDoneBtn = $(ev.currentTarget); var activityID = $markDoneBtn.data('activity-id'); var previousActivityTypeID = $markDoneBtn.data('previous-activity-type-id') || false; - var forceNextActivity = $markDoneBtn.data('force-next-activity'); + var chainingTypeActivity = $markDoneBtn.data('chaining-type-activity'); if ($markDoneBtn.data('toggle') === 'collapse') { var $actLi = $markDoneBtn.parents('.o_log_activity'); @@ -348,7 +348,7 @@ var BasicActivity = AbstractField.extend({ if (!$panel.data('bs.collapse')) { var $form = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, - force_next: forceNextActivity + chaining_type: chainingTypeActivity })); $panel.append($form); self._onMarkActivityDoneActions($markDoneBtn, $form, activityID); @@ -388,7 +388,7 @@ var BasicActivity = AbstractField.extend({ content: function () { var $popover = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID, - force_next: forceNextActivity + chaining_type: chainingTypeActivity })); self._onMarkActivityDoneActions($markDoneBtn, $popover, activityID); return $popover; diff --git a/addons/mail/static/src/models/activity/activity.js b/addons/mail/static/src/models/activity/activity.js index 8ee51e9711d..5454ba6cb06 100644 --- a/addons/mail/static/src/models/activity/activity.js +++ b/addons/mail/static/src/models/activity/activity.js @@ -49,8 +49,8 @@ function factory(dependencies) { if ('date_deadline' in data) { data2.dateDeadline = data.date_deadline; } - if ('force_next' in data) { - data2.force_next = data.force_next; + if ('chaining_type' in data) { + data2.chaining_type = data.chaining_type; } if ('icon' in data) { data2.icon = data.icon; @@ -289,8 +289,8 @@ function factory(dependencies) { * In all other cases, this field value should not be trusted. */ feedbackBackup: attr(), - force_next: attr({ - default: false, + chaining_type: attr({ + default: 'suggest', }), icon: attr(), id: attr({ diff --git a/addons/mail/static/src/xml/activity.xml b/addons/mail/static/src/xml/activity.xml index 487eb2101fe..feca1c10867 100644 --- a/addons/mail/static/src/xml/activity.xml +++ b/addons/mail/static/src/xml/activity.xml @@ -84,11 +84,11 @@ - + Mark Done - + Upload Document @@ -112,7 +112,7 @@ - + Done & Schedule Next diff --git a/addons/mail/static/src/xml/web_kanban_activity.xml b/addons/mail/static/src/xml/web_kanban_activity.xml index e6d82e3773f..c73229f85b5 100644 --- a/addons/mail/static/src/xml/web_kanban_activity.xml +++ b/addons/mail/static/src/xml/web_kanban_activity.xml @@ -39,7 +39,7 @@ - + @@ -61,10 +61,10 @@ - + - + @@ -72,7 +72,7 @@ - + @@ -85,7 +85,7 @@ - - - - + + - + @@ -23,11 +23,13 @@ - - - - + + + + - - + + + - - - - - + + Modifying the model can have an impact on existing activities using this activity type, be careful. @@ -104,7 +104,7 @@ - + @@ -133,13 +133,13 @@ attrs="{'invisible': [('id', '!=', False)]}"/> - - -
Modifying the model can have an impact on existing activities using this activity type, be careful.