# SLA Timer & Breach Notification – Implementation Plan

> **Status: Implemented** (see implementation summary at end)

## Overview
Implement timer tracking (Response, In Review, Resolution, Auto Close) with breach detection and notifications per the Notification Channel settings.

---

## Status Mapping

| Spec Status      | Current Constant | Notes |
|------------------|------------------|-------|
| New              | OPEN (1)         | Response Time runs |
| In Review        | IN_REVIEW (2)    | Response stops, In Review starts |
| In Progress      | **MISSING**      | In Review stops, Resolution starts – *may need new status* |
| Waiting for Client | WAITING_CLIENT (4) | Resolution pauses |
| Client Reply     | CLIENT_REPLY (5) | Resolution resumes |
| Solved           | SOLVED (3)       | Resolution stops, Auto Close starts |
| Closed           | CLOSED (6)       | Auto Close stops (manual) |

**Recommendation:** Add `IN_PROGRESS = 7` to `TicketStatusConstants` for full spec alignment, or treat `IN_REVIEW` as both “In Review” and “In Progress” (Resolution starts when entering IN_REVIEW).

---

## 1. Database

### 1.1 `ticket_sla_timers` – Timer state
- `ticket_id`, `timer_type` (response|in_review|resolution|auto_close)
- `started_at`, `paused_at`, `resumed_at`, `stopped_at`
- `elapsed_minutes` (cached for support-type-aware calculations)
- `status` (running|paused|stopped)

### 1.2 `ticket_sla_delays` – Breach records
- `ticket_id`, `delay_type` (response_time|in_review_time|resolution_time)
- `breached_at`, `threshold_minutes`, `elapsed_minutes`
- `notified_at` (nullable – to avoid duplicate notifications)

### 1.3 Business hours config
- Add `business_hours` config (e.g. `8:00–18:00`, Sun–Thu) or reuse existing config.

---

## 2. Core Logic

### 2.1 Timer lifecycle (status changes)

| From → To      | Response Time | In Review Time | Resolution Time | Auto Close |
|----------------|---------------|----------------|-----------------|------------|
| (created)      | Start         | —              | —               | —          |
| OPEN → IN_REVIEW | Stop        | Start          | Start*          | —          |
| IN_REVIEW → IN_PROGRESS | — | Stop       | Start           | —          |
| * → WAITING_CLIENT | —       | —              | Pause           | —          |
| WAITING_CLIENT → CLIENT_REPLY | — | —  | Resume          | —          |
| * → SOLVED     | —             | —              | Stop            | Start      |
| SOLVED → CLOSED | —            | —              | —               | Stop       |

\* If no IN_PROGRESS: treat Resolution start = In Review start (both run in IN_REVIEW).

### 2.2 Support type (24/7 vs business hours)

- **24/7:** Elapsed = `diffInMinutes(start, end)`.
- **Business hours:** Count only minutes between 8:00 and 18:00, Sun–Thu (or configurable).

---

## 3. Components to Build

### 3.1 `SlaTimerService`
- Start / stop / pause / resume timers on ticket status change
- Compute elapsed minutes (24/7 or business hours)
- Detect breaches against SLA priority config
- Record delays in `ticket_sla_delays`

### 3.2 `SlaBreachNotificationService`
- Resolve effective channels from `NotificationChannelSetting` / `SlaNotificationOverride` for the ticket’s SLA and priority
- Determine recipients (users with `set-notification-channel`)
- Send via Email and Teams using existing infrastructure

### 3.3 Ticket observer / events
- On `created`: start Response Time
- On `updated` (status change): apply timer transitions per matrix above

### 3.4 Scheduled jobs
- **SlaBreachCheckCommand** – Periodic check for running timers that exceeded thresholds
- **AutoCloseResolvedTicketsCommand** – Already exists; add notification dispatch when auto-closing

---

## 4. Notification flow

1. Breach detected (immediate on status change or via scheduled job).
2. Get ticket’s SLA and priority → priority key (critical/high/medium/low).
3. Resolve matrix:
   - Use `SlaNotificationOverride` if exists for the SLA
   - Else use `NotificationChannelSetting` (default)
4. Select channels for that priority from `sla_breach_matrix` (e.g. Email, Teams).
5. Get recipients (users with `set-notification-channel` permission).
6. Send notifications per channel.

---

## 5. Existing pieces

- `NotificationChannelSetting` / `SlaNotificationOverride` – channel matrix
- `SlaPriorityTemplate` / SLA `priority_configuration` – thresholds (response_time, in_review_time, resolution_time, auto_close_after_resolved)
- `SupportTypeConstants` – 24/7 vs business_hours
- `PriorityTimeHelper::toMinutes()` – parse 24H, 7D, etc.
- `AutoCloseResolvedTicketsCommand` – auto-close logic
- `SendNotificationTrait` – in-app / FCM notifications
- `NotificationContract` – create notifications for users

---

## 6. Implementation order

1. Migrations for `ticket_sla_timers`, `ticket_sla_delays`.
2. `SlaTimerService` – timer state and elapsed-time calculation (incl. business hours).
3. `TicketStatusObserver` or events – update timers on status change.
4. Breach detection in `SlaTimerService` or dedicated service.
5. `SlaBreachNotificationService` – resolve channels and recipients, send notifications.
6. `SlaBreachCheckCommand` – cron for periodic breach checks.
7. Update `AutoCloseResolvedTicketsCommand` – send notification on auto-close.
8. Optional: add `IN_PROGRESS` status if the full spec is required.

---

## 7. Status decision

**Option A (recommended):** Add `IN_PROGRESS` to `TicketStatusConstants` and update UI/workflow.

**Implemented Option B:** Resolution starts in IN_REVIEW alongside In Review Time.

---

## Implementation Summary (Completed)

| Component | Location |
|-----------|----------|
| Migrations | `database/migrations/2026_02_11_120000_create_ticket_sla_timer_tables.php` |
| Models | `TicketSlaTimer`, `TicketSlaDelay` |
| Business Hours Helper | `app/Helpers/BusinessHoursHelper.php` |
| SlaTimerService | `app/Services/SlaTimerService.php` |
| SlaBreachNotificationService | `app/Services/SlaBreachNotificationService.php` |
| TicketObserver | `app/Observers/TicketObserver.php` |
| SlaBreachCheckCommand | `app/Console/Commands/SlaBreachCheckCommand.php` (scheduled every 15 min) |
| AutoCloseResolvedTicketsCommand | Updated with notification + business hours support |

**To run migrations:** `php artisan migrate`

**Option B:** Map “In Progress” to `IN_REVIEW` – Response stops and In Review starts on entering IN_REVIEW; Resolution also starts in IN_REVIEW (In Review and Resolution run in parallel there).
