enhancements of PMT
This commit is contained in:
parent
05bdddc472
commit
f118600ab6
|
|
@ -120,6 +120,7 @@ class projectTask(models.Model):
|
||||||
project_privacy_visibility = fields.Selection(related="project_id.privacy_visibility")
|
project_privacy_visibility = fields.Selection(related="project_id.privacy_visibility")
|
||||||
show_submission_button = fields.Boolean(compute="_compute_access_check")
|
show_submission_button = fields.Boolean(compute="_compute_access_check")
|
||||||
show_approval_button = fields.Boolean(compute="_compute_access_check")
|
show_approval_button = fields.Boolean(compute="_compute_access_check")
|
||||||
|
show_skip_approval_button = fields.Boolean(compute="_compute_access_check")
|
||||||
show_refuse_button = fields.Boolean(compute="_compute_access_check")
|
show_refuse_button = fields.Boolean(compute="_compute_access_check")
|
||||||
show_back_button = fields.Boolean(compute="_compute_access_check")
|
show_back_button = fields.Boolean(compute="_compute_access_check")
|
||||||
|
|
||||||
|
|
@ -681,11 +682,12 @@ class projectTask(models.Model):
|
||||||
record.can_edit_approval_flow_stages = False
|
record.can_edit_approval_flow_stages = False
|
||||||
record._add_activity_log(f"Task {action} by {self.env.user.name}")
|
record._add_activity_log(f"Task {action} by {self.env.user.name}")
|
||||||
|
|
||||||
@api.depends("assignees_timelines", "stage_id", "project_id", "approval_status")
|
@api.depends("assignees_timelines", "assignees_timelines.assigned_to", "assignees_timelines.responsible_lead", "stage_id", "project_id", "approval_status", "involved_user_ids")
|
||||||
def _compute_access_check(self):
|
def _compute_access_check(self):
|
||||||
for task in self:
|
for task in self:
|
||||||
task.show_submission_button = False
|
task.show_submission_button = False
|
||||||
task.show_approval_button = False
|
task.show_approval_button = False
|
||||||
|
task.show_skip_approval_button = False
|
||||||
task.show_refuse_button = False
|
task.show_refuse_button = False
|
||||||
task.show_back_button = False
|
task.show_back_button = False
|
||||||
if task.project_id:
|
if task.project_id:
|
||||||
|
|
@ -699,11 +701,14 @@ class projectTask(models.Model):
|
||||||
next_stage = task.project_id.type_ids.filtered(lambda s: s.sequence > task.stage_id.sequence).sorted(
|
next_stage = task.project_id.type_ids.filtered(lambda s: s.sequence > task.stage_id.sequence).sorted(
|
||||||
key=lambda s: s.sequence)[:1]
|
key=lambda s: s.sequence)[:1]
|
||||||
|
|
||||||
|
approval_not_required = False
|
||||||
|
|
||||||
# Compute buttons visibility
|
# Compute buttons visibility
|
||||||
if current_timeline:
|
if current_timeline:
|
||||||
line = current_timeline[0]
|
line = current_timeline[0]
|
||||||
assigned_to = line.assigned_to
|
assigned_to = line.assigned_to
|
||||||
responsible_lead = line.responsible_lead
|
responsible_lead = line.responsible_lead
|
||||||
|
approval_not_required = not assigned_to and not responsible_lead
|
||||||
|
|
||||||
if (
|
if (
|
||||||
assigned_to
|
assigned_to
|
||||||
|
|
@ -713,16 +718,25 @@ class projectTask(models.Model):
|
||||||
):
|
):
|
||||||
task.show_submission_button = True
|
task.show_submission_button = True
|
||||||
|
|
||||||
|
if (
|
||||||
|
approval_not_required
|
||||||
|
and user in task.involved_user_ids
|
||||||
|
and task.approval_status != "submitted"
|
||||||
|
):
|
||||||
|
task.show_submission_button = True
|
||||||
|
task.show_skip_approval_button = True
|
||||||
|
|
||||||
# a) Submitted + current user is responsible lead / project manager
|
# a) Submitted + current user is responsible lead / project manager
|
||||||
if (
|
if (
|
||||||
task.approval_status == "submitted"
|
task.approval_status == "submitted"
|
||||||
|
and not approval_not_required
|
||||||
and (responsible_lead == user or project_manager == user)
|
and (responsible_lead == user or project_manager == user)
|
||||||
):
|
):
|
||||||
task.show_approval_button = True
|
task.show_approval_button = True
|
||||||
task.show_refuse_button = True # both approve & refuse in review state
|
task.show_refuse_button = True # both approve & refuse in review state
|
||||||
|
|
||||||
# b) No assigned user: directly approvable
|
# b) No assigned user, but a responsible user exists: directly approvable
|
||||||
elif not assigned_to and (responsible_lead == user or project_manager == user):
|
elif not assigned_to and responsible_lead and (responsible_lead == user or project_manager == user):
|
||||||
task.show_approval_button = True
|
task.show_approval_button = True
|
||||||
|
|
||||||
# c) Assigned_to == responsible_lead: no submission needed, direct approve
|
# c) Assigned_to == responsible_lead: no submission needed, direct approve
|
||||||
|
|
@ -734,13 +748,16 @@ class projectTask(models.Model):
|
||||||
task.show_approval_button = True
|
task.show_approval_button = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Allow project lead or project manager to approve directly
|
approval_not_required = True
|
||||||
if user in [project_lead, project_manager]:
|
if user in task.involved_user_ids and task.approval_status != "submitted":
|
||||||
task.show_approval_button = True
|
task.show_submission_button = True
|
||||||
|
task.show_skip_approval_button = True
|
||||||
|
|
||||||
if user in [project_manager] or user.has_group("project.group_project_manager"):
|
if (user in [project_manager] or user.has_group("project.group_project_manager")) and not approval_not_required:
|
||||||
task.show_approval_button = True
|
task.show_approval_button = True
|
||||||
task.show_back_button = True
|
task.show_back_button = True
|
||||||
|
elif user in [project_manager] or user.has_group("project.group_project_manager"):
|
||||||
|
task.show_back_button = True
|
||||||
|
|
||||||
if task.stage_id and task.project_id.type_ids:
|
if task.stage_id and task.project_id.type_ids:
|
||||||
is_first_stage = task.stage_id.sequence == min(task.project_id.type_ids.mapped('sequence'))
|
is_first_stage = task.stage_id.sequence == min(task.project_id.type_ids.mapped('sequence'))
|
||||||
|
|
@ -749,6 +766,7 @@ class projectTask(models.Model):
|
||||||
is_last_stage = task.stage_id.sequence == max(task.project_id.type_ids.mapped('sequence'))
|
is_last_stage = task.stage_id.sequence == max(task.project_id.type_ids.mapped('sequence'))
|
||||||
if is_last_stage:
|
if is_last_stage:
|
||||||
task.show_submission_button = False
|
task.show_submission_button = False
|
||||||
|
task.show_skip_approval_button = False
|
||||||
task.show_approval_button = False
|
task.show_approval_button = False
|
||||||
task.show_refuse_button = False
|
task.show_refuse_button = False
|
||||||
|
|
||||||
|
|
@ -786,8 +804,42 @@ class projectTask(models.Model):
|
||||||
def submit_for_approval(self):
|
def submit_for_approval(self):
|
||||||
for task in self:
|
for task in self:
|
||||||
task.can_edit_approval_flow_stages = True
|
task.can_edit_approval_flow_stages = True
|
||||||
task.approval_status = "submitted"
|
|
||||||
stage = task.assignees_timelines.filtered(lambda s: s.stage_id == task.stage_id)
|
stage = task.assignees_timelines.filtered(lambda s: s.stage_id == task.stage_id)
|
||||||
|
if not stage or (not stage[0].assigned_to and not stage[0].responsible_lead):
|
||||||
|
current_stage = task.stage_id
|
||||||
|
next_stage = task.project_id.type_ids.filtered(lambda s: s.sequence > current_stage.sequence)
|
||||||
|
next_stage = next_stage.sorted(key=lambda s: s.sequence)[:1]
|
||||||
|
if next_stage:
|
||||||
|
task.stage_id = next_stage
|
||||||
|
task.approval_status = False
|
||||||
|
activity_log = "%s: approval skipped by %s and moved to %s" % (
|
||||||
|
current_stage.name,
|
||||||
|
self.env.user.employee_id.name,
|
||||||
|
next_stage.name
|
||||||
|
)
|
||||||
|
task._add_activity_log(activity_log)
|
||||||
|
channel_message = _("Task %s moved from %s to %s. Approval was not required for the empty stage.") % (
|
||||||
|
task.sequence_name or task.name,
|
||||||
|
current_stage.name,
|
||||||
|
next_stage.name
|
||||||
|
)
|
||||||
|
task._post_to_project_channel(channel_message)
|
||||||
|
task.message_post(body=channel_message, message_type="notification", subtype_xmlid="mail.mt_comment")
|
||||||
|
else:
|
||||||
|
task.approval_status = "approved"
|
||||||
|
activity_log = "%s: approval skipped by %s and task completed" % (
|
||||||
|
current_stage.name,
|
||||||
|
self.env.user.employee_id.name
|
||||||
|
)
|
||||||
|
task._add_activity_log(activity_log)
|
||||||
|
channel_message = _("Task %s completed. Approval was not required for the empty stage.") % (
|
||||||
|
task.sequence_name or task.name
|
||||||
|
)
|
||||||
|
task._post_to_project_channel(channel_message)
|
||||||
|
task.message_post(body=channel_message, message_type="notification", subtype_xmlid="mail.mt_comment")
|
||||||
|
task.can_edit_approval_flow_stages = False
|
||||||
|
continue
|
||||||
|
task.approval_status = "submitted"
|
||||||
responsible_user = stage.responsible_lead if stage and stage.responsible_lead else False
|
responsible_user = stage.responsible_lead if stage and stage.responsible_lead else False
|
||||||
|
|
||||||
activity_log = "%s : %s Submitted to %s for approval" % (
|
activity_log = "%s : %s Submitted to %s for approval" % (
|
||||||
|
|
@ -1848,3 +1900,6 @@ class projectTaskTimelines(models.Model):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,16 @@
|
||||||
<record id="project_task_search_project_by_module" model="ir.ui.view">
|
<record id="project_task_search_project_by_module" model="ir.ui.view">
|
||||||
<field name="name">project.task.search.project.by.module</field>
|
<field name="name">project.task.search.project.by.module</field>
|
||||||
<field name="model">project.task</field>
|
<field name="model">project.task</field>
|
||||||
<field name="inherit_id" ref="project.view_task_search_form"/>
|
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//search" position="inside">
|
<search>
|
||||||
|
<field name="name" string="Task"/>
|
||||||
|
<field name="project_id" string="Project"/>
|
||||||
|
<field name="model_id" string="Module" filter_domain="[('model_id.name', 'ilike', self)]"/>
|
||||||
<filter name="group_by_module" string="Module" context="{'group_by': 'model_id'}"/>
|
<filter name="group_by_module" string="Module" context="{'group_by': 'model_id'}"/>
|
||||||
</xpath>
|
<searchpanel>
|
||||||
|
<field name="model_id" string="Module"/>
|
||||||
|
</searchpanel>
|
||||||
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
@ -54,8 +59,8 @@
|
||||||
<field name="name">Project by Module</field>
|
<field name="name">Project by Module</field>
|
||||||
<field name="res_model">project.task</field>
|
<field name="res_model">project.task</field>
|
||||||
<field name="view_mode">kanban,list,form,calendar,activity</field>
|
<field name="view_mode">kanban,list,form,calendar,activity</field>
|
||||||
<field name="search_view_id" ref="project.view_task_search_form"/>
|
<field name="search_view_id" ref="project_task_timesheet_extended.project_task_search_project_by_module"/>
|
||||||
<field name="context">{'search_default_group_by_module': 1}</field>
|
<field name="context">{}</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="o_view_nocontent_smiling_face">
|
<p class="o_view_nocontent_smiling_face">
|
||||||
No projects found.
|
No projects found.
|
||||||
|
|
@ -75,3 +80,5 @@
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,8 @@
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//header" position="inside">
|
<xpath expr="//header" position="inside">
|
||||||
<button type="object" name="request_timelines" string="Request Timelines" class="oe_highlight" invisible="not show_approval_flow or timelines_requested or record_paused"/>
|
<button type="object" name="request_timelines" string="Request Timelines" class="oe_highlight" invisible="not show_approval_flow or timelines_requested or record_paused"/>
|
||||||
<button type="object" name="submit_for_approval" string="Request Approval" class="oe_highlight" invisible="not show_approval_flow or not show_submission_button or not timelines_requested or record_paused"/>
|
<button type="object" name="submit_for_approval" string="Request Approval" class="oe_highlight" invisible="not show_approval_flow or not show_submission_button or show_skip_approval_button or record_paused"/>
|
||||||
|
<button type="object" name="submit_for_approval" string="Next" class="oe_highlight" invisible="not show_approval_flow or not show_skip_approval_button or record_paused"/>
|
||||||
<button type="object" name="proceed_further" string="Approve & Proceed" class="oe_highlight" invisible="not show_approval_flow or not show_approval_button or not timelines_requested or record_paused"/>
|
<button type="object" name="proceed_further" string="Approve & Proceed" class="oe_highlight" invisible="not show_approval_flow or not show_approval_button or not timelines_requested or record_paused"/>
|
||||||
<button type="object" name="action_open_reject_wizard" string="Reject & Return" class="oe_highlight" invisible="not show_approval_flow or not show_refuse_button or not timelines_requested or record_paused"/>
|
<button type="object" name="action_open_reject_wizard" string="Reject & Return" class="oe_highlight" invisible="not show_approval_flow or not show_refuse_button or not timelines_requested or record_paused"/>
|
||||||
<button type="object" name="back_button" string="Go Back" class="oe_highlight" invisible="not show_approval_flow or not show_back_button or not timelines_requested or record_paused"/>
|
<button type="object" name="back_button" string="Go Back" class="oe_highlight" invisible="not show_approval_flow or not show_back_button or not timelines_requested or record_paused"/>
|
||||||
|
|
@ -115,6 +116,7 @@
|
||||||
<field name="show_approval_flow" invisible="1"/>
|
<field name="show_approval_flow" invisible="1"/>
|
||||||
<field name="show_submission_button" invisible="1"/>
|
<field name="show_submission_button" invisible="1"/>
|
||||||
<field name="show_approval_button" invisible="1"/>
|
<field name="show_approval_button" invisible="1"/>
|
||||||
|
<field name="show_skip_approval_button" invisible="1"/>
|
||||||
<field name="show_refuse_button" invisible="1"/>
|
<field name="show_refuse_button" invisible="1"/>
|
||||||
<field name="show_back_button" invisible="1"/>
|
<field name="show_back_button" invisible="1"/>
|
||||||
<field name="has_supervisor_access" invisible="1"/>
|
<field name="has_supervisor_access" invisible="1"/>
|
||||||
|
|
@ -304,3 +306,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue