99 lines
4.4 KiB
Markdown
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`. |