diff options
| author | Kevin Baptiste <kba@odoo.com> | 2020-02-27 13:06:27 +0000 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2020-05-08 08:12:51 +0000 |
| commit | 42c430a539711e3b4f27b9e53fb449bb34a8d463 (patch) | |
| tree | eb60044953801e296763aa89e8e96039d84a19a5 /addons/project | |
| parent | a9d117178f815455461e9475e324eef2f12cecca (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/project')
| -rw-r--r-- | addons/project/data/project_demo.xml | 2 | ||||
| -rw-r--r-- | addons/project/models/project.py | 15 | ||||
| -rw-r--r-- | addons/project/static/src/js/project.js | 23 | ||||
| -rw-r--r-- | addons/project/views/project_views.xml | 19 |
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<current_date)" string="Tasks" multi_edit="1"> + <tree decoration-bf="message_needaction==True" decoration-danger="not is_closed and date_deadline and (date_deadline<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 < current_date" default_order="activity_date_deadline"> + <tree string="Next Activities" decoration-danger="not is_closed and activity_date_deadline < 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','<',time.strftime('%Y-%m-%d'))]</field> + <field name="domain">[('is_closed', '=', False), ('date_deadline','<',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> |
