enhancements of PMT

This commit is contained in:
karuna 2026-06-04 15:36:32 +05:30
parent 05bdddc472
commit f118600ab6
3 changed files with 80 additions and 14 deletions

View File

@ -120,6 +120,7 @@ class projectTask(models.Model):
project_privacy_visibility = fields.Selection(related="project_id.privacy_visibility")
show_submission_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_back_button = fields.Boolean(compute="_compute_access_check")
@ -681,11 +682,12 @@ class projectTask(models.Model):
record.can_edit_approval_flow_stages = False
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):
for task in self:
task.show_submission_button = False
task.show_approval_button = False
task.show_skip_approval_button = False
task.show_refuse_button = False
task.show_back_button = False
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(
key=lambda s: s.sequence)[:1]
approval_not_required = False
# Compute buttons visibility
if current_timeline:
line = current_timeline[0]
assigned_to = line.assigned_to
responsible_lead = line.responsible_lead
approval_not_required = not assigned_to and not responsible_lead
if (
assigned_to
@ -713,16 +718,25 @@ class projectTask(models.Model):
):
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
if (
task.approval_status == "submitted"
and not approval_not_required
and (responsible_lead == user or project_manager == user)
):
task.show_approval_button = True
task.show_refuse_button = True # both approve & refuse in review state
# b) No assigned user: directly approvable
elif not assigned_to and (responsible_lead == user or project_manager == user):
# b) No assigned user, but a responsible user exists: directly approvable
elif not assigned_to and responsible_lead and (responsible_lead == user or project_manager == user):
task.show_approval_button = True
# c) Assigned_to == responsible_lead: no submission needed, direct approve
@ -734,13 +748,16 @@ class projectTask(models.Model):
task.show_approval_button = True
else:
# Allow project lead or project manager to approve directly
if user in [project_lead, project_manager]:
task.show_approval_button = True
approval_not_required = True
if user in task.involved_user_ids and task.approval_status != "submitted":
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_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:
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'))
if is_last_stage:
task.show_submission_button = False
task.show_skip_approval_button = False
task.show_approval_button = False
task.show_refuse_button = False
@ -786,8 +804,42 @@ class projectTask(models.Model):
def submit_for_approval(self):
for task in self:
task.can_edit_approval_flow_stages = True
task.approval_status = "submitted"
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
activity_log = "%s : %s Submitted to %s for approval" % (
@ -1848,3 +1900,6 @@ class projectTaskTimelines(models.Model):

View File

@ -40,11 +40,16 @@
<record id="project_task_search_project_by_module" model="ir.ui.view">
<field name="name">project.task.search.project.by.module</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_search_form"/>
<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'}"/>
</xpath>
<searchpanel>
<field name="model_id" string="Module"/>
</searchpanel>
</search>
</field>
</record>
@ -54,8 +59,8 @@
<field name="name">Project by Module</field>
<field name="res_model">project.task</field>
<field name="view_mode">kanban,list,form,calendar,activity</field>
<field name="search_view_id" ref="project.view_task_search_form"/>
<field name="context">{'search_default_group_by_module': 1}</field>
<field name="search_view_id" ref="project_task_timesheet_extended.project_task_search_project_by_module"/>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No projects found.
@ -75,3 +80,5 @@
</odoo>

View File

@ -104,7 +104,8 @@
</xpath>
<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="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 &amp; 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 &amp; 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"/>
@ -115,6 +116,7 @@
<field name="show_approval_flow" invisible="1"/>
<field name="show_submission_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_back_button" invisible="1"/>
<field name="has_supervisor_access" invisible="1"/>
@ -304,3 +306,5 @@