# Phase 3A - Waiting List Workflow

Date/time: 2026-05-29 12:30:00 +03:00

## What Was Implemented

| Area | Result | Files |
|---|---|---|
| Pending/unassigned data model | `conversations.assigned_to` is nullable; pending waiting conversations use `status = pending` and `assigned_to = null`. | `database/migrations/2026_05_29_120000_prepare_conversations_for_waiting_list.php`, `app/Models/Conversation.php` |
| Source phone capture | Incoming conversations store `source_phone_number_id` for filtering and routing context. | Migration, `ProcessIncomingMessageJob.php` |
| Routing behavior | Dedicated active agents and active employees matching the source WhatsApp phone ID receive open conversations. Unknown/unroutable conversations become pending/unassigned. | `ConversationRouter.php`, `AssignmentResult.php`, `ProcessIncomingMessageJob.php` |
| Duplicate prevention | Existing conversation for the same contact is reused. Pending conversations receive new messages without duplicate waiting rows. | `ProcessIncomingMessageJob.php` |
| Waiting List page | `/admin/waiting-list` is now an operational Filament table with customer, phone, last message, waiting duration, unread count, source phone ID, status, suggested agent, filters, and Assign action. | `WaitingList.php`, `waiting-list.blade.php` |
| Waiting List API | Added authenticated API endpoints for listing and assigning waiting conversations. | `WaitingListController.php`, `routes/api.php` |
| Assignment action | Admin can assign any waiting conversation to an active employee. Supervisor can assign team-scoped waiting conversations only to active employees under the same team. | `WaitingListService.php`, `ConversationPolicy.php` |
| Employee restriction | Employees cannot access Waiting List page/API and cannot assign by direct API call. | `WaitingList.php`, `ConversationPolicy.php`, tests |
| Assignment Log | Every successful waiting-list assignment creates an `assignments` row with `manual_transfer` and `assigned_by` set. | `WaitingListService.php` |
| Dashboard queue | Dashboard queue now reads the real waiting-list query and employees no longer see the Waiting List navigation item. | `ChatWorkspaceController.php`, `chat-workspace.blade.php` |

## Routing Behavior

| Scenario | Behavior |
|---|---|
| Contact has dedicated active employee | Create/update open conversation assigned to that employee; assignment log is created for new routed conversations. |
| Source WhatsApp phone ID belongs to an active employee | Create/update open conversation assigned to that employee. |
| Dedicated employee exists but inactive | Conversation becomes pending/unassigned and keeps that employee's team scope for supervisor visibility. |
| No valid employee found | Conversation becomes pending/unassigned with no team scope; admin can assign it. |
| Existing open conversation with valid assignee | Keep assignment and update latest message/unread count. |
| Existing pending conversation | Keep pending; update the same row and move it up by `last_message_at`. |
| Existing closed conversation | Reopen if the old assignee is still a valid active employee; otherwise reroute or send to waiting list. |

## Role Permissions

| Role | Waiting List Access | Assign Rules |
|---|---|---|
| Admin | Full access | Can assign any pending/unassigned conversation to any active employee. |
| Supervisor | Team-scoped access | Can assign only conversations scoped to their team, and only to active employees under that team. |
| Employee | No access | Cannot view or assign waiting conversations. |

## Remaining Limitations

- Supervisor can only see unassigned conversations that have `department_id` equal to their team. Global waiting conversations with no team scope remain admin-only.
- Assignment targets are intentionally limited to active `agent` users. Supervisors are not assignment targets in Phase 3A.
- Waiting List is Filament/server-rendered; no WebSocket/Reverb or live push was added.
- Reports, Settings, Employee Profile, and deeper navigation performance work are still outside this phase.

## Verification

| Check | Result |
|---|---|
| `phpunit.xml` isolation | Confirmed sqlite `:memory:` before tests. |
| Route list | Passed; `/admin/waiting-list`, `GET /api/waiting-list`, and `POST /api/waiting-list/{conversation}/assign` exist. |
| Full test suite | Passed: 34 tests, 111 assertions. |
| Development DB safety | `database/database.sqlite` timestamp stayed unchanged before/after tests. |

