| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- # -*- coding: utf-8 -*-
- # Part of Odoo. See LICENSE file for full copyright and licensing details.
- from odoo import api, fields, models
- class HelpdeskTicket(models.Model):
- _inherit = 'helpdesk.ticket'
- request_type_id = fields.Many2one(
- 'helpdesk.request.type',
- string='Request Type',
- required=True,
- tracking=True,
- help="Type of ticket (e.g., Incident, Improvement)",
- default=lambda self: self._default_request_type_id()
- )
- request_type_code = fields.Char(
- related='request_type_id.code',
- string='Request Type Code',
- store=True,
- readonly=True,
- help="Code of the request type for conditional logic"
- )
- affected_module_id = fields.Many2one(
- 'helpdesk.affected.module',
- string='Affected Module',
- required=False,
- domain=[('active', '=', True)],
- help="Odoo module where the issue or improvement occurs"
- )
- affected_user_email = fields.Char(
- string='Affected User Email',
- tracking=True,
- help="Email address of the affected user (from another Odoo instance or external)"
- )
- business_impact = fields.Selection(
- [
- ('0', 'Critical'),
- ('1', 'High'),
- ('2', 'Normal'),
- ],
- string='Business Impact',
- default='2',
- tracking=True,
- help="Urgency reported by the client"
- )
- reproduce_steps = fields.Html(
- string='Steps to Reproduce',
- help="Detailed steps to reproduce the issue (only for Incidents)"
- )
- business_goal = fields.Html(
- string='Business Goal',
- help="Business objective for this improvement (only for Improvements)"
- )
- client_authorization = fields.Boolean(
- string='Client Authorization',
- default=False,
- help="Checkbox from web form indicating client authorization"
- )
- estimated_hours = fields.Float(
- string='Estimated Hours',
- help="Hours quoted after analysis"
- )
- approval_status = fields.Selection(
- [
- ('draft', 'N/A'),
- ('waiting', 'Waiting for Approval'),
- ('approved', 'Approved'),
- ('rejected', 'Rejected'),
- ],
- string='Approval Status',
- default='draft',
- tracking=True,
- help="Status of the approval workflow"
- )
- has_template = fields.Boolean(
- string='Has Template',
- compute='_compute_has_template',
- help="Indicates if the team has a template assigned"
- )
- attachment_ids = fields.One2many(
- 'ir.attachment',
- 'res_id',
- string='Attachments',
- domain=[('res_model', '=', 'helpdesk.ticket')],
- help="Files attached to this ticket"
- )
- @api.depends('team_id.template_id')
- def _compute_has_template(self):
- """Compute if team has a template"""
- for ticket in self:
- ticket.has_template = bool(ticket.team_id and ticket.team_id.template_id)
- @api.model
- def _default_request_type_id(self):
- """Default to 'Incident' type if available"""
- incident_type = self.env.ref(
- 'helpdesk_extras.type_incident',
- raise_if_not_found=False
- )
- return incident_type.id if incident_type else False
- def _get_template_fields(self):
- """Get template fields for this ticket's team"""
- self.ensure_one()
- if not self.team_id or not self.team_id.template_id:
- return self.env['helpdesk.template.field']
- return self.team_id.template_id.field_ids.sorted('sequence')
- @api.onchange('request_type_id', 'business_impact')
- def _onchange_compute_priority(self):
- """
- Auto-calculate priority based on request type and business impact.
- Only applies when both fields have values.
-
- Mapping:
- - Incident + Critical = 3 (Urgent)
- - Incident + High = 2 (High)
- - Incident + Normal = 1 (Normal)
- - Improvement + Critical = 2 (High)
- - Improvement + High = 1 (Normal)
- - Improvement + Normal = 0 (Low)
- """
- priority = self._compute_priority_from_impact()
- if priority is not None:
- self.priority = priority
- def _compute_priority_from_impact(self, request_type_id=None, business_impact=None):
- """
- Helper method to compute priority from request type and business impact.
- Can be used by onchange, create, and write methods.
- Returns the priority string or None if not applicable.
- """
- # Use provided values or instance values
- if request_type_id is None:
- request_type = self.request_type_id
- else:
- request_type = self.env['helpdesk.request.type'].browse(request_type_id) if isinstance(request_type_id, int) else request_type_id
-
- if business_impact is None:
- business_impact = self.business_impact
-
- if not request_type or not business_impact:
- return None
-
- type_code = request_type.code if hasattr(request_type, 'code') else ''
- if not type_code:
- return None
-
- # Priority mapping based on business_impact
- # business_impact: '0' = Critical, '1' = High, '2' = Normal
- # priority: '0' = Low, '1' = Normal, '2' = High, '3' = Urgent
- priority_map = {
- # Incidents get +1 priority boost
- ('incident', '0'): '3', # Incident + Critical = Urgent
- ('incident', '1'): '2', # Incident + High = High
- ('incident', '2'): '1', # Incident + Normal = Normal
- # Improvements have standard mapping
- ('improvement', '0'): '2', # Improvement + Critical = High
- ('improvement', '1'): '1', # Improvement + High = Normal
- ('improvement', '2'): '0', # Improvement + Normal = Low
- }
-
- key = (type_code, business_impact)
- return priority_map.get(key)
- @api.model_create_multi
- def create(self, vals_list):
- """Override create to auto-calculate priority for website form submissions."""
- for vals in vals_list:
- # Only calculate if priority not explicitly set and we have both fields
- if 'priority' not in vals or vals.get('priority') == '0':
- request_type_id = vals.get('request_type_id')
- business_impact = vals.get('business_impact')
- if request_type_id and business_impact:
- priority = self._compute_priority_from_impact(request_type_id, business_impact)
- if priority is not None:
- vals['priority'] = priority
- return super().create(vals_list)
- def write(self, vals):
- """Override write to recalculate priority when request_type or business_impact changes."""
- result = super().write(vals)
- # If either field was updated, recalculate priority for affected records
- if 'request_type_id' in vals or 'business_impact' in vals:
- for record in self:
- priority = record._compute_priority_from_impact()
- if priority is not None and record.priority != priority:
- # Use super().write to avoid recursion
- super(HelpdeskTicket, record).write({'priority': priority})
- return result
|