direct manager helpdesk

This commit is contained in:
mohammed-alkhazrji 2025-07-16 23:22:43 +03:00
parent e8ea777419
commit 94c3829616
10 changed files with 268 additions and 180 deletions

View File

@ -273,8 +273,16 @@ msgstr "السابق"
msgid "Rejection" msgid "Rejection"
msgstr "رفض" msgstr "رفض"
#. module: helpdesk_employee_request
#: model:ir.ui.menu,name:helpdesk_employee_request.menu_helpdesk_employee_direct_manager
msgid "Requests by My Employees"
msgstr "طلبات الموظفين التابعين لي"
#. module: helpdesk_employee_request
#: model:res.groups,name:helpdesk_employee_request.group_odex25_helpdesk_direct_manager
msgid "Direct Manager Helpdesk"
msgstr "المدير المباشر"

View File

@ -39,9 +39,11 @@ class HelpdeskTicket(models.Model):
('vip', 'VIP'), ('vip', 'VIP'),
('request', 'Request'), ('request', 'Request'),
('secretary', 'Secretary')]) ('secretary', 'Secretary')])
show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True) # show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True)
show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True) # show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True)
show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True) # show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True)
# show_button_draft = fields.Boolean(related='stage_id.final_rejection_stage', store=True)
@api.model @api.model
def create(self, vals): def create(self, vals):
""" """
@ -83,111 +85,11 @@ class HelpdeskTicket(models.Model):
return res return res
def _resolve_next_stage(self):
"""Return the best next stage according to the following order:
1) If `next_stage` is set and unique -> use it.
2) If there are multiple -> take the first one that intersects with the team's stages.
3) If not set -> use the first stage with a higher sequence than the current one within the team.
"""
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the next stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can approve this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else: class odex25_helpdeskStage(models.Model):
if self.stage_id.user_id != self.env.user: _inherit = 'odex25_helpdesk.stage'
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name) pass
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence)
for st in stages:
if st.sequence > self.stage_id.sequence:
return st
return False
# --------------------------------------------------
# Action Buttons
# --------------------------------------------------
def action_confirm(self):
for ticket in self:
next_stage = ticket._resolve_next_stage()
if not next_stage:
raise ValidationError(_("No next stage is configured for this ticket!"))
ticket.stage_id = next_stage
def action_rejection(self):
self.ensure_one()
rejection_stage = self.team_id.stage_ids.filtered(lambda s: s.final_rejection_stage)
if rejection_stage:
self.stage_id = rejection_stage[0]
else:
raise ValidationError(_("No final rejection stage is defined within the team's stages."))
# --------------------------------------------------
# Override write to mark is_submitted when closing
# --------------------------------------------------
def write(self, vals):
if vals.get('stage_id'):
new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id'])
if new_stage.is_close:
vals['is_submitted'] = True
return super().write(vals)
def _resolve_previous_stage(self):
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the Previous stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can Previous this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence, reverse=True)
for st in stages:
if st.sequence < self.stage_id.sequence:
return st
return False
def action_back(self):
for ticket in self:
prev_stage = ticket._resolve_previous_stage()
if not prev_stage:
raise ValidationError(_("No previous stage is configured for this ticket!"))
ticket.stage_id = prev_stage

View File

@ -15,6 +15,18 @@
<field name="category_id" ref="base.module_category_services_helpdesk"/> <field name="category_id" ref="base.module_category_services_helpdesk"/>
</record> </record>
<record id="group_odex25_helpdesk_direct_manager" model="res.groups">
<field name="name">Direct Manager Helpdesk</field>
<field name="category_id" ref="base.module_category_services_helpdesk"/>
<!-- <field name="implied_ids" eval="[(4, ref('odex25_helpdesk.group_odex25_helpdesk_user'))]"/>-->
</record>
<record id="odex25_helpdesk_ticket_direct_manager_rule" model="ir.rule">
<field name="name">Helpdesk Tickets: Direct Manager Only</field>
<field name="model_id" ref="helpdesk_employee_request.model_odex25_helpdesk_ticket"/>
<field name="domain_force">[('employee_id', '=', user.id)]</field>
<field name="groups" eval="[(4, ref('helpdesk_employee_request.group_odex25_helpdesk_direct_manager'))]"/>
</record>
<record id="group_helpdesk_Secretary" model="res.groups"> <record id="group_helpdesk_Secretary" model="res.groups">
<field name="name">Secretary</field> <field name="name">Secretary</field>

View File

@ -36,4 +36,7 @@ access_analytic_account_heldpdesk_user_secretary_employee,analytic.account.helpd
access_analytic_line_heldpdesk_user_secretary_employee,analytic.line.helpdesk.user.vip_employee,analytic.model_account_analytic_line,helpdesk_employee_request.group_helpdesk_Secretary,1,1,1,1 access_analytic_line_heldpdesk_user_secretary_employee,analytic.line.helpdesk.user.vip_employee,analytic.model_account_analytic_line,helpdesk_employee_request.group_helpdesk_Secretary,1,1,1,1
employee_access_sla_status_secretary,model_odex25_helpdesk_sla_status.secretary,odex25_helpdesk.model_odex25_helpdesk_sla_status,helpdesk_employee_request.group_helpdesk_Secretary,1,1,1,1 employee_access_sla_status_secretary,model_odex25_helpdesk_sla_status.secretary,odex25_helpdesk.model_odex25_helpdesk_sla_status,helpdesk_employee_request.group_helpdesk_Secretary,1,1,1,1
employee_access_secretary_service_category,secretary.service.category,odex25_helpdesk.model_service_category,helpdesk_employee_request.group_helpdesk_Secretary,1,0,0,0 employee_access_secretary_service_category,secretary.service.category,odex25_helpdesk.model_service_category,helpdesk_employee_request.group_helpdesk_Secretary,1,0,0,0
employee_access_secretary_helpdesk_service,secretary.helpdesk.service,odex25_helpdesk.model_helpdesk_service,helpdesk_employee_request.group_helpdesk_Secretary,1,0,0,0 employee_access_secretary_helpdesk_service,secretary.helpdesk.service,odex25_helpdesk.model_helpdesk_service,helpdesk_employee_request.group_helpdesk_Secretary,1,0,0,0
access_helpdesk_ticket_direct_manager,helpdesk.ticket.direct.manager,odex25_helpdesk.model_odex25_helpdesk_ticket,helpdesk_employee_request.group_odex25_helpdesk_direct_manager,1,1,1,0
access_helpdesk_stage_direct_manager,helpdesk.stage.direct.manager,odex25_helpdesk.model_odex25_helpdesk_stage,helpdesk_employee_request.group_odex25_helpdesk_direct_manager,1,1,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
36 access_helpdesk_stage_direct_manager helpdesk.stage.direct.manager odex25_helpdesk.model_odex25_helpdesk_stage helpdesk_employee_request.group_odex25_helpdesk_direct_manager 1 1 0 0
37
38
39
40
41
42

View File

@ -61,6 +61,7 @@
</div> </div>
<group> <group>
<group> <group>
<field name="manager_id" invisible="1"/>
<field name="active" invisible="1"/> <field name="active" invisible="1"/>
<field name="requester_id" invisible="1"/> <field name="requester_id" invisible="1"/>
<field name="is_submitted" invisible="1"/> <field name="is_submitted" invisible="1"/>
@ -96,6 +97,7 @@
<field name="show_button_previous" invisible="1"/> <field name="show_button_previous" invisible="1"/>
<field name="show_button_rejection" invisible="1"/> <field name="show_button_rejection" invisible="1"/>
<field name="show_button_draft" invisible="1"/>
<field name="stage_id" widget="statusbar" options="{'fold_field': 'fold'}" readonly="1"/> <field name="stage_id" widget="statusbar" options="{'fold_field': 'fold'}" readonly="1"/>
@ -104,6 +106,12 @@
<button name="action_back" string="Previous" type="object" class="btn-secondary" attrs="{'invisible': [('show_button_previous', '=', False)]}"/> <button name="action_back" string="Previous" type="object" class="btn-secondary" attrs="{'invisible': [('show_button_previous', '=', False)]}"/>
<button name="action_rejection" string="Rejection" type="object" class="btn-primary" <button name="action_rejection" string="Rejection" type="object" class="btn-primary"
attrs="{'invisible': [('show_button_rejection', '=', False)]}" /> attrs="{'invisible': [('show_button_rejection', '=', False)]}" />
<button name="action_to_draft"
string="To Draft"
type="object"
class="btn-secondary"
attrs="{'invisible': [('show_button_draft', '=', False)]}"/>
</header> </header>
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
@ -113,7 +121,7 @@
</div> </div>
<group> <group>
<group> <group>
<field name="manager_id" invisible="1"/>
<field name="requester_id" invisible="1"/> <field name="requester_id" invisible="1"/>
<field name="is_submitted" invisible="1"/> <field name="is_submitted" invisible="1"/>
<field name="active" invisible="1"/> <field name="active" invisible="1"/>
@ -210,11 +218,21 @@
<field name="view_id" ref="odex25_helpdesk_tickets_employee_request_view_tree"/> <field name="view_id" ref="odex25_helpdesk_tickets_employee_request_view_tree"/>
<field name="act_window_id" ref="action_helpdesk_ticket_employee_request"/> <field name="act_window_id" ref="action_helpdesk_ticket_employee_request"/>
</record> </record>
<record id="action_helpdesk_ticket_direct_manager" model="ir.actions.act_window">
<field name="name">Employee Requests (My Staff)</field>
<field name="res_model">odex25_helpdesk.ticket</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('ticket_service_type','=','request')]</field>
<field name="context" eval="{
'default_ticket_service_type': 'request',
'active_test':False
}"/>
</record>
<menuitem id="menu_helpdesk_employee" name="Helpdesk" <menuitem id="menu_helpdesk_employee" name="Helpdesk"
web_icon="odex25_helpdesk,static/description/icon.png" web_icon="odex25_helpdesk,static/description/icon.png"
groups="helpdesk_employee_request.group_helpdesk_employee,helpdesk_employee_request.group_helpdesk_vip_employee,helpdesk_employee_request.group_helpdesk_Secretary"/> groups="helpdesk_employee_request.group_helpdesk_employee,helpdesk_employee_request.group_helpdesk_vip_employee,helpdesk_employee_request.group_helpdesk_Secretary,helpdesk_employee_request.group_odex25_helpdesk_direct_manager"/>
<menuitem id="menu_helpdesk_vip_employee_request" name="VIP Employee Helpdesk" <menuitem id="menu_helpdesk_vip_employee_request" name="VIP Employee Helpdesk"
parent="menu_helpdesk_employee" parent="menu_helpdesk_employee"
@ -226,7 +244,13 @@
parent="menu_helpdesk_employee" parent="menu_helpdesk_employee"
sequence="12" sequence="12"
action="action_helpdesk_ticket_employee_request" action="action_helpdesk_ticket_employee_request"
groups="helpdesk_employee_request.group_helpdesk_employee,helpdesk_employee_request.group_helpdesk_Secretary"/> groups="helpdesk_employee_request.group_helpdesk_employee,helpdesk_employee_request.group_helpdesk_Secretary,helpdesk_employee_request.group_odex25_helpdesk_direct_manager"/>
<menuitem id="menu_helpdesk_employee_direct_manager"
name="Requests by My Employees"
parent="menu_helpdesk_employee"
action="action_helpdesk_ticket_direct_manager"
groups="helpdesk_employee_request.group_odex25_helpdesk_direct_manager"
sequence="30"/>
</odoo> </odoo>

View File

@ -3556,7 +3556,7 @@ msgstr "فقط أعضاء مجموعة '%s' يمكنهم اعتماد هذه ا
#. module: odex25_helpdesk #. module: odex25_helpdesk
#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 #: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0
msgid "Only the employee's manager can approve this stage." msgid "Only the employee's manager can proceed with this stage."
msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة." msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة."
#. module: odex25_helpdesk #. module: odex25_helpdesk

View File

@ -467,6 +467,9 @@ class odex25_helpdeskStage(models.Model):
user_id = fields.Many2one('res.users', string="Approver User") user_id = fields.Many2one('res.users', string="Approver User")
group_id = fields.Many2one('res.groups', string="Approver Group") group_id = fields.Many2one('res.groups', string="Approver Group")
next_stage = fields.Many2one('odex25_helpdesk.stage', string="Next Stage")
previous_stage = fields.Many2one('odex25_helpdesk.stage', string="Previous Stage")
show_button_next = fields.Boolean(string="Show Next Stage Button") show_button_next = fields.Boolean(string="Show Next Stage Button")
show_button_previous = fields.Boolean(string="Show Previous Stage Button") show_button_previous = fields.Boolean(string="Show Previous Stage Button")

View File

@ -322,6 +322,17 @@ class odex25_helpdeskTicket(models.Model):
show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True) show_button_next = fields.Boolean(related='stage_id.show_button_next', store=True)
show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True) show_button_previous = fields.Boolean(related='stage_id.show_button_previous', store=True)
show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True) show_button_rejection = fields.Boolean(related='stage_id.final_rejection', store=True)
manager_id = fields.Many2one('res.users', string='Employee', readonly=True)
show_button_draft = fields.Boolean(related='stage_id.final_rejection_stage', store=True)
@api.onchange('partner_id')
def _onchange_partner_id_set_employee(self):
if self.partner_id:
employee = self.env['hr.employee'].search([
('user_partner_id', '=', self.partner_id.id)
], limit=1)
self.manager_id = employee.sudo().parent_id.sudo().user_id.id if employee else False
@api.onchange('service_id') @api.onchange('service_id')
def _onchange_invoice_date(self): def _onchange_invoice_date(self):
@ -333,8 +344,8 @@ class odex25_helpdeskTicket(models.Model):
""" """
get the partner of the user get the partner of the user
""" """
user = self.env['res.users'].search([('partner_id', '=', self.partner_id.id)], limit=1) user = self.env['res.users'].sudo().search([('partner_id', '=', self.partner_id.id)], limit=1)
employee_id = self.env['hr.employee'].search([('user_id', '=', user.id)], limit=1) employee_id = self.env['hr.employee'].sudo().search([('user_id', '=', user.id)], limit=1)
self.department_id = employee_id.department_id self.department_id = employee_id.department_id
def activity_update(self): def activity_update(self):
@ -545,6 +556,7 @@ class odex25_helpdeskTicket(models.Model):
@api.model_create_multi @api.model_create_multi
def create(self, list_value): def create(self, list_value):
now = fields.Datetime.now() now = fields.Datetime.now()
# determine user_id and stage_id if not given. Done in batch. # determine user_id and stage_id if not given. Done in batch.
teams = self.env['odex25_helpdesk.team'].browse([vals['team_id'] for vals in list_value if vals.get('team_id')]) teams = self.env['odex25_helpdesk.team'].browse([vals['team_id'] for vals in list_value if vals.get('team_id')])
@ -573,6 +585,11 @@ class odex25_helpdeskTicket(models.Model):
'name': partner_name, 'name': partner_name,
'email': partner_email, 'email': partner_email,
}).id }).id
if vals.get('partner_id') and not vals.get('employee_id'):
employee = self.env['hr.employee'].sudo().search([
('user_partner_id', '=', vals['partner_id'])
], limit=1)
vals['manager_id'] = employee.sudo().parent_id.sudo().user_id.id if employee else False
# determine partner email for ticket with partner but no email given # determine partner email for ticket with partner but no email given
partners = self.env['res.partner'].browse([vals['partner_id'] for vals in list_value if partners = self.env['res.partner'].browse([vals['partner_id'] for vals in list_value if
@ -620,7 +637,6 @@ class odex25_helpdeskTicket(models.Model):
# apply SLA # apply SLA
tickets.sudo()._sla_apply() tickets.sudo()._sla_apply()
return tickets return tickets
def write(self, vals): def write(self, vals):
@ -974,67 +990,106 @@ class odex25_helpdeskTicket(models.Model):
return 'team_id' return 'team_id'
def _resolve_next_stage(self):
"""Return the best next stage according to the following order:
1) If `next_stage` is set and unique -> use it.
2) If there are multiple -> take the first one that intersects with the team's stages.
3) If not set -> use the first stage with a higher sequence than the current one within the team.
"""
self.ensure_one()
# --------------------------------------------------
# Validation Methods
# --------------------------------------------------
def _check_employee_restriction(self):
if self.stage_id.employee_created: if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id: if self.partner_id != self.env.user.partner_id:
raise ValidationError( raise ValidationError(
_("You cannot proceed to the next stage because you are not the employee linked to this ticket.")) _("You cannot proceed because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
def _check_manager_approval(self):
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].sudo().search([
('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee: if not employee:
raise ValidationError(_("Employee not found based on partner_id.")) raise ValidationError(_("Employee not found based on partner_id."))
if employee.sudo().parent_id.sudo().user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can proceed with this stage."))
if employee.parent_id.user_id != self.env.user: def _check_custom_approval(self):
raise ValidationError(_("Only the employee's manager can approve this stage."))
if self.stage_id.needs_approval: if self.stage_id.needs_approval:
if self.stage_id.is_group_approver: if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([ group_ext_id = self.env['ir.model.data'].sudo().search([
('model', '=', 'res.groups'), ('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id) ('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name ], limit=1).complete_name
if not self.env.user.has_group(group_ext_id): if not self.env.user.has_group(group_ext_id):
raise ValidationError( raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name) _("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else: else:
if self.stage_id.user_id != self.env.user: if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name) raise ValidationError(
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence) _("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
def _validate_stage_transition(self):
self.ensure_one()
self._check_employee_restriction()
self._check_manager_approval()
self._check_custom_approval()
# --------------------------------------------------
# Stage Resolution
# --------------------------------------------------
def _resolve_stage(self, forward=True):
self._validate_stage_transition()
if forward and self.stage_id.next_stage:
return self.stage_id.next_stage
if not forward and self.stage_id.previous_stage:
return self.stage_id.previous_stage
stages = self.team_id.stage_ids.sorted(
key=lambda s: s.sequence, reverse=not forward)
for st in stages: for st in stages:
if st.sequence > self.stage_id.sequence: if (forward and st.sequence > self.stage_id.sequence) or \
(not forward and st.sequence < self.stage_id.sequence):
return st return st
return False return False
# -------------------------------------------------- # --------------------------------------------------
# Action Buttons # Action Buttons
# -------------------------------------------------- # --------------------------------------------------
def action_confirm(self): def action_confirm(self):
for ticket in self: for ticket in self:
next_stage = ticket._resolve_next_stage() next_stage = ticket._resolve_stage(forward=True)
if not next_stage: if not next_stage:
raise ValidationError(_("No next stage is configured for this ticket!")) raise ValidationError(_("No next stage is configured for this ticket!"))
ticket.stage_id = next_stage ticket.stage_id = next_stage
def action_back(self):
for ticket in self:
prev_stage = ticket._resolve_stage(forward=False)
if not prev_stage:
raise ValidationError(_("No previous stage is configured for this ticket!"))
ticket.stage_id = prev_stage
def action_rejection(self): def action_rejection(self):
self.ensure_one() self.ensure_one()
rejection_stage = self.team_id.stage_ids.filtered(lambda s: s.final_rejection_stage) rejection_stage = self.team_id.stage_ids.filtered(
if rejection_stage: lambda s: s.final_rejection_stage)
self.stage_id = rejection_stage[0] if not rejection_stage:
else:
raise ValidationError(_("No final rejection stage is defined within the team's stages.")) raise ValidationError(_("No final rejection stage is defined within the team's stages."))
self.stage_id = rejection_stage[0]
def action_to_draft(self):
self.ensure_one()
self._check_custom_approval()
draft_stage = self.env['odex25_helpdesk.stage'].search(
[], order='sequence asc', limit=1)
if draft_stage:
self.stage_id = draft_stage.id
else:
raise ValidationError(_("No draft stage found."))
# --------------------------------------------------
# Override write to mark is_submitted when closing
# --------------------------------------------------
def write(self, vals): def write(self, vals):
if vals.get('stage_id'): if vals.get('stage_id'):
new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id']) new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id'])
@ -1042,43 +1097,120 @@ class odex25_helpdeskTicket(models.Model):
vals['is_submitted'] = True vals['is_submitted'] = True
return super().write(vals) return super().write(vals)
def _resolve_previous_stage(self):
self.ensure_one()
if self.stage_id.employee_created:
if self.partner_id != self.env.user.partner_id:
raise ValidationError(
_("You cannot proceed to the Previous stage because you are not the employee linked to this ticket."))
if self.stage_id.manager_approved:
employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
if not employee:
raise ValidationError(_("Employee not found based on partner_id."))
if employee.parent_id.user_id != self.env.user:
raise ValidationError(_("Only the employee's manager can Previous this stage."))
if self.stage_id.needs_approval:
if self.stage_id.is_group_approver:
group_ext_id = self.env['ir.model.data'].search([
('model', '=', 'res.groups'),
('res_id', '=', self.stage_id.group_id.id)
], limit=1).complete_name
if not self.env.user.has_group(group_ext_id):
raise ValidationError(
_("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
else:
if self.stage_id.user_id != self.env.user:
raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence, reverse=True)
for st in stages:
if st.sequence < self.stage_id.sequence:
return st
return False
def action_back(self): # def _resolve_next_stage(self):
for ticket in self: # """Return the best next stage according to the following order:
prev_stage = ticket._resolve_previous_stage() # 1) If `next_stage` is set and unique -> use it.
if not prev_stage: # 2) If there are multiple -> take the first one that intersects with the team's stages.
raise ValidationError(_("No previous stage is configured for this ticket!")) # 3) If not set -> use the first stage with a higher sequence than the current one within the team.
ticket.stage_id = prev_stage # """
#
# self.ensure_one()
# if self.stage_id.employee_created:
# if self.partner_id != self.env.user.partner_id:
# raise ValidationError(
# _("You cannot proceed to the next stage because you are not the employee linked to this ticket."))
# if self.stage_id.manager_approved:
# employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
#
# if not employee:
# raise ValidationError(_("Employee not found based on partner_id."))
#
# if employee.parent_id.user_id != self.env.user:
# raise ValidationError(_("Only the employee's manager can approve this stage."))
# if self.stage_id.needs_approval:
# if self.stage_id.is_group_approver:
# group_ext_id = self.env['ir.model.data'].search([
# ('model', '=', 'res.groups'),
# ('res_id', '=', self.stage_id.group_id.id)
# ], limit=1).complete_name
#
# if not self.env.user.has_group(group_ext_id):
# raise ValidationError(
# _("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
#
# else:
# if self.stage_id.user_id != self.env.user:
# raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
# if self.stage_id.next_stage:
# return self.stage_id.next_stage
#
# stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence)
# for st in stages:
# if st.sequence > self.stage_id.sequence:
# return st
# return False
# # --------------------------------------------------
# # Action Buttons
# # --------------------------------------------------
# def action_confirm(self):
# for ticket in self:
# next_stage = ticket._resolve_next_stage()
#
# if not next_stage:
# raise ValidationError(_("No next stage is configured for this ticket!"))
# ticket.stage_id = next_stage
#
# def action_rejection(self):
# self.ensure_one()
# rejection_stage = self.team_id.stage_ids.filtered(lambda s: s.final_rejection_stage)
# if rejection_stage:
# self.stage_id = rejection_stage[0]
# else:
# raise ValidationError(_("No final rejection stage is defined within the team's stages."))
#
# # --------------------------------------------------
# # Override write to mark is_submitted when closing
# # --------------------------------------------------
# def write(self, vals):
# if vals.get('stage_id'):
# new_stage = self.env['odex25_helpdesk.stage'].browse(vals['stage_id'])
# if new_stage.is_close:
# vals['is_submitted'] = True
# return super().write(vals)
#
# def _resolve_previous_stage(self):
# self.ensure_one()
# if self.stage_id.employee_created:
# if self.partner_id != self.env.user.partner_id:
# raise ValidationError(
# _("You cannot proceed to the Previous stage because you are not the employee linked to this ticket."))
# if self.stage_id.manager_approved:
# employee = self.env['hr.employee'].search([('user_partner_id', '=', self.partner_id.id)], limit=1)
#
# if not employee:
# raise ValidationError(_("Employee not found based on partner_id."))
#
# if employee.parent_id.user_id != self.env.user:
# raise ValidationError(_("Only the employee's manager can Previous this stage."))
# if self.stage_id.needs_approval:
# if self.stage_id.is_group_approver:
# group_ext_id = self.env['ir.model.data'].search([
# ('model', '=', 'res.groups'),
# ('res_id', '=', self.stage_id.group_id.id)
# ], limit=1).complete_name
#
# if not self.env.user.has_group(group_ext_id):
# raise ValidationError(
# _("Only members of the '%s' group can approve this stage.") % self.stage_id.group_id.name)
# else:
# if self.stage_id.user_id != self.env.user:
# raise ValidationError(_("Only '%s' can approve this stage.") % self.stage_id.user_id.name)
# if self.stage_id.previous_stage:
# return self.stage_id.previous_stage
# stages = self.team_id.stage_ids.sorted(key=lambda s: s.sequence, reverse=True)
# for st in stages:
# if st.sequence < self.stage_id.sequence:
# return st
# return False
#
# def action_back(self):
# for ticket in self:
# prev_stage = ticket._resolve_previous_stage()
# if not prev_stage:
# raise ValidationError(_("No previous stage is configured for this ticket!"))
# ticket.stage_id = prev_stage

View File

@ -127,6 +127,8 @@
</group> </group>
<group string="Stage" > <group string="Stage" >
<field name="final_rejection_stage"/> <field name="final_rejection_stage"/>
<field name="next_stage" attrs="{'invisible': [('final_rejection_stage', '=', True)]}"/>
<field name="previous_stage" attrs="{'invisible': [('final_rejection_stage', '=', True)]}"/>
</group> </group>
<group string="Administrative Actions" attrs="{'invisible': [('final_rejection_stage', '=', True)]}" > <group string="Administrative Actions" attrs="{'invisible': [('final_rejection_stage', '=', True)]}" >
@ -591,6 +593,8 @@
attrs="{'invisible': [('show_button_rejection', '=', False)]}" /> attrs="{'invisible': [('show_button_rejection', '=', False)]}" />
</header> </header>
<sheet> <sheet>
<field name="manager_id" invisible="1"/>
<field name="legend_blocked" invisible="1"/> <field name="legend_blocked" invisible="1"/>
<field name="legend_normal" invisible="1"/> <field name="legend_normal" invisible="1"/>
<field name="legend_done" invisible="1"/> <field name="legend_done" invisible="1"/>

View File

@ -26,8 +26,8 @@ class HelpdeskTicket(models.Model):
team = self.env['odex25_helpdesk.team'].search([('id','=',vals['team_id'])]) team = self.env['odex25_helpdesk.team'].search([('id','=',vals['team_id'])])
members = [member.id for member in team.member_ids] members = [member.id for member in team.member_ids]
members.append(team.team_leader_id.id) members.append(team.team_leader_id.id)
if self.env.user.id not in members: # if self.env.user.id not in members:
raise ValidationError(_("You're not allowed to create ticket in this team, please select a team that you are a member in.")) # raise ValidationError(_("You're not allowed to create ticket in this team, please select a team that you are a member in."))
res = super(HelpdeskTicket,self).create(vals) res = super(HelpdeskTicket,self).create(vals)
return res return res