# Explanation Request Workflow Implementation ## Overview Modified the explanation request system with the following workflow: 1. **Initial Request**: Link sent to staff, informational notification to manager 2. **Escalation**: If staff doesn't respond within SLA, manager gets a link to respond 3. **Manager Response**: Manager can submit their perspective when escalated ## Workflow Diagram ``` ┌─────────────────────────────────────────────────────────────────────┐ │ EXPLANATION REQUEST FLOW │ └─────────────────────────────────────────────────────────────────────┘ INITIAL REQUEST │ ├──► Staff receives: Link to submit explanation │ (can respond immediately) │ └──► Manager receives: Informational email only (no link - just notification) │ │ ┌──────────────┴──────────────┐ │ │ [Staff responds] [No response] │ │ ▼ ▼ Explanation saved After SLA deadline System notifies (e.g., 48 hours) assigned user │ ▼ ESCALATION TRIGGERED │ ▼ Manager receives: Link to submit explanation as escalation response │ ▼ [Manager responds] │ ▼ Manager explanation saved Linked to staff explanation ``` ## Changes Made ### 1. Backend API (`apps/complaints/views.py`) #### `request_explanation` method **Behavior:** - Creates ONE explanation record (for staff only) - Sends link to staff member - Sends informational email to manager (no link, no token) **Staff Email:** - Subject: "Explanation Request - Complaint #..." - Contains: Link to submit explanation - SLA deadline applies **Manager Email:** - Subject: "Staff Explanation Request Notification - Complaint #..." - Contains: Complaint details for awareness - States: "If no response is received within the SLA deadline, you will receive a follow-up request with a link to provide your perspective as the manager." - NO link/token included **API Response:** ```json { "success": true, "results": [ { "recipient_type": "staff", "recipient": "Dr. Ahmed Smith", "sent": true, "explanation_id": "..." }, { "recipient_type": "manager", "recipient": "Dr. Sarah Johnson", "sent": true, "informational_only": true, "note": "Manager will receive link if staff does not respond within SLA" } ], "staff_explanation_id": "...", "manager_notified": true } ``` #### `resend_explanation` method **Behavior:** - Only resends to staff member (regenerates token) - Manager informational email is NOT resent (they already received it) ### 2. Celery Tasks (`apps/complaints/tasks.py`) #### `check_overdue_explanation_requests` task **Behavior:** - Runs every 15 minutes - Finds staff explanations that are overdue (past SLA deadline) - Creates NEW explanation record for manager with: - Unique token/link - Fresh SLA deadline - Escalation metadata - Sends email to manager with link **Manager Escalation Email:** - Subject: "Explanation Request: Complaint #..." - Contains: Link to submit explanation - Message: "ESCALATED: [Staff Name] did not provide an explanation within the SLA deadline..." **Escalation Linkage:** ```python staff_explanation.escalated_to_manager = manager_explanation staff_explanation.escalated_at = now ``` ### 3. UI Template (`templates/complaints/complaint_detail.html`) **Before Request:** - Shows staff as primary recipient (with link) - Shows manager as "Notification Only" - Note: "Will receive link only if staff doesn't respond within SLA" **After Request:** - Shows staff explanation status - Shows manager escalation status (when applicable) - Distinguishes between: - "Explanation from Staff" / "Pending Staff Explanation" - "Explanation from Manager (Escalated)" / "Pending Manager Explanation" ## Data Model ### Staff Explanation Record ```python { "id": "uuid", "staff": staff_id, "token": "secure_token_for_staff", "is_used": false/true, "sla_due_at": "2026-02-12T10:00:00Z", "escalated_to_manager": null or manager_explanation_id, "escalated_at": null or timestamp, "metadata": { "escalation_level": 0 // Staff is level 0 } } ``` ### Manager Explanation Record (Created on Escalation) ```python { "id": "uuid", "staff": manager_id, // The manager "token": "secure_token_for_manager", "is_used": false/true, "sla_due_at": "2026-02-14T10:00:00Z", // Fresh SLA "escalated_to_manager": null, // Manager can also escalate up "metadata": { "escalated_from_explanation_id": "staff_explanation_id", "escalation_level": 1, "original_staff_id": "staff_id", "original_staff_name": "Staff Name", "is_escalation": True } } ``` ## API Endpoints ### `POST /api/complaints/{id}/request_explanation/` Send initial explanation request to staff + informational notification to manager. ### `POST /api/complaints/{id}/resend_explanation/` Resend explanation request to staff only (new token). ### `GET /complaints/{complaint_id}/explain/{token}/` Public form for submitting explanation (works for both staff and manager tokens). ## Escalation Hierarchy ``` Level 0: Staff (initial request with link) ↓ (if no response within SLA) Level 1: Manager (receives link via escalation) ↓ (if no response within SLA) Level 2: Manager's Manager (receives link via escalation) ↓ Level 3+: Continue up hierarchy... ``` ## Benefits of This Approach 1. **Staff Priority**: Staff gets first chance to respond with direct link 2. **Manager Awareness**: Manager is informed immediately but not burdened with link 3. **Clear Escalation Path**: Manager only gets involved if staff doesn't respond 4. **Audit Trail**: Clear record of escalation from staff to manager 5. **Fresh SLA**: Manager gets their own SLA deadline when escalated 6. **Parallel Visibility**: Both explanations visible in complaint detail ## Testing Scenarios ### Scenario 1: Staff Responds Immediately 1. Request explanation → Staff gets link, Manager gets notification 2. Staff clicks link and submits explanation 3. System shows "Explanation from Staff" as submitted 4. Manager escalation never triggered ### Scenario 2: Staff Doesn't Respond 1. Request explanation → Staff gets link, Manager gets notification 2. Staff doesn't respond within SLA (e.g., 48 hours) 3. Escalation task runs → Manager gets link 4. Manager submits explanation 5. System shows: - Staff: "Pending Explanation (Overdue)" - Manager: "Explanation from Manager (Escalated)" ### Scenario 3: No Manager Assigned 1. Request explanation → Only staff gets email 2. System shows warning "No manager assigned" 3. If staff doesn't respond, no escalation possible ## Files Modified 1. `apps/complaints/views.py` - `request_explanation` and `resend_explanation` methods 2. `apps/complaints/tasks.py` - `check_overdue_explanation_requests` task 3. `templates/complaints/complaint_detail.html` - UI updates ## Backward Compatibility - Existing staff explanations work as before - Manager escalation creates new explanation record - No database migrations required - API endpoints remain at same URLs