diff --git a/odex25_helpdesk/helpdesk_employee_request/i18n/ar_001.po b/odex25_helpdesk/helpdesk_employee_request/i18n/ar_001.po index 6d30fd909..8f3c12e49 100644 --- a/odex25_helpdesk/helpdesk_employee_request/i18n/ar_001.po +++ b/odex25_helpdesk/helpdesk_employee_request/i18n/ar_001.po @@ -187,3 +187,99 @@ msgstr "" msgid "محجوب" msgstr "" + + + + + + + + + + + + + + + + + + + + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "No previous stage is configured for this ticket!" +msgstr "لا توجد مرحلة سابقة مهيئة لهذه التذكرة!" + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +#, python-format +msgid "Only members of the '%s' group can approve this stage." +msgstr "فقط أعضاء مجموعة '%s' يمكنهم اعتماد هذه المرحلة." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "Only the employee's manager can approve this stage." +msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +#, python-format +msgid "Only '%s' can approve this stage." +msgstr "فقط '%s' يمكنه اعتماد هذه المرحلة." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "Employee not found based on partner_id." +msgstr "الموظف غير موجود بناءً على partner_id." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "You cannot proceed to the previous stage because you are not the employee linked to this ticket." +msgstr "لا يمكنك الانتقال إلى المرحلة السابقة لأنك لست الموظف المرتبط بهذه التذكرة." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "No final rejection stage is defined within the team's stages." +msgstr "لا توجد مرحلة رفض نهائي محددة ضمن مراحل الفريق." + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "No next stage is configured for this ticket!" +msgstr "لا توجد مرحلة تالية مهيئة لهذه التذكرة!" + +#. module: helpdesk_employee_request +#: code:addons/helpdesk_employee_request/models/helpdesk.py:0 +msgid "You cannot proceed to the next stage because you are not the employee linked to this ticket." +msgstr "لا يمكنك الانتقال إلى المرحلة التالية لأنك لست الموظف المرتبط بهذه التذكرة." + + +#. module: helpdesk_employee_request +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form +msgid "Send" +msgstr "إرسال" + +#. module: helpdesk_employee_request +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form +msgid "Previous" +msgstr "السابق" + +#. module: helpdesk_employee_request +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.odex25_helpdesk_ticket_vip_view_form +#: model_terms:ir.ui.view,arch_db:helpdesk_employee_request.ticket_request_view_form +msgid "Rejection" +msgstr "رفض" + + + + + + + + + + + diff --git a/odex25_helpdesk/helpdesk_employee_request/models/helpdesk.py b/odex25_helpdesk/helpdesk_employee_request/models/helpdesk.py index ebf41651f..0a63da8f8 100644 --- a/odex25_helpdesk/helpdesk_employee_request/models/helpdesk.py +++ b/odex25_helpdesk/helpdesk_employee_request/models/helpdesk.py @@ -6,6 +6,7 @@ from lxml import etree import json import simplejson import logging +from odoo.exceptions import UserError, ValidationError _logger = logging.getLogger(__name__) @@ -38,7 +39,9 @@ class HelpdeskTicket(models.Model): ('vip', 'VIP'), ('request', 'Request'), ('secretary', 'Secretary')]) - + 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_rejection = fields.Boolean(related='stage_id.final_rejection', store=True) @api.model def create(self, vals): """ @@ -78,3 +81,113 @@ class HelpdeskTicket(models.Model): self.partner_email = self.partner_id.email res = {'domain': {'partner_id': [('id', '=', [self.requester_id.partner_id.id])]}} 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: + 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) + 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 \ No newline at end of file diff --git a/odex25_helpdesk/helpdesk_employee_request/views/help_request_view.xml b/odex25_helpdesk/helpdesk_employee_request/views/help_request_view.xml index d31596977..ad231a6c3 100644 --- a/odex25_helpdesk/helpdesk_employee_request/views/help_request_view.xml +++ b/odex25_helpdesk/helpdesk_employee_request/views/help_request_view.xml @@ -41,8 +41,17 @@
- + + + + + + +
@@ -83,8 +92,18 @@
- + + + + + + + +
@@ -94,6 +113,7 @@
+ diff --git a/odex25_helpdesk/odex25_helpdesk/__manifest__.py b/odex25_helpdesk/odex25_helpdesk/__manifest__.py index 75df5c209..fed98d33d 100644 --- a/odex25_helpdesk/odex25_helpdesk/__manifest__.py +++ b/odex25_helpdesk/odex25_helpdesk/__manifest__.py @@ -39,7 +39,7 @@ Features: 'data': [ 'security/odex25_helpdesk_security.xml', 'security/ir.model.access.csv', - 'data/digest_data.xml', + # 'data/digest_data.xml', 'data/mail_data.xml', # 'data/odex25_helpdesk_data.xml', 'views/odex25_helpdesk_views.xml', diff --git a/odex25_helpdesk/odex25_helpdesk/i18n/ar.po b/odex25_helpdesk/odex25_helpdesk/i18n/ar.po index 056288563..c039f08f2 100644 --- a/odex25_helpdesk/odex25_helpdesk/i18n/ar.po +++ b/odex25_helpdesk/odex25_helpdesk/i18n/ar.po @@ -3487,3 +3487,120 @@ msgstr "نيابة عن المستخدم" msgid "Phone Number" msgstr "رقم الهاتف" + + + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__manager_approved +msgid "Direct Manager Approved" +msgstr "إعتماد المدير المباشر" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__final_rejection +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_rejection +msgid "Final Rejection" +msgstr "الرفض النهائي" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__final_rejection_stage +msgid "Final Rejection Stage" +msgstr "مرحلة الرفض النهائي" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__show_button_next +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_next +msgid "Show Next Stage Button" +msgstr "إظهار زر المرحلة التالية" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__show_button_previous +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_ticket__show_button_previous +msgid "Show Previous Stage Button" +msgstr "إظهار زر المرحلة السابقة" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__employee_created +msgid "Employee Created" +msgstr "تم إنشاء الموظف" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__group_id +msgid "Approver Group" +msgstr "مجموعة صاحب الصلاحية" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__user_id +msgid "Approver User" +msgstr "صاحب الاعتماد" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__is_group_approver +msgid "Is Group Approver?" +msgstr "هل صاحب الصلاحية مجموعة؟" + +#. module: odex25_helpdesk +#: model:ir.model.fields,field_description:odex25_helpdesk.field_odex25_helpdesk_stage__needs_approval +msgid "Requires Approval?" +msgstr "هل تحتاج إلى موافقة؟" + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "No previous stage is configured for this ticket!" +msgstr "لا توجد مرحلة سابقة مهيئة لهذه التذكرة!" + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +#, python-format +msgid "Only members of the '%s' group can approve this stage." +msgstr "فقط أعضاء مجموعة '%s' يمكنهم اعتماد هذه المرحلة." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "Only the employee's manager can approve this stage." +msgstr "فقط مدير الموظف يمكنه اعتماد هذه المرحلة." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +#, python-format +msgid "Only '%s' can approve this stage." +msgstr "فقط '%s' يمكنه اعتماد هذه المرحلة." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "Employee not found based on partner_id." +msgstr "الموظف غير موجود بناءً على partner_id." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "You cannot proceed to the previous stage because you are not the employee linked to this ticket." +msgstr "لا يمكنك الانتقال إلى المرحلة السابقة لأنك لست الموظف المرتبط بهذه التذكرة." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "No final rejection stage is defined within the team's stages." +msgstr "لا توجد مرحلة رفض نهائي محددة ضمن مراحل الفريق." + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "No next stage is configured for this ticket!" +msgstr "لا توجد مرحلة تالية مهيئة لهذه التذكرة!" + +#. module: odex25_helpdesk +#: code:addons/odex25_helpdesk/models/odex25_helpdesk_ticket.py:0 +msgid "You cannot proceed to the next stage because you are not the employee linked to this ticket." +msgstr "لا يمكنك الانتقال إلى المرحلة التالية لأنك لست الموظف المرتبط بهذه التذكرة." + +#. module: odex25_helpdesk +#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form +msgid "Send" +msgstr "إرسال" + +#. module: odex25_helpdesk +#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form +msgid "Previous" +msgstr "السابق" + +#. module: odex25_helpdesk +#: model_terms:ir.ui.view,arch_db:odex25_helpdesk.odex25_helpdesk_ticket_view_form +msgid "Rejection" +msgstr "رفض" diff --git a/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk.py b/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk.py index f1015aa26..7a949c52b 100644 --- a/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk.py +++ b/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk.py @@ -462,6 +462,25 @@ class odex25_helpdeskStage(models.Model): 'Grey Kanban Label', default=lambda s: _('In Progress'), translate=True, required=True, help='Override the default value displayed for the normal state for kanban selection, when the task or issue is in that stage.') + needs_approval = fields.Boolean(string="Requires Approval?") + is_group_approver = fields.Boolean(string="Is Group Approver?") + + user_id = fields.Many2one('res.users', string="Approver User") + group_id = fields.Many2one('res.groups', string="Approver Group") + + show_button_next = fields.Boolean(string="Show Next Stage Button") + show_button_previous = fields.Boolean(string="Show Previous Stage Button") + employee_created = fields.Boolean(string="Employee Created") + manager_approved = fields.Boolean(string="Direct Manager Approved") + final_rejection = fields.Boolean( + string="Final Rejection", + default=False, + help="Indicates whether this stage represents the final rejection of the ticket." + ) + final_rejection_stage = fields.Boolean( + string="Final Rejection Stage", + help="Mark this stage as the final rejection stage." + ) def unlink(self): stages = self default_team_id = self.env.context.get('default_team_id') diff --git a/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk_ticket.py b/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk_ticket.py index 3ee17259a..d4762536f 100644 --- a/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk_ticket.py +++ b/odex25_helpdesk/odex25_helpdesk/models/odex25_helpdesk_ticket.py @@ -7,6 +7,7 @@ from random import randint from odoo import api, fields, models, tools, _ from odoo.osv import expression from odoo.exceptions import AccessError +from odoo.exceptions import UserError, ValidationError TICKET_PRIORITY = [ ('0', 'All'), @@ -318,6 +319,9 @@ class odex25_helpdeskTicket(models.Model): on_behalf = fields.Many2one('hr.employee', string="On behalf of") emp_req = fields.Boolean(default=False) schedule_date = fields.Datetime("Scheduled Date") + 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_rejection = fields.Boolean(related='stage_id.final_rejection', store=True) @api.onchange('service_id') def _onchange_invoice_date(self): @@ -968,3 +972,113 @@ class odex25_helpdeskTicket(models.Model): def _rating_get_parent_field_name(self): 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() + 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) + 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 \ No newline at end of file diff --git a/odex25_helpdesk/odex25_helpdesk/views/odex25_helpdesk_views.xml b/odex25_helpdesk/odex25_helpdesk/views/odex25_helpdesk_views.xml index 83bd24b53..2da058900 100644 --- a/odex25_helpdesk/odex25_helpdesk/views/odex25_helpdesk_views.xml +++ b/odex25_helpdesk/odex25_helpdesk/views/odex25_helpdesk_views.xml @@ -125,6 +125,32 @@

+ + + + + + + + + + + + + + + + + + + + + +
@@ -548,12 +574,21 @@
+ + + + +