# Phase 23 : Notifications Temps Réel POS

**Priorité :** P2
**Complexité :** MOYENNE
**Routes :** ~4
**Entités :** 1

---

## Objectif

Alertes dans l'interface POS pour les événements importants : stock bas, vente importante, remboursement en attente, session caisse longue. Badge compteur dans le header.

---

## Entité

### `PosNotification`
Table : `pos_notification`

| Champ | Type | Description |
|-------|------|-------------|
| id | int PK | |
| company | FK Company CASCADE | |
| targetUser | FK User SET NULL nullable | null = tous les managers de la company |
| type | string 30 | `low_stock`, `large_sale`, `refund_pending`, `session_long`, `daily_summary`, `loss_reported` |
| title | string 255 | |
| message | text | |
| link | string 500 nullable | URL relative vers la ressource concernée |
| isRead | bool default false | |
| readAt | datetime nullable | |
| priority | string 10, default `medium` | `low`, `medium`, `high`, `urgent` |
| createdAt | datetime Timestampable | |

**Index :** (company_id, target_user_id, is_read), (company_id, created_at)

---

## Service

### `PosNotificationService`

**`create(Company, string type, string title, string message, ?string link, ?User targetUser, string priority): PosNotification`**

**`getUnreadCount(Company, User): int`**

**`getNotifications(Company, User, ?limit): array`** — notifications pour cet utilisateur + notifications company sans targetUser

**`markAsRead(PosNotification, User): void`**

**`markAllAsRead(Company, User): void`**

### Déclencheurs (appels dans les services existants)

| Événement | Où l'ajouter | Type | Priorité |
|-----------|-------------|------|----------|
| Stock sous seuil | StockService (après décrémentation) | `low_stock` | high |
| Vente > seuil | SaleService.createSale() | `large_sale` | medium |
| Remboursement créé | RefundService.createRefund() | `refund_pending` | high |
| Perte signalée | StockLossService.createReport() | `loss_reported` | high |
| Session > 12h | CLI command (cron) | `session_long` | medium |

---

## Routes (~4)

| Route | Méthode | Path | Voter |
|-------|---------|------|-------|
| `manager_pos_notifications_index` | GET | `/manager/pos/notifications` | POS_ACCESS |
| `manager_pos_notifications_count` | GET (JSON) | `/manager/pos/notifications/count` | POS_ACCESS |
| `manager_pos_notifications_mark_read` | POST | `/manager/pos/notifications/{id}/read` | POS_ACCESS |
| `manager_pos_notifications_mark_all_read` | POST | `/manager/pos/notifications/read-all` | POS_ACCESS |

---

## Frontend

### Badge header
Dans `_menu_manager.html.twig` ou le header du layout :
- Badge compteur non-lu (rouge) à côté de l'icône cloche
- Polling AJAX `/manager/pos/notifications/count` toutes les 30 secondes
- Dropdown avec les 5 dernières notifications

### Stimulus controller
`pos-notifications_controller.js` :
- Auto-poll toutes les 30s
- Met à jour le badge compteur
- Affiche toast pour nouvelles notifications `urgent`/`high`

---

## Templates (1)
- `notifications/index.html.twig` — Liste complète paginée, filtres (type, lu/non-lu), marquer tout comme lu
