enhancements of Reuqesttimelines

This commit is contained in:
karuna 2026-07-13 18:14:19 +05:30
parent 923f2beab4
commit d7dadb5974
4 changed files with 31 additions and 53 deletions

View File

@ -506,6 +506,7 @@ class projectTask(models.Model):
self.env.user.name, self.env.user.name,
task.suggested_deadline.strftime('%Y-%m-%d %H:%M') if task.suggested_deadline else _('Not available') task.suggested_deadline.strftime('%Y-%m-%d %H:%M') if task.suggested_deadline else _('Not available')
)) ))
task._sync_involved_assignees_from_timelines()
@api.depends("project_id", "stage_id") @api.depends("project_id", "stage_id")
def _compute_has_supervisor_access(self): def _compute_has_supervisor_access(self):
@ -541,13 +542,14 @@ class projectTask(models.Model):
task.has_supervisor_access = True task.has_supervisor_access = True
@api.depends("project_id", "project_id.user_id", "project_id.project_lead") @api.depends("project_id", "project_id.user_id", "project_id.project_lead", "timelines_requested")
def _compute_show_reassign_button(self): def _compute_show_reassign_button(self):
current_user = self.env.user current_user = self.env.user
is_admin = current_user.has_group("base.group_system") or current_user.has_group("project.group_project_manager") is_admin = current_user.has_group("base.group_system") or current_user.has_group("project.group_project_manager")
for task in self: for task in self:
task.show_reassign_button = bool( task.show_reassign_button = bool(
task.project_id task.project_id
and task.timelines_requested
and ( and (
is_admin is_admin
or current_user == task.project_id.user_id or current_user == task.project_id.user_id
@ -1196,7 +1198,7 @@ class projectTask(models.Model):
else: else:
if update_assignees: if update_assignees:
self.sudo().write({'user_ids': [(6, 0, selected_users.ids)]}) self.sudo().write({'user_ids': [(6, 0, selected_users.ids)]})
self.sudo().write({'involved_user_ids': [(6, 0, selected_users.ids)]}) self._sync_involved_assignees_from_timelines()
action = _("Re-assigned") if reassignment else _("Timeline users selected") action = _("Re-assigned") if reassignment else _("Timeline users selected")
note = _("%s: %s") % (action, "; ".join(notes)) note = _("%s: %s") % (action, "; ".join(notes))
if reason: if reason:
@ -1325,8 +1327,7 @@ class projectTask(models.Model):
+ task.assignees_timelines.assigned_to.ids + task.assignees_timelines.assigned_to.ids
+ task.assignees_timelines.team_id.team_lead.ids + task.assignees_timelines.team_id.team_lead.ids
) )
existing_user_ids = set(task.involved_user_ids.ids) involved_users = list(timeline_user_ids - set(task.user_ids.ids))
involved_users = list((existing_user_ids | timeline_user_ids) - set(task.user_ids.ids))
task.involved_user_ids = [(6, 0, involved_users)] task.involved_user_ids = [(6, 0, involved_users)]
@api.model @api.model

View File

@ -16,7 +16,11 @@ class TaskStages(models.Model):
related='team_id.team_lead', related='team_id.team_lead',
readonly=True, readonly=True,
) )
team_related_user_ids = fields.Many2many(related='team_id.all_members_ids', string='Team Users') team_related_user_ids = fields.Many2many(
'res.users',
string='Team Users',
compute='_compute_team_related_user_ids',
)
is_workflow_template = fields.Boolean( is_workflow_template = fields.Boolean(
string='Workflow Template Stage', string='Workflow Template Stage',
default=False, default=False,
@ -27,11 +31,17 @@ class TaskStages(models.Model):
@api.onchange('team_id') @api.onchange('team_id')
def onchange_team_id(self): def onchange_team_id(self):
for rec in self: for rec in self:
if rec.team_id and rec.team_id.all_members_ids: if rec.team_id and (rec.team_id.all_members_ids or rec.team_id.team_lead):
rec.involved_user_ids = [(6,0,rec.team_id.all_members_ids.ids)] users = rec.team_id.all_members_ids | rec.team_id.team_lead
rec.involved_user_ids = [(6, 0, users.ids)]
else: else:
rec.involved_user_ids = [(5, 0, 0)] rec.involved_user_ids = [(5, 0, 0)]
@api.depends('team_id', 'team_id.all_members_ids', 'team_id.team_lead')
def _compute_team_related_user_ids(self):
for rec in self:
rec.team_related_user_ids = rec.team_id.all_members_ids | rec.team_id.team_lead
def _is_project_owned_stage(self, project): def _is_project_owned_stage(self, project):
self.ensure_one() self.ensure_one()
return ( return (

View File

@ -119,32 +119,17 @@ class TaskRequestTimelinesWizardLine(models.TransientModel):
def _get_project_involved_users(self): def _get_project_involved_users(self):
self.ensure_one() self.ensure_one()
users = self.env["res.users"] users = self.stage_id.involved_user_ids if self.stage_id else self.env["res.users"]
task = self.task_id if self.stage_id and self.stage_id.team_id:
project = task.project_id users |= self.stage_id.team_id.all_members_ids | self.stage_id.team_id.team_lead
if project:
users |= project.members_ids | project.user_id | project.project_lead | project.project_sponsor
if self.stage_id:
users |= self.stage_id.involved_user_ids
if self.stage_id.team_id:
users |= self.stage_id.team_id.team_lead | self.stage_id.team_id.all_members_ids
if task:
users |= task.user_ids | task.involved_user_ids
return users.filtered(lambda user: user.active and not user.share) return users.filtered(lambda user: user.active and not user.share)
@api.depends( @api.depends(
"stage_id", "stage_id",
"stage_id.involved_user_ids", "stage_id.involved_user_ids",
"stage_id.team_id", "stage_id.team_id",
"stage_id.team_id.team_lead",
"stage_id.team_id.all_members_ids", "stage_id.team_id.all_members_ids",
"task_id", "stage_id.team_id.team_lead",
"task_id.user_ids",
"task_id.involved_user_ids",
"task_id.project_id.members_ids",
"task_id.project_id.user_id",
"task_id.project_id.project_lead",
"task_id.project_id.project_sponsor",
) )
def _compute_available_user_ids(self): def _compute_available_user_ids(self):
for line in self: for line in self:
@ -172,7 +157,7 @@ class TaskReassignAssigneesWizard(models.TransientModel):
values["line_ids"] = [ values["line_ids"] = [
(0, 0, { (0, 0, {
"stage_id": stage.id, "stage_id": stage.id,
"user_id": task.assignees_timelines.filtered(lambda line: line.stage_id == stage)[:1].assigned_to.id, "responsible_user_id": task._get_stage_responsible_user(stage).id,
}) })
for stage in default_stage for stage in default_stage
] ]
@ -195,11 +180,6 @@ class TaskReassignAssigneesWizard(models.TransientModel):
users |= wizard.task_id.project_id.members_ids | wizard.task_id.project_id.user_id | wizard.task_id.project_id.project_lead | wizard.task_id.project_id.project_sponsor users |= wizard.task_id.project_id.members_ids | wizard.task_id.project_id.user_id | wizard.task_id.project_id.project_lead | wizard.task_id.project_id.project_sponsor
wizard.available_user_ids = [(6, 0, users.filtered(lambda u: u.active and not u.share).ids)] wizard.available_user_ids = [(6, 0, users.filtered(lambda u: u.active and not u.share).ids)]
def _get_default_user_for_stage(self, stage):
self.ensure_one()
timeline = self.task_id.assignees_timelines.filtered(lambda line: line.stage_id == stage)[:1]
return timeline.assigned_to.id if timeline else False
def _preferred_existing_line(self, stage): def _preferred_existing_line(self, stage):
self.ensure_one() self.ensure_one()
lines = self.line_ids.filtered(lambda line: line.stage_id == stage) lines = self.line_ids.filtered(lambda line: line.stage_id == stage)
@ -217,7 +197,7 @@ class TaskReassignAssigneesWizard(models.TransientModel):
else: else:
lines |= Line.new({ lines |= Line.new({
"stage_id": stage.id, "stage_id": stage.id,
"user_id": wizard._get_default_user_for_stage(stage), "responsible_user_id": wizard.task_id._get_stage_responsible_user(stage).id,
}) })
wizard.line_ids = lines wizard.line_ids = lines
@ -239,38 +219,24 @@ class TaskReassignAssigneesWizardLine(models.TransientModel):
wizard_id = fields.Many2one("task.reassign.assignees.wizard", required=True, ondelete="cascade") wizard_id = fields.Many2one("task.reassign.assignees.wizard", required=True, ondelete="cascade")
task_id = fields.Many2one(related="wizard_id.task_id", store=False) task_id = fields.Many2one(related="wizard_id.task_id", store=False)
stage_id = fields.Many2one("project.task.type", string="Stage") stage_id = fields.Many2one("project.task.type", string="Stage")
responsible_user_id = fields.Many2one("res.users", string="Responsible User")
user_id = fields.Many2one("res.users", string="New Assignee") user_id = fields.Many2one("res.users", string="New Assignee")
reason = fields.Text(string="Reason") reason = fields.Text(string="Reason")
available_user_ids = fields.Many2many("res.users", compute="_compute_available_user_ids") available_user_ids = fields.Many2many("res.users", compute="_compute_available_user_ids")
def _get_project_involved_users(self): def _get_project_involved_users(self):
self.ensure_one() self.ensure_one()
users = self.env["res.users"] users = self.stage_id.involved_user_ids if self.stage_id else self.env["res.users"]
task = self.task_id if self.stage_id and self.stage_id.team_id:
project = task.project_id users |= self.stage_id.team_id.all_members_ids | self.stage_id.team_id.team_lead
if project:
users |= project.members_ids | project.user_id | project.project_lead | project.project_sponsor
if self.stage_id:
users |= self.stage_id.involved_user_ids
if self.stage_id.team_id:
users |= self.stage_id.team_id.team_lead | self.stage_id.team_id.all_members_ids
if task:
users |= task.user_ids | task.involved_user_ids
return users.filtered(lambda user: user.active and not user.share) return users.filtered(lambda user: user.active and not user.share)
@api.depends( @api.depends(
"stage_id", "stage_id",
"stage_id.involved_user_ids", "stage_id.involved_user_ids",
"stage_id.team_id", "stage_id.team_id",
"stage_id.team_id.team_lead",
"stage_id.team_id.all_members_ids", "stage_id.team_id.all_members_ids",
"task_id", "stage_id.team_id.team_lead",
"task_id.user_ids",
"task_id.involved_user_ids",
"task_id.project_id.members_ids",
"task_id.project_id.user_id",
"task_id.project_id.project_lead",
"task_id.project_id.project_sponsor",
) )
def _compute_available_user_ids(self): def _compute_available_user_ids(self):
for line in self: for line in self:

View File

@ -79,7 +79,7 @@
<field name="line_ids" nolabel="1"> <field name="line_ids" nolabel="1">
<list editable="bottom" create="0" delete="0"> <list editable="bottom" create="0" delete="0">
<field name="stage_id" readonly="1" force_save="1" options="{'no_open': True}"/> <field name="stage_id" readonly="1" force_save="1" options="{'no_open': True}"/>
<field name="responsible_user_id" force_save="1" domain="[('id', 'in', available_user_ids)]" options="{'no_create': True, 'no_open': True}"/> <field name="responsible_user_id" force_save="1" readonly="1" options="{'no_open': True}"/>
<field name="available_user_ids" column_invisible="1"/> <field name="available_user_ids" column_invisible="1"/>
<field name="user_id" string="Assignee" domain="[('id', 'in', available_user_ids)]" options="{'no_create': True, 'no_open': True}"/> <field name="user_id" string="Assignee" domain="[('id', 'in', available_user_ids)]" options="{'no_create': True, 'no_open': True}"/>
</list> </list>
@ -105,6 +105,7 @@
<field name="line_ids" nolabel="1" invisible="not stage_ids"> <field name="line_ids" nolabel="1" invisible="not stage_ids">
<list editable="bottom" create="0" delete="0"> <list editable="bottom" create="0" delete="0">
<field name="stage_id" readonly="1" force_save="1" options="{'no_open': True}"/> <field name="stage_id" readonly="1" force_save="1" options="{'no_open': True}"/>
<field name="responsible_user_id" readonly="1" force_save="1" options="{'no_open': True}"/>
<field name="available_user_ids" column_invisible="1"/> <field name="available_user_ids" column_invisible="1"/>
<field name="user_id" string="New Assignee" force_save="1" domain="[('id', 'in', available_user_ids)]" options="{'no_create': True, 'no_open': True}"/> <field name="user_id" string="New Assignee" force_save="1" domain="[('id', 'in', available_user_ids)]" options="{'no_create': True, 'no_open': True}"/>
<field name="reason" required="1" force_save="1"/> <field name="reason" required="1" force_save="1"/>