From 32c7b1442e012da7c0fbcc9b1bdec7da6afdf3ee Mon Sep 17 00:00:00 2001 From: Kevin Baptiste Date: Mon, 31 Aug 2020 09:15:12 +0000 Subject: [PATCH] [IMP] project: stop recurrence on delete/archive task closes odoo/odoo#57226 Signed-off-by: Yannick Tivisse (yti) --- addons/project/models/project.py | 13 +++ addons/project/static/src/js/project_form.js | 109 ++++++++++++++++++ addons/project/static/src/js/project_list.js | 112 +++++++++++++++++++ addons/project/views/project_assets.xml | 2 + addons/project/views/project_views.xml | 5 +- 5 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 addons/project/static/src/js/project_form.js create mode 100644 addons/project/static/src/js/project_list.js diff --git a/addons/project/models/project.py b/addons/project/models/project.py index ef936b96576..37897a835a6 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -1379,6 +1379,10 @@ class Task(models.Model): return action + # ------------ + # Actions + # ------------ + def action_recurring_tasks(self): return { 'name': 'Tasks in Recurrence', @@ -1388,6 +1392,15 @@ class Task(models.Model): 'domain': [('recurrence_id', 'in', self.recurrence_id.ids)], } + def action_stop_recurrence(self): + tasks = self.env['project.task'].with_context(active_test=False).search([('recurrence_id', 'in', self.recurrence_id.ids)]) + tasks.write({'recurring_task': False}) + self.recurrence_id.unlink() + + def action_continue_recurrence(self): + self.recurrence_id = False + self.recurring_task = False + # --------------------------------------------------- # Rating business # --------------------------------------------------- diff --git a/addons/project/static/src/js/project_form.js b/addons/project/static/src/js/project_form.js new file mode 100644 index 00000000000..9d82d876793 --- /dev/null +++ b/addons/project/static/src/js/project_form.js @@ -0,0 +1,109 @@ +odoo.define('project.ProjectFormView', function (require) { + "use strict"; + + const Dialog = require('web.Dialog'); + const FormView = require('web.FormView'); + const FormController = require('web.FormController'); + const core = require('web.core'); + const view_registry = require('web.view_registry'); + + const _t = core._t; + + const ProjectFormController = FormController.extend({ + _getActionMenuItems(state) { + if (!this.archiveEnabled || !state.data['recurrence_id']) { + return this._super(...arguments); + } + + this.archiveEnabled = false; + let actions = this._super(...arguments); + this.archiveEnabled = true; + + if (actions) { + const activeField = this.model.getActiveField(state); + actions.items.other.unshift({ + description: state.data[activeField] ? _t('Archive') : _t('Unarchive'), + callback: () => this._stopRecurrence(state.data['id'], state.data[activeField]?'archive':'unarchive'), + }); + } + + return actions; + }, + + _onDeleteRecord() { + const record = this.model.get(this.handle); + + if(!record.data.recurrence_id) { + return this._super(...arguments); + } + this._stopRecurrence(record.res_id, 'delete'); + }, + + _stopRecurrence(res_id, mode) { + new Dialog(this, { + buttons: [ + { + classes: 'btn-primary', + click: () => { + this._rpc({ + model: 'project.task', + method: 'action_stop_recurrence', + args: [res_id], + }).then(() => { + if (mode === 'archive') { + this._toggleArchiveState(true); + } else if (mode === 'unarchive') { + this._toggleArchiveState(false); + } else if (mode === 'delete') { + this._deleteRecords([this.handle]); + } + }); + }, + close: true, + text: _t('Stop Recurrence'), + }, + { + click: () => { + this._rpc({ + model: 'project.task', + method: 'action_continue_recurrence', + args: [res_id], + }).then(() => { + if (mode === 'archive') { + this._toggleArchiveState(true); + } else if (mode === 'unarchive') { + this._toggleArchiveState(false); + } else if (mode === 'delete') { + this._deleteRecords([this.handle]); + } + }); + }, + close: true, + text: _t('Continue Recurrence'), + }, + { + close: true, + text: _t('Discard'), + } + ], + size: 'medium', + title: _t('Confirmation'), + $content: $('
', { + role: 'alert', + text: _t('It seems that this task is part of a recurrence.'), + }), + }).open(); + } + + }); + + const ProjectFormView = FormView.extend({ + config: _.extend({}, FormView.prototype.config, { + Controller: ProjectFormController, + }), + }); + + view_registry.add('project_form', ProjectFormView); + + return ProjectFormView; +}); diff --git a/addons/project/static/src/js/project_list.js b/addons/project/static/src/js/project_list.js new file mode 100644 index 00000000000..48be808876d --- /dev/null +++ b/addons/project/static/src/js/project_list.js @@ -0,0 +1,112 @@ +odoo.define('project.ProjectListView', function (require) { + "use strict"; + + const Dialog = require('web.Dialog'); + const ListView = require('web.ListView'); + const ListController = require('web.ListController'); + const core = require('web.core'); + const view_registry = require('web.view_registry'); + + const _t = core._t; + + const ProjectListController = ListController.extend({ + _getActionMenuItems(state) { + if(!this.archiveEnabled) { + return this._super(...arguments); + } + + const recurringRecords = this.getSelectedRecords().filter(rec => rec.data.recurrence_id).map(rec => rec.data.id); + this.archiveEnabled = recurringRecords.length == 0; + let actions = this._super(...arguments); + this.archiveEnabled = true; + + if(actions && recurringRecords.length > 0) { + actions.items.other.unshift({ + description: _t('Archive'), + callback: () => this._stopRecurrence(recurringRecords, this.selectedRecords, 'archive'), + }, { + description: _t('Unarchive'), + callback: () => this._toggleArchiveState(false) + }); + } + return actions; + }, + + _onDeleteSelectedRecords() { + const recurringRecords = this.getSelectedRecords().filter(rec => rec.data.recurrence_id).map(rec => rec.data.id); + if(recurringRecords.length > 0) { + return this._stopRecurrence(recurringRecords, this.selectedRecords, 'delete'); + } + + return this._super(...arguments); + }, + + _stopRecurrence(recurring_res_ids, res_ids, mode) { + let warning; + if (res_ids.length > 1) { + warning = _t('It seems that some tasks are part of a recurrence.'); + } else { + warning = _t('It seems that this task is part of a recurrence.'); + } + return new Dialog(this, { + buttons: [ + { + classes: 'btn-primary', + click: () => { + this._rpc({ + model: 'project.task', + method: 'action_stop_recurrence', + args: [recurring_res_ids], + }).then(() => { + if (mode === 'archive') { + this._toggleArchiveState(true); + } else if (mode === 'delete') { + this._deleteRecords(res_ids); + } + }); + }, + close: true, + text: _t('Stop Recurrence'), + }, + { + click: () => { + this._rpc({ + model: 'project.task', + method: 'action_continue_recurrence', + args: [recurring_res_ids], + }).then(() => { + if (mode === 'archive') { + this._toggleArchiveState(true); + } else if (mode === 'delete') { + this._deleteRecords(res_ids); + } + }); + }, + close: true, + text: _t('Continue Recurrence'), + }, + { + close: true, + text: _t('Discard'), + } + ], + size: 'medium', + title: _t('Confirmation'), + $content: $('
', { + role: 'alert', + text: warning, + }), + }).open(); + } + }); + + const ProjectListView = ListView.extend({ + config: _.extend({}, ListView.prototype.config, { + Controller: ProjectListController, + }), + }); + + view_registry.add('project_list', ProjectListView); + + return ProjectListView; +}); diff --git a/addons/project/views/project_assets.xml b/addons/project/views/project_assets.xml index 4a520675e9d..76c047170b5 100644 --- a/addons/project/views/project_assets.xml +++ b/addons/project/views/project_assets.xml @@ -3,7 +3,9 @@