[IMP] project: stop recurrence on delete/archive task

closes odoo/odoo#57226

Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
Kevin Baptiste
2020-11-17 19:47:38 +00:00
committed by Yannick Tivisse
parent 642bce457c
commit 32c7b1442e
5 changed files with 239 additions and 2 deletions
+13
View File
@@ -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
# ---------------------------------------------------
@@ -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: $('<main/>', {
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;
});
@@ -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: $('<main/>', {
role: 'alert',
text: warning,
}),
}).open();
}
});
const ProjectListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: ProjectListController,
}),
});
view_registry.add('project_list', ProjectListView);
return ProjectListView;
});
+2
View File
@@ -3,7 +3,9 @@
<template id="assets_backend" name="project assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/project/static/src/css/project.css"/>
<script type="text/javascript" src="/project/static/src/js/project_form.js"></script>
<script type="text/javascript" src="/project/static/src/js/project_kanban.js"></script>
<script type="text/javascript" src="/project/static/src/js/project_list.js"></script>
<script type="text/javascript" src="/project/static/src/js/project_rating_reporting.js"></script>
<script type="text/javascript" src="/project/static/src/js/project_task_kanban_examples.js"></script>
<script type="text/javascript" src="/project/static/src/js/tours/project.js"></script>
+3 -2
View File
@@ -614,7 +614,7 @@
<field name="model">project.task</field>
<field eval="2" name="priority"/>
<field name="arch" type="xml">
<form string="Task" class="o_form_project_tasks">
<form string="Task" class="o_form_project_tasks" js_class="project_form">
<field name="allow_subtasks" invisible="1" />
<field name="is_closed" invisible="1" />
<field name="allow_recurring_tasks" invisible="1" />
@@ -909,7 +909,7 @@
<field name="model">project.task</field>
<field eval="2" name="priority"/>
<field name="arch" type="xml">
<tree string="Tasks" multi_edit="1" sample="1">
<tree string="Tasks" multi_edit="1" sample="1" js_class="project_list">
<field name="message_needaction" invisible="1" readonly="1"/>
<field name="is_closed" invisible="1" />
<field name="sequence" invisible="1" readonly="1"/>
@@ -923,6 +923,7 @@
<field name="date_deadline" optional="hide" widget="remaining_days" attrs="{'invisible': [('is_closed', '=', True)]}"/>
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
<field name="stage_id" invisible="context.get('set_visible',False)" optional="show" readonly="1"/>
<field name="recurrence_id" invisible="1" />
</tree>
</field>
</record>