diff --git a/addons/crm/data/mail_activity_demo.xml b/addons/crm/data/mail_activity_demo.xml index d18dd3a0e0c..4dad17022ff 100644 --- a/addons/crm/data/mail_activity_demo.xml +++ b/addons/crm/data/mail_activity_demo.xml @@ -4,18 +4,18 @@ Follow-up Quote fa-file-text-o - 30 + 30 Make Quote fa-file-text-o - 15 + 15 Call for Demo fa-phone - 10 + 10 diff --git a/addons/crm/tests/test_crm_activity.py b/addons/crm/tests/test_crm_activity.py index d3d847612d4..3bb9bae9a48 100644 --- a/addons/crm/tests/test_crm_activity.py +++ b/addons/crm/tests/test_crm_activity.py @@ -15,19 +15,19 @@ class TestCrmMailActivity(TestCrmCases): ActivityType = self.env['mail.activity.type'] self.activity3 = ActivityType.create({ 'name': 'Celebrate the sale', - 'days': 3, + 'delay_count': 3, 'summary': 'ACT 3 : Beers for everyone because I am a good salesman !', 'res_model_id': lead_model_id, }) self.activity2 = ActivityType.create({ 'name': 'Call for Demo', - 'days': 6, + 'delay_count': 6, 'summary': 'ACT 2 : I want to show you my ERP !', 'res_model_id': lead_model_id, }) self.activity1 = ActivityType.create({ 'name': 'Initial Contact', - 'days': 5, + 'delay_count': 5, 'summary': 'ACT 1 : Presentation, barbecue, ... ', 'res_model_id': lead_model_id, }) diff --git a/addons/mail/data/mail_activity_data.xml b/addons/mail/data/mail_activity_data.xml index f8f1f8b09ca..7309c991b6c 100644 --- a/addons/mail/data/mail_activity_data.xml +++ b/addons/mail/data/mail_activity_data.xml @@ -9,7 +9,7 @@ Call fa-phone - 2 + 2 6 @@ -20,7 +20,7 @@ To Do fa-tasks - 5 + 5 12 diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index dcb60831ef2..fda0b5f88de 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -1,7 +1,9 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from datetime import date, datetime, timedelta +from collections import defaultdict +from datetime import date, datetime +from dateutil.relativedelta import relativedelta import pytz from odoo import api, exceptions, fields, models, _ @@ -29,9 +31,16 @@ class MailActivityType(models.Model): summary = fields.Char('Summary', translate=True) sequence = fields.Integer('Sequence', default=10) active = fields.Boolean(default=True) - days = fields.Integer( - 'Planned in', default=0, - help='Number of days before executing the action. It allows to plan the action deadline.') + delay_count = fields.Integer( + 'After', default=0, oldname='days', + help='Number of days/week/month before executing the action. It allows to plan the action deadline.') + delay_unit = fields.Selection([ + ('days', 'days'), + ('weeks', 'weeks'), + ('months', 'months')], string="Delay units", help="Unit of delay", required=True, default='days') + delay_from = fields.Selection([ + ('current_date', 'after validation 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([ ('warning', 'Alert'), @@ -42,6 +51,8 @@ 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)]") next_type_ids = fields.Many2many( 'mail.activity.type', 'mail_activity_rel', 'activity_id', 'recommended_id', domain="['|', ('res_model_id', '=', False), ('res_model_id', '=', res_model_id)]", @@ -141,6 +152,13 @@ class MailActivity(models.Model): def _compute_has_recommended_activities(self): for record in self: record.has_recommended_activities = bool(record.previous_activity_type_id.next_type_ids) + + @api.multi + @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 @api.depends('res_model', 'res_id') def _compute_res_name(self): @@ -174,7 +192,10 @@ class MailActivity(models.Model): self.summary = self.activity_type_id.summary # Date.context_today is correct because date_deadline is a Date and is meant to be # expressed in user TZ - self.date_deadline = fields.Date.context_today(self) + timedelta(days=self.activity_type_id.days) + base = fields.Date.context_today(self) + if self.activity_type_id.delay_from == 'previous_activity' and 'activity_previous_deadline' in self.env.context: + base = fields.Date.from_string(self.env.context.get('activity_previous_deadline')) + self.date_deadline = base + relativedelta(**{self.activity_type_id.delay_unit: self.activity_type_id.delay_count}) @api.onchange('recommended_activity_type_id') def _onchange_recommended_activity_type_id(self): @@ -336,10 +357,11 @@ class MailActivity(models.Model): return message.ids and message.ids[0] or False @api.multi - def action_done_schedule_next(self): + def action_done_schedule_next(self, feedback=False): wizard_ctx = dict( self.env.context, default_previous_activity_type_id=self.activity_type_id.id, + activity_previous_deadline=self.date_deadline, default_res_id=self.res_id, default_res_model=self.res_model, ) diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js index acd15cbef20..dbff89c76db 100644 --- a/addons/mail/static/src/js/activity.js +++ b/addons/mail/static/src/js/activity.js @@ -132,16 +132,27 @@ var AbstractActivityField = AbstractField.extend({ * @private * @param {Object} params * @param {integer} params.activityID - * @param {integer} params.activityTypeID * @param {string} params.feedback */ _markActivityDoneAndScheduleNext: function(params) { var activityID = params.activityID; - var activityTypeID = params.activityTypeID; var feedback = params.feedback; - - this._sendActivityFeedback(activityID, feedback) - .then(this.scheduleActivity.bind(this, activityTypeID)); + var self = this; + this._rpc({ + model: 'mail.activity', + method: 'action_done_schedule_next', + args: [[activityID]], + kwargs: {feedback: feedback}, + context: this.record.getContext(), + }).then( + function(rslt_action) { + self.do_action(rslt_action, { + on_close: function () { + self.trigger_up('reload'); + }, + }); + } + ); }, /** * @private @@ -410,7 +421,6 @@ var Activity = AbstractActivityField.extend({ $popover.on('click', '.o_activity_popover_done_next', function () { self._markActivityDoneAndScheduleNext({ activityID: activityID, - activityTypeID: $popoverElement.data('previous-activity-type-id'), feedback: _.escape($popover.find('#activity_feedback').val()), }); }); @@ -583,7 +593,6 @@ var KanbanActivity = AbstractActivityField.extend({ ev.stopPropagation(); self._markActivityDoneAndScheduleNext({ activityID: activityID, - activityTypeID: $popoverElement.data('previous-activity-type-id'), feedback: _.escape($popover.find('#activity_feedback').val()), }); }); diff --git a/addons/mail/views/mail_activity_views.xml b/addons/mail/views/mail_activity_views.xml index 6284a4e3d89..7b92502934f 100644 --- a/addons/mail/views/mail_activity_views.xml +++ b/addons/mail/views/mail_activity_views.xml @@ -24,15 +24,17 @@ - diff --git a/addons/product_expiry/data/product_expiry_data.xml b/addons/product_expiry/data/product_expiry_data.xml index ca621cef17e..f0effeaaa77 100644 --- a/addons/product_expiry/data/product_expiry_data.xml +++ b/addons/product_expiry/data/product_expiry_data.xml @@ -9,7 +9,7 @@ default fa-tasks - 0 + 0