feat(api,web): c2 consulta de clientes — list + search + auth flow

prisma: modelo Client + migração 20260527225728_add_client + seed dev (10 clientes)
api: GET /clients (list, busca, filtro atividade/financeiro, paginação) + GET /clients/:id
     rep vê carteira própria; supervisor/admin vê tudo; activityStatus calculado de lastOrderAt
@sar/api-interface: ClientSummarySchema, ClientDetailSchema, ClientListResponseSchema
web: ClientsPage (tabela AntD, busca, filtro), DevLogin (token dev), authStore, Bearer no apiFetch
oq-4 resolvida: creditLimit gerenciado no SAR

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 23:08:57 +00:00
parent 2a8be3fd82
commit 14c8350216
26 changed files with 1394 additions and 84 deletions

View File

@@ -412,7 +412,32 @@
**Pendente próxima sessão:**
1. **OpenTelemetry SDK** plugar quando entrar no catálogo.
2. **Modelagem C2** modelo `Client` no Prisma schema + migração + endpoint `GET /clients`. Requer OQ-1/OQ-4 resolvidos com primeiro cliente.
2. **C2 ficha do cliente**`ClientDetailPage` (web), endpoint detalhe já existe; precisa de UI.
3. **C3 Consulta de Pedidos Históricos** — modelo `Order` + `OrderItem` no Prisma + endpoint.
### 2026-05-27 — C2 Consulta de Clientes COMPLETO ✅
**OQ-4 resolvida:** Limite de crédito gerenciado no SAR (admin/supervisor define; SAR é fonte da verdade).
**Entregas:**
- **Prisma schema:** modelo `Client` + enum `FinancialStatus`. Migração `20260527225728_add_client` aplicada.
Campos: taxId (unique), endereço (JSON), creditLimit (Decimal, null = não definido), repId, lastOrderAt/Value (desnorm. de Orders), openOrdersCount, erpCode, syncedAt, deletedAt (soft delete).
- **Contratos Zod:** `@sar/api-interface``ClientSummarySchema`, `ClientDetailSchema`, `ClientListResponseSchema`, `ClientListQuerySchema`. `activityStatus` calculado em runtime (não persiste — evita drift).
- **API:** `ClientsModule``GET /api/v1/clients` (list, search, paginação, filtro atividade) + `GET /api/v1/clients/:id`. Rep vê só carteira (`repId = userId`); supervisor/manager/admin vê tudo. `activityStatus` computado de `lastOrderAt` (thresholds: 30d alert, 60d inactive — FR-2.3).
- **Seed dev:** 10 clientes fictícios brasileiros (8 do user-001, 2 do user-002) com dados variados de atividade e situação financeira.
- **Web:** `ClientsPage` (Rafael cockpit) com tabela AntD (busca, filtro atividade, paginação). `DevLogin` para adquirir token em dev. `authStore` (localStorage dev). `/clientes` e `/clientes/:id` no router.
- **Smoke test:** `GET /clients` sem token → 401 ✓. Com token rep user-001 → 8 clientes ✓. Filtro `?status=inactive` → 1 resultado ✓. Busca `?q=padaria` → 1 resultado ✓.
**Pendente próxima sessão:**
1. `ClientDetailPage` — UI da ficha (web); endpoint já existe.
2. C3 — modelo `Order` + `OrderItem` + endpoint `GET /clients/:id/orders`.
3. OpenTelemetry SDK.
---