summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorKevin Baptiste <kba@odoo.com>2020-02-27 13:06:27 +0000
committerYannick Tivisse <yti@odoo.com>2020-05-08 08:12:51 +0000
commit42c430a539711e3b4f27b9e53fb449bb34a8d463 (patch)
treeeb60044953801e296763aa89e8e96039d84a19a5 /addons
parenta9d117178f815455461e9475e324eef2f12cecca (diff)
[IMP] project: add closed stage in project
closes odoo/odoo#46749 Taskid: 2205057 Related: odoo/enterprise#9119 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/project/data/project_demo.xml2
-rw-r--r--addons/project/models/project.py15
-rw-r--r--addons/project/static/src/js/project.js23
-rw-r--r--addons/project/views/project_views.xml19
4 files changed, 46 insertions, 13 deletions
diff --git a/addons/project/data/project_demo.xml b/addons/project/data/project_demo.xml
index 280321e67c5..44be6bc5ec4 100644
--- a/addons/project/data/project_demo.xml
+++ b/addons/project/data/project_demo.xml
@@ -38,12 +38,14 @@
<field name="sequence">20</field>
<field name="name">Done</field>
<field name="fold" eval="True"/>
+ <field name="is_closed" eval="True"/>
</record>
<record id="project_stage_3" model="project.task.type">
<field name="sequence">30</field>
<field name="name">Cancelled</field>
<field name="legend_done">Ready to reopen</field>
<field name="fold" eval="True"/>
+ <field name="is_closed" eval="True"/>
</record>
<record id="project_project_1" model="project.project">
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index 5ae41e236c7..8accaa81de7 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -50,6 +50,7 @@ class ProjectTaskType(models.Model):
help="Automatically modify the kanban state when the customer replies to the feedback for this stage.\n"
" * A good feedback from the customer will update the kanban state to 'ready for the new stage' (green bullet).\n"
" * A medium or a bad feedback will set the kanban state to 'blocked' (red bullet).\n")
+ is_closed = fields.Boolean('Closing Stage', help="Tasks in this stage are considered as closed.")
def unlink_wizard(self, stage_view=False):
self = self.with_context(active_test=False)
@@ -102,7 +103,7 @@ class Project(models.Model):
])
def _compute_task_count(self):
- task_data = self.env['project.task'].read_group([('project_id', 'in', self.ids), '|', ('stage_id.fold', '=', False), ('stage_id', '=', False)], ['project_id'], ['project_id'])
+ task_data = self.env['project.task'].read_group([('project_id', 'in', self.ids), '|', '&', ('stage_id.is_closed', '=', False), ('stage_id.fold', '=', False), ('stage_id', '=', False)], ['project_id'], ['project_id'])
result = dict((data['project_id'][0], data['project_id_count']) for data in task_data)
for project in self:
project.task_count = result.get(project.id, 0)
@@ -517,7 +518,7 @@ class Task(models.Model):
project_id = self.env.context.get('default_project_id')
if not project_id:
return False
- return self.stage_find(project_id, [('fold', '=', False)])
+ return self.stage_find(project_id, [('fold', '=', False), ('is_closed', '=', False)])
@api.model
def _default_company_id(self):
@@ -592,6 +593,7 @@ class Task(models.Model):
legend_blocked = fields.Char(related='stage_id.legend_blocked', string='Kanban Blocked Explanation', readonly=True, related_sudo=False)
legend_done = fields.Char(related='stage_id.legend_done', string='Kanban Valid Explanation', readonly=True, related_sudo=False)
legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing Explanation', readonly=True, related_sudo=False)
+ is_closed = fields.Boolean(related="stage_id.is_closed", string="Closing Stage", readonly=True, related_sudo=False)
parent_id = fields.Many2one('project.task', string='Parent Task', index=True)
child_ids = fields.One2many('project.task', 'parent_id', string="Sub-tasks", context={'active_test': False})
subtask_project_id = fields.Many2one('project.project', related="project_id.subtask_project_id", string='Sub-task Project', readonly=True)
@@ -716,7 +718,7 @@ class Task(models.Model):
self.partner_id = self.project_id.partner_id
# find stage
if self.project_id not in self.stage_id.project_ids:
- self.stage_id = self.stage_find(self.project_id.id, [('fold', '=', False)])
+ self.stage_id = self.stage_find(self.project_id.id, [('fold', '=', False), ('is_closed', '=', False)])
# keep multi company consistency
self.company_id = self.project_id.company_id
else:
@@ -795,6 +797,7 @@ class Task(models.Model):
def create(self, vals):
# context: no_log, because subtype already handle this
context = dict(self.env.context)
+ stage_id = vals.get('stage_id') or context.get('default_stage_id') or False
# for default stage
if vals.get('project_id') and not context.get('default_project_id'):
context['default_project_id'] = vals.get('project_id')
@@ -802,8 +805,8 @@ class Task(models.Model):
if vals.get('user_id'):
vals['date_assign'] = fields.Datetime.now()
# Stage change: Update date_end if folded stage and date_last_stage_update
- if vals.get('stage_id'):
- vals.update(self.update_date_end(vals['stage_id']))
+ if stage_id:
+ vals.update(self.update_date_end(stage_id))
vals['date_last_stage_update'] = fields.Datetime.now()
task = super(Task, self.with_context(context)).create(vals)
return task
@@ -831,7 +834,7 @@ class Task(models.Model):
def update_date_end(self, stage_id):
project_task_type = self.env['project.task.type'].browse(stage_id)
- if project_task_type.fold:
+ if project_task_type.fold or project_task_type.is_closed:
return {'date_end': fields.Datetime.now()}
return {'date_end': False}
diff --git a/addons/project/static/src/js/project.js b/addons/project/static/src/js/project.js
index 4938d4bf4de..5e0062a9965 100644
--- a/addons/project/static/src/js/project.js
+++ b/addons/project/static/src/js/project.js
@@ -2,6 +2,8 @@ odoo.define('project.update_kanban', function (require) {
'use strict';
var KanbanRecord = require('web.KanbanRecord');
+var basic_fields = require('web.basic_fields');
+var registry = require('web.field_registry');
KanbanRecord.include({
//--------------------------------------------------------------------------
@@ -21,4 +23,25 @@ KanbanRecord.include({
},
});
+
+var FieldTaskClosedDeadline = basic_fields.FieldDate.extend({
+ _renderReadonly: function () {
+ if (this.value && this.value.toISOString()) {
+ var deadline = moment(this.value.toISOString()).startOf('day');
+ var task_closed = 'is_closed' in this.record.data && this.record.data.is_closed;
+
+ if (!task_closed && deadline < moment().startOf('day')) {
+ this.$el.addClass('text-danger font-weight-bold');
+ } else if (!task_closed && deadline < moment().endOf('day')) {
+ this.$el.addClass('text-warning font-weight-bold');
+ }
+ }
+
+ this.$el.text(this._formatValue(this.value));
+ }
+});
+
+registry.add('task_closed_deadline', FieldTaskClosedDeadline);
+
+return FieldTaskClosedDeadline;
});
diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml
index 03ca2bafb53..2fd2c4ef026 100644
--- a/addons/project/views/project_views.xml
+++ b/addons/project/views/project_views.xml
@@ -105,7 +105,7 @@
</button>
<button class="oe_stat_button" type="action"
name="%(act_project_project_2_project_task_all)d" icon="fa-tasks">
- <field string="Tasks" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
+ <field string="Tasks In Progress" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
</button>
<button name="action_view_all_rating" type="object" attrs="{'invisible': ['|', ('rating_status', '=', 'no'), ('rating_percentage_satisfaction', '=', -1)]}" class="oe_stat_button oe_percent" icon="fa-smile-o" groups="project.group_project_rating">
<div class="o_field_widget o_stat_info">
@@ -473,6 +473,7 @@
<field name="arch" type="xml">
<form string="Task" class="o_form_project_tasks">
<field name="allow_subtasks" invisible="1" />
+ <field name="is_closed" invisible="1" />
<header>
<button name="action_assign_to_me" string="Assign to Me" type="object" class="oe_highlight"
attrs="{'invisible' : [('user_id', '!=', False)]}"/>
@@ -516,7 +517,7 @@
domain="[('parent_id', '=', False)]"
attrs="{'invisible' : [('allow_subtasks', '=', False)]}"
/>
- <field name="date_deadline"/>
+ <field name="date_deadline" widget="task_closed_deadline" />
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
</group>
</group>
@@ -613,6 +614,7 @@
<field name="sequence"/>
<field name="date_deadline"/>
<field name="date_deadline_formatted"/>
+ <field name="is_closed"/>
<field name="partner_is_company"/>
<field name="message_needaction_counter"/>
<field name="displayed_image_id"/>
@@ -680,10 +682,10 @@
<t t-set="date_format" t-value="'MM/DD/YY'" />
<t t-set="date" t-value=""/>
<!-- color of the span -->
- <t t-if="record.date_deadline.raw_value and moment(record.date_deadline.raw_value.toISOString()).startOf('day') lt moment().startOf('day')">
+ <t t-if="!record.is_closed.raw_value and record.date_deadline.raw_value and moment(record.date_deadline.raw_value.toISOString()).startOf('day') lt moment().startOf('day')">
<t t-set="deadline_class" t-value="'oe_kanban_text_red'" />
</t>
- <t t-elif="record.date_deadline.raw_value and moment(record.date_deadline.raw_value.toISOString()).startOf('day') lt moment().endOf('day')">
+ <t t-elif="!record.is_closed.raw_value and record.date_deadline.raw_value and moment(record.date_deadline.raw_value.toISOString()).startOf('day') lt moment().endOf('day')">
<t t-set="deadline_class" t-value="'text-warning font-weight-bold'" />
</t>
<!-- Date value -->
@@ -709,8 +711,9 @@
<field name="model">project.task</field>
<field eval="2" name="priority"/>
<field name="arch" type="xml">
- <tree decoration-bf="message_needaction==True" decoration-danger="date_deadline and (date_deadline&lt;current_date)" string="Tasks" multi_edit="1">
+ <tree decoration-bf="message_needaction==True" decoration-danger="not is_closed and date_deadline and (date_deadline&lt;current_date)" string="Tasks" multi_edit="1">
<field name="message_needaction" invisible="1" readonly="1"/>
+ <field name="is_closed" invisible="1" />
<field name="sequence" invisible="not context.get('seq_visible', False)" readonly="1"/>
<field name="name"/>
<!-- YTI TODO user_invisible and seq_visible seem to be useless -->
@@ -731,7 +734,8 @@
<field name="name">project.task.tree.activity</field>
<field name="model">project.task</field>
<field name="arch" type="xml">
- <tree string="Next Activities" decoration-danger="activity_date_deadline &lt; current_date" default_order="activity_date_deadline">
+ <tree string="Next Activities" decoration-danger="not is_closed and activity_date_deadline &lt; current_date" default_order="activity_date_deadline">
+ <field name="is_closed"/>
<field name="name"/>
<field name="project_id"/>
<field name="activity_date_deadline"/>
@@ -856,7 +860,7 @@
<field name="name">Overpassed Tasks</field>
<field name="res_model">project.task</field>
<field name="view_mode">tree,form,calendar,graph,kanban</field>
- <field name="domain">[('date_deadline','&lt;',time.strftime('%Y-%m-%d'))]</field>
+ <field name="domain">[('is_closed', '=', False), ('date_deadline','&lt;',time.strftime('%Y-%m-%d'))]</field>
<field name="filter" eval="True"/>
<field name="search_view_id" ref="view_task_search_form"/>
</record>
@@ -899,6 +903,7 @@
</group>
<group>
<field name="fold"/>
+ <field name="is_closed" groups="base.group_no_one"/>
<field name="project_ids" widget="many2many_tags" groups="base.group_no_one"/>
<field name="sequence" groups="base.group_no_one"/>
</group>