225 lines
7.9 KiB
Markdown
225 lines
7.9 KiB
Markdown
# Complaint Escalation Dropdown Implementation
|
|
|
|
## Overview
|
|
Modified the escalate complaint modal to show a dropdown for selecting who to escalate to, with the staff's manager pre-selected as the default.
|
|
|
|
## Changes Made
|
|
|
|
### 1. Backend - `apps/complaints/ui_views.py`
|
|
|
|
#### Added Logger Import
|
|
```python
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
```
|
|
|
|
#### Updated `complaint_detail` View
|
|
Added escalation targets to the context:
|
|
|
|
```python
|
|
# Get escalation targets (for escalate modal dropdown)
|
|
escalation_targets = []
|
|
default_escalation_target = None
|
|
|
|
if complaint.hospital:
|
|
# Get hospital admins and department managers as escalation targets
|
|
escalation_targets = list(User.objects.filter(
|
|
is_active=True,
|
|
hospital=complaint.hospital
|
|
).filter(
|
|
models.Q(role='hospital_admin') | models.Q(role='department_manager') | models.Q(role='px_admin')
|
|
).select_related('department').order_by('first_name', 'last_name'))
|
|
|
|
# If complaint has staff with a manager, add manager as default
|
|
if complaint.staff and complaint.staff.report_to:
|
|
# Try to find the manager's user account
|
|
manager_user = None
|
|
if complaint.staff.report_to.user:
|
|
manager_user = complaint.staff.report_to.user
|
|
else:
|
|
# Try to find by email
|
|
manager_user = User.objects.filter(
|
|
email=complaint.staff.report_to.email,
|
|
is_active=True
|
|
).first()
|
|
|
|
if manager_user and manager_user not in escalation_targets:
|
|
escalation_targets.insert(0, manager_user)
|
|
|
|
if manager_user:
|
|
default_escalation_target = manager_user.id
|
|
```
|
|
|
|
Added to context:
|
|
```python
|
|
"escalation_targets": escalation_targets,
|
|
"default_escalation_target": default_escalation_target,
|
|
```
|
|
|
|
#### Updated `complaint_escalate` View
|
|
Modified to accept and handle the `escalate_to` parameter:
|
|
|
|
```python
|
|
reason = request.POST.get("reason", "")
|
|
escalate_to_id = request.POST.get("escalate_to", "")
|
|
|
|
# Get the escalation target user
|
|
escalate_to_user = None
|
|
if escalate_to_id:
|
|
escalate_to_user = User.objects.filter(id=escalate_to_id, is_active=True).first()
|
|
|
|
# If no user selected or user not found, default to staff's manager
|
|
if not escalate_to_user and complaint.staff and complaint.staff.report_to:
|
|
if complaint.staff.report_to.user:
|
|
escalate_to_user = complaint.staff.report_to.user
|
|
else:
|
|
# Try to find by email
|
|
escalate_to_user = User.objects.filter(
|
|
email=complaint.staff.report_to.email,
|
|
is_active=True
|
|
).first()
|
|
|
|
# Mark as escalated and assign to selected user
|
|
complaint.escalated_at = timezone.now()
|
|
if escalate_to_user:
|
|
complaint.assigned_to = escalate_to_user
|
|
complaint.save(update_fields=["escalated_at", "assigned_to"])
|
|
```
|
|
|
|
Features added:
|
|
- Creates detailed escalation message with target user name
|
|
- Sends email notification to the escalated user
|
|
- Logs audit with escalation details
|
|
- Shows success message with the name of the person escalated to
|
|
|
|
### 2. Frontend - `templates/complaints/complaint_detail.html`
|
|
|
|
#### Updated Escalate Modal
|
|
|
|
**Before:**
|
|
- Simple modal with just a reason text area
|
|
- No selection of who to escalate to
|
|
|
|
**After:**
|
|
- Dropdown to select escalation target (required field)
|
|
- Shows all hospital admins, department managers, and PX admins
|
|
- Manager of the staff is pre-selected by default (marked with [Manager (Default)])
|
|
- Shows department and role for each target
|
|
- Helpful text explaining the default selection
|
|
- Warning if no manager is assigned
|
|
|
|
**Template Code:**
|
|
```html
|
|
<div class="mb-3">
|
|
<label class="form-label">{% trans "Escalate To" %} <span class="text-danger">*</span></label>
|
|
<select name="escalate_to" class="form-select" required>
|
|
{% if escalation_targets %}
|
|
<option value="" disabled>{% trans "Select person to escalate to..." %}</option>
|
|
{% for target in escalation_targets %}
|
|
<option value="{{ target.id }}"
|
|
{% if default_escalation_target and target.id == default_escalation_target %}selected{% endif %}>
|
|
{{ target.get_full_name }}
|
|
{% if target.department %}
|
|
({{ target.department.name }})
|
|
{% endif %}
|
|
{% if target.role %}
|
|
- {{ target.get_role_display }}
|
|
{% endif %}
|
|
{% if complaint.staff and complaint.staff.report_to and complaint.staff.report_to.user and complaint.staff.report_to.user.id == target.id %}
|
|
[{% trans "Manager (Default)" %}]
|
|
{% endif %}
|
|
</option>
|
|
{% endfor %}
|
|
{% else %}
|
|
<option value="" disabled selected>{% trans "No escalation targets available" %}</option>
|
|
{% endif %}
|
|
</select>
|
|
{% if complaint.staff and complaint.staff.report_to %}
|
|
<div class="form-text text-muted">
|
|
<i class="bi bi-info-circle me-1"></i>
|
|
{% trans "Default selected is" %} <strong>{{ complaint.staff.report_to.get_full_name }}</strong> ...
|
|
</div>
|
|
{% else %}
|
|
<div class="form-text text-warning">
|
|
<i class="bi bi-exclamation-triangle me-1"></i>
|
|
{% trans "No manager assigned to this staff member..." %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
```
|
|
|
|
## User Flow
|
|
|
|
### Scenario 1: Staff Has Manager Assigned
|
|
1. Admin opens complaint detail page
|
|
2. Clicks "Escalate" button
|
|
3. Modal opens with dropdown pre-selected to staff's manager
|
|
4. Manager's name shows with "[Manager (Default)]" label
|
|
5. Admin can either:
|
|
- Keep the default (manager) and submit
|
|
- Select a different person from the dropdown
|
|
6. On submit:
|
|
- Complaint is assigned to the selected user
|
|
- Escalation update is created with details
|
|
- Selected user receives email notification
|
|
- Admin sees success message with selected person's name
|
|
|
|
### Scenario 2: Staff Has No Manager Assigned
|
|
1. Admin opens complaint detail page
|
|
2. Clicks "Escalate" button
|
|
3. Modal opens with dropdown but no default selection
|
|
4. Warning message shows: "No manager assigned to this staff member"
|
|
5. Admin must select a person from the dropdown
|
|
6. On submit: Same flow as above
|
|
|
|
## Escalation Target Selection
|
|
|
|
### Available Targets Include:
|
|
- **Staff's Manager** (default, if exists) - marked with "[Manager (Default)]"
|
|
- Hospital Admins
|
|
- Department Managers
|
|
- PX Admins
|
|
|
|
### Display Format:
|
|
```
|
|
John Smith (Cardiology) - Hospital Admin [Manager (Default)]
|
|
Sarah Johnson (Emergency) - Department Manager
|
|
Mike Davis (Surgery) - PX Admin
|
|
```
|
|
|
|
## API Changes
|
|
|
|
### `POST /complaints/{id}/escalate/`
|
|
|
|
**Parameters:**
|
|
- `reason` (required): Reason for escalation
|
|
- `escalate_to` (optional): User ID to escalate to (defaults to staff's manager)
|
|
|
|
**Behavior:**
|
|
- If `escalate_to` is provided and valid, escalates to that user
|
|
- If `escalate_to` is not provided or invalid, defaults to staff's manager
|
|
- If staff has no manager and no target is selected, escalation proceeds without assignment
|
|
|
|
## Files Modified
|
|
|
|
1. `apps/complaints/ui_views.py`
|
|
- Added logging import
|
|
- Updated `complaint_detail` to pass escalation targets
|
|
- Updated `complaint_escalate` to handle target selection
|
|
|
|
2. `templates/complaints/complaint_detail.html`
|
|
- Updated escalate modal with dropdown
|
|
- Added default selection logic
|
|
- Added help text and warnings
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Open complaint with staff who has manager → Manager pre-selected
|
|
- [ ] Open complaint with staff who has no manager → No default, warning shown
|
|
- [ ] Escalate with default manager → Success, manager gets email
|
|
- [ ] Escalate with different target → Success, selected person gets email
|
|
- [ ] Escalate without selecting target when no manager → Works without assignment
|
|
- [ ] Verify escalation appears in complaint timeline
|
|
- [ ] Verify audit log captures escalation details
|
|
- [ ] Verify assigned_to field is updated to selected user
|