Files
mercadodevida/work/artifacts/NOTIF-INVENTORY-ALERTS/documenter.md

99 lines
4.4 KiB
Markdown

# NOTIF-INVENTORY-ALERTS — Documenter notes
> Documenter: document · Estado: ready for close
## Cambio de contrato
### Nuevo endpoint
**`GET /api/inventory/admin/notifications`**
- **Auth:** requiere rol `admin` (HTTP 403 si no).
- **Response:**
```jsonc
{
"items": [
{ "id": "low_stock", "count": 7, "href": "/inventory?filter=low_stock", "label": "Stock bajo", "tone": "amber" },
{ "id": "out_of_stock", "count": 3, "href": "/inventory?filter=out_of_stock", "label": "Sin stock", "tone": "red" },
{ "id": "expired", "count": 2, "href": "/inventory?filter=expired", "label": "Caducados", "tone": "red" },
{ "id": "expiring_soon", "count": 5, "href": "/inventory?filter=expiring", "label": "Por caducar (≤30d)", "tone": "amber" },
{ "id": "low_margin", "count": 4, "href": "/inventory?filter=low_margin", "label": "Margen <30%", "tone": "red" }
],
"total": 21
}
```
- **Reglas:**
- Solo se incluyen items con `count > 0`.
- `total` es la suma de los counts de items incluidos.
- Items NO incluidos en respuesta cuando su count es 0 (no aparecen como `{count: 0}`).
### Cambio en filtro existente
`GET /api/inventory/admin/overview?filter=...` ahora acepta `expired` además
de los filtros anteriores (`all`, `in_stock`, `low_stock`, `out_of_stock`,
`expiring`, `low_margin`).
- **`expired`:** productos activos cuya `expiration_date < current_date`.
Ordenados por `expiration_date DESC NULLS LAST` (caducados más recientes primero).
### Cambio en UI
`OrderNotifications` (campanita del header admin) ahora tiene 3 tabs en lugar
de 2:
| Tab | Icono | Color del badge | Datos |
|---|---|---|---|
| Pendientes | 📦 | amber | stale orders (PENDING/SHIPPED >24h) |
| Esperando pago | 💳 | purple | orders AWAITING_PAYMENT |
| **Inventario** | 🏷️ | emerald | alertas operativas de inventario (este feature) |
- Solo visible para `user.role === 'admin'`.
- Polling cada 5 min vía `Promise.all([staleNotifications, awaitingPaymentNotifications, inventoryApi.notificationCounts])`.
- Badge total suma los 3 totales.
## Quién se ve afectado
- **Operador admin del backoffice:** ahora ve alertas de inventario en la campanita sin entrar a `/inventory`.
- **No-admin (customer, cashier):** sin cambios (no ven la campanita).
- **API consumers externos:** nuevo endpoint disponible (auth admin). Sin breaking change en endpoints existentes.
## Comportamiento observable
| Escenario | Antes | Después |
|---|---|---|
| Admin abre campanita | 2 tabs (Pendientes, Esperando pago) | 3 tabs (Pendientes, Esperando pago, **Inventario**) |
| Producto caduca | Sin notificación visible | Aparece en tab Inventario como "Caducados" (rojo), badge se incrementa |
| Producto entra en stock bajo (<5) | Sin notificación visible | Aparece en tab Inventario como "Stock bajo" (amber), badge se incrementa |
| Producto baja de margen 30% | Sin notificación visible | Aparece en tab Inventario como "Margen <30%" (rojo), badge se incrementa |
| Click en cualquier alerta de inventario | n/a | Navega a `/inventory?filter=...` con la lista filtrada |
## Notas operacionales
- **Umbrales hardcoded:** 5 unidades (low_stock), 30 días (expiring), 30% (low_margin). Consistente con los filtros existentes. Si en el futuro el operador pide flexibilidad, se mueven a `store_settings` en otro ticket.
- **Polling:** 5 minutos. Si la campanita está abierta, el polling refresca los 3 endpoints. Latencia añadida: <50ms (3er endpoint).
- **No hay emails:** las alertas son solo in-app. Si en el futuro se piden emails, sería un nuevo ticket en el módulo `notifications`.
## Notas de release (sugeridas)
```
feat(notif-inventory-alerts): admin bell shows inventory alerts (low stock, out of stock, expired, expiring, low margin)
Adds GET /api/inventory/admin/notifications (admin role) with 5 count types.
Extends OrderNotifications header bell with third tab "Inventario".
Extends inventory filter enum with 'expired' (expiration_date < current_date).
5/5 unit tests for the new endpoint; tsc + next build green.
```
## Cross-references
- architect.md §2 diseño de las 3 piezas (backend, helper, frontend).
- implementer.md §3 detalle de los cambios y evidencia.
- reviewer.json 10/12 checks PASS + 2 PASS_WITH_NOTE.
- security.json 10/10 checks PASS.
- qa.json 8/9 AC + 4/4 integration + 3/3 regression.
## Próximo stage
**close (leader)**: ejecutar `scripts/close_feature.py NOTIF-INVENTORY-ALERTS`.