Sync detailed Pizza Digital PRDs for all SPECs

This commit is contained in:
Admin 2026-11-09 21:22:23 +00:00
parent efea024cbc
commit 2804755ab3
30 changed files with 1833 additions and 175 deletions

View file

@ -1,204 +1,111 @@
# PRD — Cardápio Joinville (o que a plataforma faz)
# PRD — Cardápio Joinville (Menu)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Módulo** | Cardápio / Menu (pesquisa regional → operação) |
| **Fonte Spec** | [`CARDAPIO-JOINVILLE.md`](CARDAPIO-JOINVILLE.md) · [`SPEC-CARDAPIO.md`](SPEC-CARDAPIO.md) |
| **Ambiente auditado** | https://pizza.itecnologys.com · VM125 · `v0.5.0` |
| **Loja piloto** | Pizza Digital Joinville (`pizza-digital-piloto`) |
| **Data auditoria** | 2026-11-09 |
| **Tipo** | PRD operacional (Spec × construído × passos de uso) |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/CARDAPIO-JOINVILLE.md + docs/SPEC-CARDAPIO.md` |
| **Módulo** | Cardápio / PDV sheet de pizza |
| **Rotas UI** | `/pdv` · Admin menu |
| **APIs** | `GET/POST/PATCH/DELETE /api/menu/*` · `GET /api/menu/sizes` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Contexto do desenvolvedor
O cardápio Joinville não é só uma lista de sabores: é o **catálogo canônico** que o PDV usa para montar `OrderItem`.
Pesquisa regional (`CARDAPIO-JOINVILLE.md`) virou seed + `PizzaSizeBase`. Preço catalogado = **Grande 40 cm**;
tamanho/split resolvem no pedido.
### Artefatos de código
- UI: `apps/web/src/PdvPage.tsx` (sheet tamanho/sabores)
- API: `apps/api/src/menu/menu.controller.ts` · `menu.service.ts` · `pizza-sizes.ts`
- Dados: `MenuCategory`, `MenuItem`, `PizzaSizeBase`, `MenuItemStation`, `MenuItemRecipeLine`
- Seed: `apps/api/prisma/seed.ts`
### Inventário auditado
8 categorias ativas · **92 itens ativos** · 6 tamanhos · cat. Broto legado `active=false`.
---
## 1. Entendimento da demanda
## 2. Processo — carregar cardápio no PDV
Documentar **cada Spec** não só como intenção, mas como **PRD da plataforma real**:
1. Operador autentica (`POST /api/auth/login` com `storeSlug`).
2. Front chama `GET /api/menu` → `{ pizzaSizes, categories[] }` filtrando `active=true`.
3. Front monta abas/lista por categoria.
4. Item com `halfHalf=true` abre sheet; demais vão direto ao carrinho.
1. Ler a Spec / pesquisa
2. Inspecionar o que está construído (UI + API + banco)
3. Descrever **passo a passo** o que o usuário faz
4. Marcar o que já funciona, o que é parcial e o que falta
Este arquivo é o **exemplo-piloto** usando `CARDAPIO-JOINVILLE.md`.
**Estados**
- Sem token → 401
- Categoria sem itens ativos → não deve renderizar (ou vazia)
- 🐛 Em 2026-11-09 a UI chegou a mostrar “Nenhuma categoria…” com API OK — validar fetch/storeSlug no client
---
## 2. Problema e objetivo
## 3. Processo — montar pizza (passo a passo)
### Problema
Pizzarias de Joinville vendem com nomenclatura inconsistente de tamanhos, sabores regionais e preços locais. Sem um cardápio único, PDV/KDS/canais divergem.
1. Atendente escolhe fulfillment: Entrega / Balcão / Mesa.
2. Clica sabor (ex.: Calabresa) → sheet.
3. Escolhe `sizeCode` (broto|pequena|media|grande|gigante|familia).
4. Sistema lê `maxFlavors` / `priceFactor` / `diameterCm` / `slices` de `PizzaSizeBase`.
5. Seleciona sabores até o limite; se exceder → erro UI.
6. Preço unitário = `max(priceCents dos sabores) * priceFactor`.
7. Opcional: borda (`Bordas especiais`).
8. Confirma → linha no pedido: `Pizza Grande 40cm · SaborA / SaborB`.
9. `POST /api/orders` com items (`sizeCode`, `halfHalf`, notes).
### Objetivo do módulo (construído)
Ser a **fonte da verdade do que a loja vende** no piloto Joinville: categorias, itens, preços base (Grande), tamanhos no pedido, split de sabores e acompanhamentos — alimentando o **PDV** e, depois, KDS/Central.
### Tabela de regras (congelada)
### Fora deste PRD
Saldo de estoque, NF, inventário → [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) / SmartStock.
| sizeCode | cm | fatias | max sabores | fator |
|----------|----|--------|-------------|-------|
| broto | 25 | 4 | 1 | 0,55 |
| pequena | 30 | 6 | 1 | 0,70 |
| media | 35 | 8 | 2 | 0,85 |
| grande | 40 | 12 | 3 | 1,00 |
| gigante | 45 | 16 | 4 | 1,20 |
| familia | 50 | 20 | 4 | 1,35 |
---
## 3. O que a pesquisa Joinville definiu vs o que existe hoje
## 4. Processo — CRUD gestor
| Tema (CARDAPIO-JOINVILLE) | Spec / pesquisa | Construído na plataforma (2026-11-09) | Status |
|---------------------------|-----------------|----------------------------------------|--------|
| 6 tamanhos (Broto→Família) | cm, fatias, sabores máx., fator preço | Tabela `PizzaSizeBase` com 6 sizeCodes ativos | ✅ |
| Preço base = Grande 40 cm | Sim | `MenuItem.priceCents` = preço Grande; PDV multiplica por `priceFactor` | ✅ |
| Split = maior sabor × fator | Sim | Sheet do PDV: escolhe tamanho + N sabores até `maxFlavors` | ✅ |
| Tradicionais alta rotação | Lista ~20 sabores | Cat. **Tradicionais** · 20 ativos (Calabresa, Mussarela, Frango Catupiry…) | ✅ |
| Regionais SC | Joinville, Linguiça Blumenau, Aipim, Catarina | Cat. **Da casa** · 6 ativos (+ Aipim Blumenau, Coração) | ✅ |
| Doces | 6 tipos | Cat. **Doces** · 6 ativos (Broto legado inativo) | ✅ |
| Bebidas / sucos / energéticos / vitaminas | Tabelas de mercado | 4 categorias · 57 itens ativos | ✅ |
| Bordas | Catupiry/Cheddar ~R$12–20 | Cat. **Bordas especiais** · 3 itens | ✅ |
| SKU Broto separado | Evitar no piloto | Cat. legado **Pizzas Broto** · `active=false` · 5 itens inativos | ✅ (legado) |
| Cardápio público PWA `/c/:slug` | Track C1 | Ainda não é o foco deste PRD | ⏳ |
| CRUD gestor no Admin | RF-MEN-01 | API CRUD existe; UI Admin menu | ⚠️ parcial |
### Inventário real (banco piloto)
| Categoria | Ativos | Inativos |
|-----------|--------|----------|
| Tradicionais | 20 | 1 |
| Da casa | 6 | 0 |
| Doces | 6 | 1 |
| Refrigerantes | 23 | 0 |
| Sucos | 14 | 0 |
| Energéticos | 8 | 0 |
| Vitaminas · frutas c/ leite | 12 | 0 |
| Bordas especiais | 3 | 0 |
| Pizzas Broto (legado) | 0 | 5 |
| **Total** | **92** | **7** |
### Tamanhos reais (`PizzaSizeBase`)
| sizeCode | Nome | cm | Fatias | Sabores máx. | Fator |
|----------|------|----|--------|--------------|-------|
| broto | Broto | 25 | 4 | 1 | 0,55 |
| pequena | Pequena | 30 | 6 | 1 | 0,70 |
| media | Media | 35 | 8 | 2 | 0,85 |
| grande | Grande | 40 | 12 | 3 | 1,00 |
| gigante | Gigante | 45 | 16 | 4 | 1,20 |
| familia | Familia | 50 | 20 | 4 | 1,35 |
1. Gestor com capability `menu.manage`.
2. `POST /api/menu/categories` / `PATCH` / soft-delete.
3. `POST /api/menu/items` com `priceCents`, `halfHalf`, estações, `stockMode`.
4. `GET /api/menu/ficha-meta` para BOM/ingredientes.
5. Item inativo (`active=false`) some do PDV, permanece no banco.
---
## 4. Personas e telas
| Persona | Onde usa o cardápio | Rota |
|---------|---------------------|------|
| Atendente PDV | Monta pedido a partir do cardápio | `/pdv` |
| Gestor | CRUD categorias/itens (API/Admin) | `/admin` · `/api/menu/*` |
| Cliente (futuro) | Cardápio digital | `/c/:slug` (Track C) |
| Cozinha | Não edita cardápio; recebe itens mapeados a estações | `/kds/*` |
---
## 5. Fluxo passo a passo — Atendente no PDV (construído)
> Caminho feliz: pizza com tamanho + split + bebida → enviar à cozinha.
### Passo 1 — Entrar
1. Abrir https://pizza.itecnologys.com/login
2. Usar demo: `pdv@pizza.local` / `805353` (loja `pizza-digital-piloto`)
3. Ir em **PDV**
### Passo 2 — Tipo de fulfillment
1. Escolher **Entrega**, **Balcão** ou **Mesa**
2. Se Entrega: preencher Cliente, Telefone, Bairro, Endereço
3. Opcional: observações e flag **Urgente**
### Passo 3 — Escolher item do cardápio
1. Navegar nas **categorias** (Tradicionais, Da casa, Doces, Refrigerantes…)
2. Tocar num item
3. Se o item é pizza (`halfHalf=true`): abre **sheet de montagem**
4. Se é bebida/extra: adiciona linha direta ao pedido
### Passo 4 — Montar pizza (regra Joinville)
1. Escolher **tamanho** (Broto…Família) na grade
2. Sistema limita sabores pelo `maxFlavors` do tamanho
3. Selecionar 1..N sabores (split)
4. Preço unitário = **maior `priceCents` entre sabores** × `priceFactor` do tamanho
5. Opcional: borda especial
6. Confirmar → linha no “Pedido atual” com nome tipo:
`Pizza Grande 40cm · Calabresa / Mussarela`
### Passo 5 — Enviar à cozinha
1. Revisar linhas e total
2. **Enviar pra cozinha**
3. Pedido entra na Central `/pedidos` e gera tickets KDS conforme estações do item
---
## 6. Fluxo passo a passo — Gestor (API / Admin)
### Listar cardápio
`GET /api/menu` (JWT) → `{ pizzaSizes, categories[] }` com itens ativos.
### Tamanhos
`GET /api/menu/sizes` → catálogo `PizzaSizeBase`.
### CRUD (RF-MEN-01 — parcial na UI)
- `POST/PATCH/DELETE /api/menu/categories`
- `POST/PATCH/DELETE /api/menu/items`
- Campos relevantes: `name`, `priceCents`, `halfHalf`, `active`, `stockMode`, estações, ficha (BOM)
### Regra de negócio congelada (piloto)
1. Preço catalogado = Grande
2. Broto/Pequena = 1 sabor (inteira)
3. Média ≤2 · Grande ≤3 · Gigante/Família ≤4
4. Split cobra o **maior** sabor
5. Cardápio **não** guarda saldo — ponte via `stockMode` + ficha
---
## 7. Arquitetura funcional (como a plataforma liga as peças)
## 5. Sequência (dev)
```text
CARDAPIO-JOINVILLE.md (pesquisa)
│
▼
seed / MenuCategory + MenuItem + PizzaSizeBase
│
├─► PDV sheet (tamanho × sabores × fator)
├─► OrderItem (sizeCode, halfHalf, preço calculado)
├─► KDS (estações do MenuItem)
└─► Estoque (BOM / RecipeLine) — SPEC irmã
Login → GET /menu → render cats
→ tap pizza → sheet(size, flavors)
→ calc priceForSize
→ add line → POST /orders
→ KDS tickets por MenuItemStation
```
---
## 6. Aceite / gaps
- ✅ Seed Joinville + tamanhos
- ✅ Cálculo split no PDV
- ⚠️ UI Admin CRUD
- ⏳ PWA público `/c/:slug`
- 🐛 Validar PDV vazio intermitente
## 8. Critérios de aceite (PRD)
| # | Critério | Evidência | Status |
|---|----------|-----------|--------|
| CA-01 | Existem ≥6 tamanhos com fator e max sabores | `PizzaSizeBase` | ✅ |
| CA-02 | Catálogo Joinville com tradicionais + SC + doces + bebidas | 92 ativos | ✅ |
| CA-03 | PDV calcula preço por tamanho a partir da base Grande | `PdvPage` `priceForSize` | ✅ |
| CA-04 | PDV impede ultrapassar max sabores do tamanho | validação sheet | ✅ |
| CA-05 | API menu autenticada por loja | `/api/menu` | ✅ |
| CA-06 | Categoria Broto legado não aparece como catálogo ativo | `active=false` | ✅ |
| CA-07 | PDV mostra categorias/itens ao operador logado | UI `/pdv` | ⚠️ a validar (em 2026-11-09 UI mostrou “Nenhuma categoria…” apesar da API OK — possível bug de fetch/cache) |
| CA-08 | PWA cardápio público | Track C | ⏳ |
## 7. Notas de implementação (dev)
---
## 9. Gaps e próximos passos
1. **Investigar** PDV sem categorias na UI enquanto API retorna 8 cats / 92 itens
2. Completar **UI Admin** de CRUD alinhada ao RF-MEN-01
3. Expor cardápio no **canal digital** (SPEC-CANAIS)
4. Ligar indisponibilidade a **Estoque** (esgotado / pausado)
5. Repetir este formato de PRD para as demais Specs (KDS, Despacho, Matriz, etc.)
---
## 10. Referências
- Pesquisa: [`CARDAPIO-JOINVILLE.md`](CARDAPIO-JOINVILLE.md)
- Spec: [`SPEC-CARDAPIO.md`](SPEC-CARDAPIO.md)
- Estoque: [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md)
- App: https://pizza.itecnologys.com
- Código: `apps/web/src/PdvPage.tsx` · `apps/api/src/menu/*` · `prisma/seed.ts`
—
*PRD gerado a partir de Spec + auditoria da plataforma · iTecnologys*
- `halfHalf=true` no MenuItem ⇒ sheet de tamanho no PDV (mesmo para pizza “inteira”).
- Broto legado: categoria `active=false`; não use SKU Broto separado.
- Preço: sempre derive de `priceCents` (Grande) × `PizzaSizeBase.priceFactor`.
- Após `POST /orders`, conferir `OrderTicket` gerados via estações do item.
- Se PDV listar vazio: checar JWT `storeId`, `GET /api/menu` no Network e `active` das categories.

View file

@ -0,0 +1,65 @@
# PRD — Entrada por Canais Digitais
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CANAIS-DIGITAIS.md` |
| **Módulo** | Ingestão multi-canal → quadro único /pedidos |
| **Rotas UI** | `/pedidos` · inbound WhatsApp |
| **APIs** | `POST /api/inbound/whatsapp` · `POST /api/orders/demo-digital` · Meta webhook |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Problema que o código resolve
Pedidos chegam de PDV, WhatsApp, telefone, app. Sem quadro único, a cozinha quebra.
A Spec define **origin × fulfillment** e Track C.
## 2. Modelo
- `Order.origin`: pdv | cardapio(aplicativo) | whatsapp | telefone | ifood(futuro)
- `Order.fulfillment`: entrega | retirada | mesa
- Idempotência inbound: `Order.inboundKey`
## 3. Processo — pedido WhatsApp (construído)
1. Bot/n8n/Make chama `POST /api/inbound/whatsapp` com header `X-Api-Key`.
2. Guard `InboundApiKeyGuard` valida `INBOUND_API_KEY`.
3. Service normaliza payload → cria Order `origin=whatsapp`.
4. Se `inboundKey` repetido → não duplica.
5. Pedido aparece em `/pedidos` com badge WhatsApp.
6. Meta: `GET/POST /api/inbound/whatsapp/meta` (verify token + webhook).
## 4. Processo — demo canal digital
1. Operador/dev chama `POST /api/orders/demo-digital`.
2. Gera pedido sintético para validar UI Central (filtros/som/badges).
## 5. Processo — Central (operador)
1. Abre `/pedidos`.
2. Filtra por origin/fulfillment.
3. Ouve Socket para novos pedidos.
4. Encaminha mentalmente à cozinha (já ticketado no create).
## 6. Aceite / gaps
- ✅ Inbound WhatsApp + demo digital + badges Central
- ⏳ PWA cardápio público Track C1
- ⏳ iFood Track C2
- ⚠️ SMTP/notificações reais
## 7. Camada inbound (WhatsappService)
| Método | Fluxo |
|--------|-------|
| `createOrder` | Payload API key → Order whatsapp |
| `fromMetaText` | Webhook Meta texto → parse |
| `resolveItems` | Mapeia texto/IDs para MenuItem |
Guard: `InboundApiKeyGuard` em `POST /api/inbound/whatsapp`.

View file

@ -0,0 +1,64 @@
# PRD — SPEC Cardápio (Menu domain)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CARDAPIO.md` |
| **Módulo** | Domínio Menu* + tamanhos + modifiers |
| **Rotas UI** | `/pdv` · Admin |
| **APIs** | `/api/menu/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Contrato do domínio (dev)
```text
MenuCategory 1─N MenuItem
MenuItem N─N Station (MenuItemStation)
MenuItem 1─N RecipeLine (BOM) → Ingredient
PizzaSizeBase (catálogo de tamanhos da loja)
```
`stockMode`: `none|bom|sku` — cardápio não guarda saldo.
## 2. Processos
### Listagem PDV
`GET /api/menu` → categories+items ativos + pizzaSizes.
### Tamanhos
`GET /api/menu/sizes` lê `PizzaSizeBase`.
### CRUD
Gestor: create/patch/delete categories & items (Roles/capabilities).
### Ficha
`GET /api/menu/ficha-meta` apoia edição de BOM.
## 3. Regras RF-MEN (status)
- RF-MEN-01 CRUD ⚠️ parcial UI
- RF-MEN-02 map estações ✅
- RF-MEN-05 meia-a-meia/split ✅
- RF-MEN-04 PWA ⏳
- RF-MEN-06/07 horário/áreas ⏳ (zonas em `/admin/zonas`)
## 4. Walkthrough teste QA
1. Login gestor
2. Listar menu via API — esperar Tradicionais/Da casa/Doces/bebidas
3. PDV: montar Grande 2 sabores — preço = max*1.0
4. PDV: Broto 2 sabores — deve bloquear (max=1)
## 5. MenuService — métodos
`getStore` · `listStations` · `listMenu` · `fichaMeta` · CRUD category/item · replaceRecipeLines.
Teste automatizável: login → GET menu → assert categories includes Tradicionais/Da casa.

View file

@ -0,0 +1,34 @@
# PRD — Paridade UI 3 vídeos CityFoods
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CITYFOODS-VIDEO-PARITY.md` |
| **Módulo** | UX Despacho mapa-first |
| **Rotas UI** | `/despacho` |
| **APIs** | `/api/routes/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Intenção
Backend de rotas não basta: a UI precisa **parecer e operar** como os vídeos
(mapa full-bleed, CTA Ir para entrega, multi-motoboy, pin some ao entregar).
## 2. Processo de validação (QA com Spec aberta)
1. Abrir `/despacho` em viewport desktop
2. Verificar se mapa é o bloco dominante (não painel lateral primeiro)
3. Despachar rota com 2+ motoboys — rastreio simultâneo
4. Marcar entregue — pin deve sumir
5. Filtro forno por sabor (se RF-VID exigir)
## 3. Status
- ✅ Dados/API routes
- ⚠️ UI mapa-first / RF-VID-01…08 — acompanhar implementação vs Spec

View file

@ -0,0 +1,66 @@
# PRD — Despacho / Gestor de Rotas (CityFoods parity)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-DESPACHO-CITYFOODS-PARITY.md` |
| **Módulo** | Rotas, motoboys, mapa |
| **Rotas UI** | `/despacho` `/motoboy` `/ops` |
| **APIs** | `/api/routes/*` `/api/drivers/*` `/api/ops/*` `/api/zones/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo implementado
Sair de “lista de prontos + SAIR” para fluxo:
**Montar rota → Despachar → mapa → status motoboy → fechar**.
## 2. Processo — montar e despachar rota
1. Pedidos `ready` no board
2. Operador em `/despacho` seleciona pedidos
3. `POST /api/routes/preview` (ordem sugerida)
4. `POST /api/routes` cria `DispatchBatch` + `DispatchStop`
5. `PATCH /api/routes/:id/driver` associa motoboy (`Driver`)
6. `POST /api/routes/:id/dispatch` sai para rua
7. Mapa acompanha; `POST /api/routes/:id/ping` atualiza lat/lng
8. Por stop: `POST /api/routes/:id/stops/:orderId/status` (a_caminho/entregue)
9. `POST /api/routes/:id/close` fecha batch
## 3. Processo — motoboy
1. UI `/motoboy`
2. `GET /api/routes/driver/:driverId` / `GET /api/routes/active`
3. Atualiza status das paradas
## 4. Cadastros apoio
- Drivers CRUD `/api/drivers`
- Zonas `/api/zones` · UI `/admin/zonas`
- Ops funnel/ranking/priority `/api/ops/*`
## 5. Aceite
- ✅ Routes API + Despacho/Motoboy pages
- ⚠️ Paridade mapa full-bleed (ver PRD vídeo)
- ⏳ ORS tour produção robusto
## 6. Camada de serviço (RoutesService)
Arquivo: `apps/api/src/routes/routes.service.ts` (~548 linhas)
| Método | Processo |
|--------|----------|
| `preview` | Ordena stops candidatos (sem persistir) |
| `buildStops` / `create` | Cria batch+stops |
| `assignDriver` | Liga Driver |
| `dispatch` | Status em rota |
| `ping` | GPS |
| `setStopStatus` | a_caminho / entregue / falha |
| `close` | Fecha batch |
| `listActive` / `activeForDriver` / `get` | Leituras UI |

View file

@ -0,0 +1,68 @@
# PRD — Estoque / SmartStock
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-ESTOQUE.md` |
| **Módulo** | Insumos, CMV, transferências, turnos |
| **Rotas UI** | `/estoque` `/estoque/smart/*` |
| **APIs** | `/api/estoque/*` `/api/estoque/smart/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Visão de implementação
Dois níveis:
1. **Estoque clássico** (`/api/estoque`) — insumos, ajuste, relatório, preview baixa
2. **SmartStock** (`/api/estoque/smart`) — estações, transferências, picking, turnos, contagens
Ponte com cardápio: BOM (`MenuItemRecipeLine`) e `stockMode`.
## 2. Processo — baixa por venda (conceitual)
1. Pedido confirmado com itens `stockMode=bom`
2. Preview `POST /api/estoque/preview`
3. Consumo grava `RecipeConsumption` / movimentos
4. Alerta se saldo insuficiente (strict mode `PATCH /api/estoque/strict`)
## 3. Processo — SmartStock transferência (dev steps)
1. Estação solicita: `POST /estoque/smart/requests`
2. Central vê `GET /estoque/smart/transfers`
3. `POST .../start-picking` → `PATCH .../picking` linhas
4. `POST .../dispatch` → envio
5. Destino `POST .../receive`
6. Movimentos auditáveis `GET /estoque/smart/movements`
## 4. Processo — turno / fechamento
1. `POST /estoque/smart/shifts/open`
2. Contagens `POST .../counts`
3. Aprovação por insumo `POST .../approve/:ingredientId`
4. `POST .../close`
5. UI: `/estoque/smart/fechamento/:shiftId`
## 5. UI map
- Dashboard, Central, Transferências, Consumo, Movimentos, Estação, Recebimento
## 6. Aceite
- ✅ Módulo SmartStock amplo na API/UI
- ⚠️ Strict/BOM amarrado 100% ao PDV em todos itens
- ⏳ NF compra / inventário físico completo
## 7. SmartStockService (~1838 linhas) — processos chave
| Método | Processo |
|--------|----------|
| `dashboard` / `listStations` / `stationBoard` | Visão |
| `createRequest` | Pedido de reposição |
| `startPicking` / `updatePickingLines` | Separação |
| `dispatchTransfer` / `receiveTransfer` | Envio/recebimento |
| `openShift` / `saveCounts` / `approveCount` / `closeShift` | Fechamento |
| `movements` / `movementDetail` / `moveBalance` | Auditoria saldo |

View file

@ -0,0 +1,100 @@
# PRD — Fase 1 — MVP Cozinha Digital
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-FASE1.md` |
| **Módulo** | PDV + KDS + Expedição (sem rotas ORS) |
| **Rotas UI** | `/pdv` `/pedidos` `/kds/:station` `/etiqueta/:id` |
| **APIs** | `/api/orders/*` `/api/kds/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo da Fase 1 (visão de implementação)
Entregar loop operacional **pedido → produção → pronto**, sem otimização de rotas.
ORS/motoboy tour ficam para despacho (Specs posteriores).
### Escopo entregue
1. PDV cria pedido
2. Central `/pedidos` vê fila
3. KDS multi-estação com claim/bump
4. Label/etiqueta
5. Gate `order.ready` quando tickets fecham
### Fora
App motoboy avançado, iFood, multi-loja, ORS.
---
## 2. Processo ponta a ponta (dev walkthrough)
### A) Criação do pedido (PDV)
1. `POST /api/auth/login`
2. Operador monta carrinho (cardápio)
3. `POST /api/orders` com `origin`, `fulfillment`, items, customer
4. Service cria `Order` + `OrderItem` + `OrderTicket` por estação mapeada
5. Emite eventos Socket.io para KDS/Central
### B) Central de pedidos
1. `GET /api/orders` (+ filtros origin/status)
2. UI `/pedidos` mostra badges (Aplicativo/WhatsApp/Telefone/PDV)
3. `PATCH /api/orders/:id/urgent` · `PATCH .../status` · `PATCH .../payment`
4. Demo digital: `POST /api/orders/demo-digital`
### C) Cozinha (KDS clássico)
1. `GET /api/kds/:station` → fila / comigo / bloqueados
2. `POST /api/kds/:station/claim/:orderId` → claim exclusivo
3. Trabalha item → `POST .../bump` avança ticket
4. Expedição só libera quando demais estações concluíram
5. Auto `order.ready` quando todos tickets fecham
### D) Etiqueta
1. `GET /api/orders/:id/label`
2. UI `/etiqueta/:id` (ESC/POS ou PDF conforme implementação)
---
## 3. Máquina de estados (Order)
```text
created/received → in_kitchen → ready → (despacho/entrega)
↘ cancelled
```
Tickets por estação: `pending → claimed → done` (simplificado).
## 4. Aceite
- ✅ Loop PDV→KDS→ready
- ✅ Claim exclusivo
- ⚠️ SLA timers por categoria (SPEC menciona)
- ⏳ Rotas ORS (não Fase 1)
## 5. Camada de serviço (OrdersService) — o que o código faz
Arquivo: `apps/api/src/orders/orders.service.ts` (~811 linhas)
| Método | Processo |
|--------|----------|
| `create` | Gera código (`nextCode`), persiste Order+Items, cria tickets KDS, emite realtime |
| `list` / `get` | Lista/detalhe com filtros para Central |
| `transition` | Muda status do pedido (máquina de estados) |
| `setUrgent` / `setPayment` | Flags operacionais/financeiras |
| `label` | Payload da etiqueta |
| `trackByHash` | Tracking público sem auth completa |
| `createDemoDigital` | Pedido sintético canal digital |
| `dayPool` | Pool do dia (agrupamento) |
### Erros que o dev deve tratar no front
- 401 sem JWT
- 400 validação items/fulfillment
- 409/422 transição ilegal de status

View file

@ -0,0 +1,65 @@
# PRD — KDS Claim (PEGAR) + pooling
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-KDS-CLAIM.md` |
| **Módulo** | KDS multi-estação clássico |
| **Rotas UI** | `/kds` `/kds/:station` |
| **APIs** | `GET/POST /api/kds/:station*` `/api/kds/ready/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Problema
Sem claim, duas estações pegam o mesmo pedido (CityFoods resolve com PEGAR exclusivo).
## 2. Processo — fila de estação
1. Cozinheiro abre `/kds/:station` (massa|montagem|forno|expedicao…)
2. `GET /api/kds/:station` devolve seções: **Fila / Comigo / Bloqueados**
3. Na Fila, clicar PEGAR **não** claima imediatamente → confirmação (Spec)
4. Confirma → `POST /api/kds/:station/claim/:orderId`
5. Outras estações veem pedido **bloqueado** (`claimedStationId`)
6. Ao concluir → `POST /api/kds/:station/orders/:orderId/bump`
7. Expedição só bumpa quando pré-requisitos ok
8. Ready board: `GET /api/kds/ready/list`
## 3. Processo — pós-pronto
- `POST /api/kds/ready/:orderId/estufa`
- `POST /api/kds/ready/:orderId/dispatch`
- `POST /api/kds/ready/:orderId/deliver`
- `POST /api/kds/ready/batch-dispatch`
## 4. Pooling
Pedidos podem agrupar saída (drawer pooling na UI) antes do despacho.
## 5. Aceite
- ✅ Claim/bump/ready endpoints
- ✅ UI KdsPage seções
- ⚠️ Confirmar UX “confirmação antes do claim” em todos fluxos
## 6. Camada de serviço (KdsService) — claim clássico
Arquivo: `apps/api/src/kds/kds.service.ts` (~1221 linhas)
| Método | Processo |
|--------|----------|
| `stationBoard` | Monta Fila/Comigo/Bloqueados da estação |
| `claim` | Exclusivo: grava claimedStationId/claimedAt; bloqueia peers |
| `bumpOrder` | Avança ticket; pode disparar ready |
| `ensurePrepTasks` | Garante tasks de produção |
| `listReady` | Board de prontos |
| `holdEstufa` | Move para estufa |
| `dispatch` / `batchDispatch` | Sai para despacho |
| `deliver` | Marca entregue no fluxo ready |
### Diálogo tipico Socket
Após claim/bump, server emite eventos para atualizar outras telas KDS sem refresh.

View file

@ -0,0 +1,57 @@
# PRD — KDS Pizzaiolo Modelo B
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-KDS-PIZZAIOLO-MODELO-B.md` |
| **Módulo** | Produção por pizza (montagem ≠ forno) |
| **Rotas UI** | `/kds/producao` |
| **APIs** | `/api/kds/pizzas/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Diferença do KDS clássico
Modelo B trabalha **PrepTask por pizza**, não só ticket por estação genérica.
Montagem e forno têm responsáveis independentes.
## 2. Processo — board pizzaiolo
1. UI `/kds/producao` → `GET /api/kds/pizzas/board`
2. Card por pizza (áreas coloridas, botões grandes)
3. `POST /api/kds/pizzas/:taskId/pegar` — assume montagem
4. `POST .../devolver` — devolve à fila
5. `POST .../enviar-forno` — handoff montagem→forno
6. `POST .../assumir-forno` — outro operador assume forno
7. `POST .../marcar-pronta` — pizza pronta
8. `POST .../transferir` — troca responsável
## 3. Estados típicos da task
```text
fila → em_montagem → no_forno → pronta → (estufa/expedição)
```
## 4. Aceite
- ✅ Endpoints pizzas/* e página KdsPizzaioloPage
- ⚠️ Paridade visual completa com mock Spec
## 5. Camada de serviço — pizzas/*
| Método | Ação do pizzaiolo |
|--------|-------------------|
| `pizzaBoard` | Snapshot do board |
| `pizzaPegar` | Assume card (montagem) |
| `pizzaDevolver` | Devolve à fila |
| `pizzaEnviarForno` | Handoff |
| `pizzaAssumirForno` | Outro user no forno |
| `pizzaMarcarPronta` | Finaliza pizza |
| `pizzaTransferir` | Troca responsável |
| `emitPizza` | Realtime do card |

View file

@ -0,0 +1,39 @@
# PRD — Lacunas vs operação SiriFood (vídeo)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-LACUNAS-VIDEO-SIRIFOOD.md` |
| **Módulo** | Gap analysis operacional |
| **Rotas UI** | `/despacho` `/kds` `/pedidos` |
| **APIs** | — |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Para que serve este PRD
Não descreve um módulo isolado: é o **checklist de lacunas** entre Pizza Digital
e a operação filmada (Siciliana/SiriFood ~70% iFood, despacho como coração).
## 2. Processo de uso (product/dev)
1. Assistir referência SiriFood
2. Percorrer despacho → estufa → conferência → motoboy na nossa UI
3. Marcar cada lacuna da Spec como ✅ mitigada / ⏳ aberta
4. Priorizar backlog (iFood cotação, estufa, conferência)
## 3. Temas típicos da Spec
- Despacho como hub
- Estufa
- Conferência
- Cotação iFood
- Multi-loja
## 4. Status
Documento vivo de gaps — não é feature shippable isolada.

View file

@ -0,0 +1,50 @@
# PRD — SPEC mãe — Pizza Digital (visão produto)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `SPEC.md / docs/SPEC.md` |
| **Módulo** | Produto completo Cozinha Digital + delivery |
| **Rotas UI** | todas as rotas |
| **APIs** | todas as APIs |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Posicionamento
SO da cozinha + delivery próprio (não marketplace). Referência CityFoods + OSS
(kitchenOS, rusterando, URY, MaSoVa, Tasty-Station).
## 2. Sequência oficial S0–S9 (como o time deve ler)
| Sprint | Entrega | PRD detalhado |
|--------|---------|---------------|
| S0–S1 bootstrap | Docker/VM125 | PRD-SPEC-FASE1 |
| S2–S3 KDS | claim/multi-estação | PRD-SPEC-KDS-CLAIM |
| S4 pizzaiolo | Modelo B | PRD-SPEC-KDS-PIZZAIOLO-MODELO-B |
| S5 canais | /pedidos + inbound | PRD-SPEC-CANAIS-DIGITAIS |
| Menu/Estoque | Track M/E | PRD-SPEC-CARDAPIO · ESTOQUE · CARDAPIO-JOINVILLE |
| ACS | matriz/users | PRD-SPEC-MATRIZ-ACESSO · USUARIOS |
| S7–S8 despacho | routes/motoboy | PRD-SPEC-DESPACHO · VIDEO-PARITY |
| Demo | /sim | PRD-SPEC-SIM-OPS-DEMO |
| Gaps iFood | — | PRD-SPEC-LACUNAS-SIRIFOOD |
## 3. Processo operacional completo (happy path)
1. Canal/PDV cria Order
2. KDS produz (clássico e/ou pizzaiolo)
3. Ready → estufa
4. Despacho monta rota → motoboy
5. Entrega → fecha batch
6. Estoque consome BOM
7. Admin gerencia menu/users/acessos
## 4. Aceite de produto (piloto)
- ✅ Fase 1 cozinha no ar
- ⚠️ Canais digitais em evolução
- ⏳ iFood / PWA completo

View file

@ -0,0 +1,69 @@
# PRD — Matriz de Acesso (MVP)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-MATRIZ-ACESSO.md` |
| **Módulo** | Capabilities admin por tenant |
| **Rotas UI** | `/admin/acessos` |
| **APIs** | `/api/access/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Ideia central (dev)
Roles operacionais (`gestor|pdv|kds|despacho`) ≠ capabilities admin.
Capabilities vivem em `UserCapability` e são **revalidadas no Core** a cada ação sensível.
### Caps
`menu.view/manage` · `staff.view/manage` · `permissions.manage` · `owners.manage` · `finance.view`
## 2. Processo — ver minhas permissões
1. Login JWT (`sub`, `storeId`, `role`)
2. `GET /api/access/me` → capabilities efetivas
3. Front esconde/mostra Admin conforme caps
## 3. Processo — editar matriz
1. Usuário com `permissions.manage`
2. `GET /api/access/matrix` carrega templates Perfil×Cap
3. Edita rascunho na UI `/admin/acessos`
4. `PUT /api/access/matrix` salva definição do template (atômico)
5. **Não** propaga sozinho aos users
## 4. Processo — aplicar template a usuários
1. Seleciona staff `GET /api/access/staff`
2. `POST /api/access/apply-template` { userIds, templateKey }
3. Reescreve `UserCapability`
4. Auditoria `AccessAuditLog` (quando habilitada)
## 5. Dependências Core
- `menu.manage` ⇒ `menu.view`
- `staff.manage` ⇒ `staff.view`
- Normalização em `capabilities.ts`
## 6. Aceite
- ✅ API matrix/me/staff/apply
- ✅ UI AccessMatrixPage
- ⚠️ Auditoria completa em todos writes
## 7. Camada de serviço (AccessService)
| Método | Fluxo |
|--------|-------|
| `ensureTemplates` | Garante templates default da loja |
| `getEffectiveCapabilities` | Resolve caps (+ fallback gestor) |
| `assertCapability` | Throws ForbiddenException |
| `getMatrix` / `saveMatrix` | CRUD definição |
| `applyTemplate` | Propaga para users |
| `listStaffForApply` | Alvos |
| `assertTenantKeepsOwner` | Não deixa loja sem owner |
| `setUserCapabilities` | Write direto |

View file

@ -0,0 +1,54 @@
# PRD — Simulação de Operação (Demo)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-SIM-OPS-DEMO.md` |
| **Módulo** | Motor /sim |
| **Rotas UI** | `/sim` |
| **APIs** | `/api/sim/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo
Demonstrar ciclo completo Joinville sem operação real: canais → KDS → estufa → rotas → ETA.
## 2. Processo — operar o simulador
1. Login (gestor/ops)
2. Abrir `/sim`
3. `GET /api/sim/status`
4. `POST /api/sim/start` — inicia geração
5. Opcional `POST /api/sim/simulate-turno`
6. Observar `/pedidos`, `/kds/producao`, `/despacho`
7. `POST /api/sim/stop`
8. Limpar: `POST /api/sim/purge`
## 3. Parâmetros típicos (Spec)
Até ~2000 ops/dia · 15 motoboys SIM · cap prep · Joinville.
## 4. Aceite
- ✅ Controller/UI sim
- ⚠️ Calibrar carga para demo comercial sem derrubar VM
## 5. Motor SimService (~1090 linhas)
| Método | Papel no loop |
|--------|----------------|
| `start` / `stop` / `statusRich` | Controle |
| `tick` | Heartbeat do simulador |
| `ingress` | Gera pedidos (canais) |
| `advanceKitchen` | Empurra KDS |
| `dispatchReady` | Cria rotas |
| `completeDeliveries` | Fecha entregas |
| `ensureFleet` / `ensurePizzaiolos` | Seeds SIM |
| `simulateTurno` | Atalho turno |
| `purge` | Limpa dados teste |

View file

@ -0,0 +1,65 @@
# PRD — Usuários, senha e sessão
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-USUARIOS.md` |
| **Módulo** | Auth + equipe |
| **Rotas UI** | `/login` `/admin/equipe` `/forgot-password` `/reset-password` |
| **APIs** | `/api/auth/*` `/api/users/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Entidades
`User`, `AuthToken`, `PushDevice`, `NotifyLog`, `UserCapability`
## 2. Processo — login
1. UI `/login` (demo: `pdv@pizza.local` / `805353` + storeSlug)
2. `POST /api/auth/login` { email, password, storeSlug }
3. Valida hash bcrypt; incrementa `failedLoginAttempts`
4. 5 falhas → `lockedUntil` +15 min
5. Sucesso → JWT + user + capabilities
6. `GET /api/auth/me` para refresh de sessão
## 3. Processo — política de senha
1. `GET /api/auth/password-policy`
2. Regras: ≥8, 1 upper, 1 lower, 1 dígito, sem local-part email
3. Código: `password-policy.ts`
## 4. Processo — CRUD equipe
1. Cap `staff.view` lista `GET /api/users`
2. Cap `staff.manage` cria `POST /api/users` (role, áreas, jobTitle)
3. Criar gestor extra exige `owners.manage`
4. Pode aplicar template na criação
5. `POST /api/users/:id/send-reset` dispara token reset
## 5. Processo — forgot / reset
1. `POST /api/auth/forgot-password` → resposta genérica
2. Token `password_reset` TTL 60 min
3. `POST /api/auth/reset-password` consome token, limpa lockout
4. `POST /api/auth/change-password` (autenticado)
## 6. Aceite
- ✅ Login/lockout/policy/CRUD/reset stub
- ⏳ SMTP/push produção (RF-USR-10)
## 7. Camada de serviço (AuthService)
| Método | Fluxo |
|--------|-------|
| `login` | storeSlug+email+senha → JWT; lockout |
| `me` | Rehidrata user+caps |
| `requestPasswordReset` | Token genérico |
| `resetPassword` | Consome token |
| `changePassword` | Autenticado |
UsersService: list/meta/create/update/sendReset/pushDevice.

View file

@ -0,0 +1,24 @@
# PRDs — Pizza Digital
PRDs **detalhados** (visão de desenvolvedor): Spec × código/API/UI × processos passo a passo.
App auditado: https://pizza.itecnologys.com · v0.5.0 · 2026-11-09
| PRD | Spec |
|-----|------|
| [PRD-SPEC-MAE.md](PRD-SPEC-MAE.md) | `SPEC.md` |
| [PRD-SPEC-FASE1.md](PRD-SPEC-FASE1.md) | `SPEC-FASE1.md` |
| [PRD-SPEC-CANAIS-DIGITAIS.md](PRD-SPEC-CANAIS-DIGITAIS.md) | `SPEC-CANAIS-DIGITAIS.md` |
| [PRD-SPEC-CARDAPIO.md](PRD-SPEC-CARDAPIO.md) | `SPEC-CARDAPIO.md` |
| [PRD-CARDAPIO-JOINVILLE.md](PRD-CARDAPIO-JOINVILLE.md) | `CARDAPIO-JOINVILLE.md` |
| [PRD-SPEC-ESTOQUE.md](PRD-SPEC-ESTOQUE.md) | `SPEC-ESTOQUE.md` |
| [PRD-SPEC-MATRIZ-ACESSO.md](PRD-SPEC-MATRIZ-ACESSO.md) | `SPEC-MATRIZ-ACESSO.md` |
| [PRD-SPEC-USUARIOS.md](PRD-SPEC-USUARIOS.md) | `SPEC-USUARIOS.md` |
| [PRD-SPEC-KDS-CLAIM.md](PRD-SPEC-KDS-CLAIM.md) | `SPEC-KDS-CLAIM.md` |
| [PRD-SPEC-KDS-PIZZAIOLO-MODELO-B.md](PRD-SPEC-KDS-PIZZAIOLO-MODELO-B.md) | `SPEC-KDS-PIZZAIOLO-MODELO-B.md` |
| [PRD-SPEC-DESPACHO.md](PRD-SPEC-DESPACHO.md) | `SPEC-DESPACHO-CITYFOODS-PARITY.md` |
| [PRD-SPEC-CITYFOODS-VIDEO-PARITY.md](PRD-SPEC-CITYFOODS-VIDEO-PARITY.md) | `SPEC-CITYFOODS-VIDEO-PARITY.md` |
| [PRD-SPEC-LACUNAS-SIRIFOOD.md](PRD-SPEC-LACUNAS-SIRIFOOD.md) | `SPEC-LACUNAS-VIDEO-SIRIFOOD.md` |
| [PRD-SPEC-SIM-OPS-DEMO.md](PRD-SPEC-SIM-OPS-DEMO.md) | `SPEC-SIM-OPS-DEMO.md` |
Cada PRD inclui: artefatos de código, processos numerados, APIs, estados e aceite/gaps.

View file

@ -0,0 +1,111 @@
# PRD — Cardápio Joinville (Menu)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/CARDAPIO-JOINVILLE.md + docs/SPEC-CARDAPIO.md` |
| **Módulo** | Cardápio / PDV sheet de pizza |
| **Rotas UI** | `/pdv` · Admin menu |
| **APIs** | `GET/POST/PATCH/DELETE /api/menu/*` · `GET /api/menu/sizes` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Contexto do desenvolvedor
O cardápio Joinville não é só uma lista de sabores: é o **catálogo canônico** que o PDV usa para montar `OrderItem`.
Pesquisa regional (`CARDAPIO-JOINVILLE.md`) virou seed + `PizzaSizeBase`. Preço catalogado = **Grande 40 cm**;
tamanho/split resolvem no pedido.
### Artefatos de código
- UI: `apps/web/src/PdvPage.tsx` (sheet tamanho/sabores)
- API: `apps/api/src/menu/menu.controller.ts` · `menu.service.ts` · `pizza-sizes.ts`
- Dados: `MenuCategory`, `MenuItem`, `PizzaSizeBase`, `MenuItemStation`, `MenuItemRecipeLine`
- Seed: `apps/api/prisma/seed.ts`
### Inventário auditado
8 categorias ativas · **92 itens ativos** · 6 tamanhos · cat. Broto legado `active=false`.
---
## 2. Processo — carregar cardápio no PDV
1. Operador autentica (`POST /api/auth/login` com `storeSlug`).
2. Front chama `GET /api/menu` → `{ pizzaSizes, categories[] }` filtrando `active=true`.
3. Front monta abas/lista por categoria.
4. Item com `halfHalf=true` abre sheet; demais vão direto ao carrinho.
**Estados**
- Sem token → 401
- Categoria sem itens ativos → não deve renderizar (ou vazia)
- 🐛 Em 2026-11-09 a UI chegou a mostrar “Nenhuma categoria…” com API OK — validar fetch/storeSlug no client
---
## 3. Processo — montar pizza (passo a passo)
1. Atendente escolhe fulfillment: Entrega / Balcão / Mesa.
2. Clica sabor (ex.: Calabresa) → sheet.
3. Escolhe `sizeCode` (broto|pequena|media|grande|gigante|familia).
4. Sistema lê `maxFlavors` / `priceFactor` / `diameterCm` / `slices` de `PizzaSizeBase`.
5. Seleciona sabores até o limite; se exceder → erro UI.
6. Preço unitário = `max(priceCents dos sabores) * priceFactor`.
7. Opcional: borda (`Bordas especiais`).
8. Confirma → linha no pedido: `Pizza Grande 40cm · SaborA / SaborB`.
9. `POST /api/orders` com items (`sizeCode`, `halfHalf`, notes).
### Tabela de regras (congelada)
| sizeCode | cm | fatias | max sabores | fator |
|----------|----|--------|-------------|-------|
| broto | 25 | 4 | 1 | 0,55 |
| pequena | 30 | 6 | 1 | 0,70 |
| media | 35 | 8 | 2 | 0,85 |
| grande | 40 | 12 | 3 | 1,00 |
| gigante | 45 | 16 | 4 | 1,20 |
| familia | 50 | 20 | 4 | 1,35 |
---
## 4. Processo — CRUD gestor
1. Gestor com capability `menu.manage`.
2. `POST /api/menu/categories` / `PATCH` / soft-delete.
3. `POST /api/menu/items` com `priceCents`, `halfHalf`, estações, `stockMode`.
4. `GET /api/menu/ficha-meta` para BOM/ingredientes.
5. Item inativo (`active=false`) some do PDV, permanece no banco.
---
## 5. Sequência (dev)
```text
Login → GET /menu → render cats
→ tap pizza → sheet(size, flavors)
→ calc priceForSize
→ add line → POST /orders
→ KDS tickets por MenuItemStation
```
## 6. Aceite / gaps
- ✅ Seed Joinville + tamanhos
- ✅ Cálculo split no PDV
- ⚠️ UI Admin CRUD
- ⏳ PWA público `/c/:slug`
- 🐛 Validar PDV vazio intermitente
## 7. Notas de implementação (dev)
- `halfHalf=true` no MenuItem ⇒ sheet de tamanho no PDV (mesmo para pizza “inteira”).
- Broto legado: categoria `active=false`; não use SKU Broto separado.
- Preço: sempre derive de `priceCents` (Grande) × `PizzaSizeBase.priceFactor`.
- Após `POST /orders`, conferir `OrderTicket` gerados via estações do item.
- Se PDV listar vazio: checar JWT `storeId`, `GET /api/menu` no Network e `active` das categories.

View file

@ -0,0 +1,65 @@
# PRD — Entrada por Canais Digitais
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CANAIS-DIGITAIS.md` |
| **Módulo** | Ingestão multi-canal → quadro único /pedidos |
| **Rotas UI** | `/pedidos` · inbound WhatsApp |
| **APIs** | `POST /api/inbound/whatsapp` · `POST /api/orders/demo-digital` · Meta webhook |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Problema que o código resolve
Pedidos chegam de PDV, WhatsApp, telefone, app. Sem quadro único, a cozinha quebra.
A Spec define **origin × fulfillment** e Track C.
## 2. Modelo
- `Order.origin`: pdv | cardapio(aplicativo) | whatsapp | telefone | ifood(futuro)
- `Order.fulfillment`: entrega | retirada | mesa
- Idempotência inbound: `Order.inboundKey`
## 3. Processo — pedido WhatsApp (construído)
1. Bot/n8n/Make chama `POST /api/inbound/whatsapp` com header `X-Api-Key`.
2. Guard `InboundApiKeyGuard` valida `INBOUND_API_KEY`.
3. Service normaliza payload → cria Order `origin=whatsapp`.
4. Se `inboundKey` repetido → não duplica.
5. Pedido aparece em `/pedidos` com badge WhatsApp.
6. Meta: `GET/POST /api/inbound/whatsapp/meta` (verify token + webhook).
## 4. Processo — demo canal digital
1. Operador/dev chama `POST /api/orders/demo-digital`.
2. Gera pedido sintético para validar UI Central (filtros/som/badges).
## 5. Processo — Central (operador)
1. Abre `/pedidos`.
2. Filtra por origin/fulfillment.
3. Ouve Socket para novos pedidos.
4. Encaminha mentalmente à cozinha (já ticketado no create).
## 6. Aceite / gaps
- ✅ Inbound WhatsApp + demo digital + badges Central
- ⏳ PWA cardápio público Track C1
- ⏳ iFood Track C2
- ⚠️ SMTP/notificações reais
## 7. Camada inbound (WhatsappService)
| Método | Fluxo |
|--------|-------|
| `createOrder` | Payload API key → Order whatsapp |
| `fromMetaText` | Webhook Meta texto → parse |
| `resolveItems` | Mapeia texto/IDs para MenuItem |
Guard: `InboundApiKeyGuard` em `POST /api/inbound/whatsapp`.

View file

@ -0,0 +1,64 @@
# PRD — SPEC Cardápio (Menu domain)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CARDAPIO.md` |
| **Módulo** | Domínio Menu* + tamanhos + modifiers |
| **Rotas UI** | `/pdv` · Admin |
| **APIs** | `/api/menu/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Contrato do domínio (dev)
```text
MenuCategory 1─N MenuItem
MenuItem N─N Station (MenuItemStation)
MenuItem 1─N RecipeLine (BOM) → Ingredient
PizzaSizeBase (catálogo de tamanhos da loja)
```
`stockMode`: `none|bom|sku` — cardápio não guarda saldo.
## 2. Processos
### Listagem PDV
`GET /api/menu` → categories+items ativos + pizzaSizes.
### Tamanhos
`GET /api/menu/sizes` lê `PizzaSizeBase`.
### CRUD
Gestor: create/patch/delete categories & items (Roles/capabilities).
### Ficha
`GET /api/menu/ficha-meta` apoia edição de BOM.
## 3. Regras RF-MEN (status)
- RF-MEN-01 CRUD ⚠️ parcial UI
- RF-MEN-02 map estações ✅
- RF-MEN-05 meia-a-meia/split ✅
- RF-MEN-04 PWA ⏳
- RF-MEN-06/07 horário/áreas ⏳ (zonas em `/admin/zonas`)
## 4. Walkthrough teste QA
1. Login gestor
2. Listar menu via API — esperar Tradicionais/Da casa/Doces/bebidas
3. PDV: montar Grande 2 sabores — preço = max*1.0
4. PDV: Broto 2 sabores — deve bloquear (max=1)
## 5. MenuService — métodos
`getStore` · `listStations` · `listMenu` · `fichaMeta` · CRUD category/item · replaceRecipeLines.
Teste automatizável: login → GET menu → assert categories includes Tradicionais/Da casa.

View file

@ -0,0 +1,34 @@
# PRD — Paridade UI 3 vídeos CityFoods
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-CITYFOODS-VIDEO-PARITY.md` |
| **Módulo** | UX Despacho mapa-first |
| **Rotas UI** | `/despacho` |
| **APIs** | `/api/routes/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Intenção
Backend de rotas não basta: a UI precisa **parecer e operar** como os vídeos
(mapa full-bleed, CTA Ir para entrega, multi-motoboy, pin some ao entregar).
## 2. Processo de validação (QA com Spec aberta)
1. Abrir `/despacho` em viewport desktop
2. Verificar se mapa é o bloco dominante (não painel lateral primeiro)
3. Despachar rota com 2+ motoboys — rastreio simultâneo
4. Marcar entregue — pin deve sumir
5. Filtro forno por sabor (se RF-VID exigir)
## 3. Status
- ✅ Dados/API routes
- ⚠️ UI mapa-first / RF-VID-01…08 — acompanhar implementação vs Spec

View file

@ -0,0 +1,66 @@
# PRD — Despacho / Gestor de Rotas (CityFoods parity)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-DESPACHO-CITYFOODS-PARITY.md` |
| **Módulo** | Rotas, motoboys, mapa |
| **Rotas UI** | `/despacho` `/motoboy` `/ops` |
| **APIs** | `/api/routes/*` `/api/drivers/*` `/api/ops/*` `/api/zones/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo implementado
Sair de “lista de prontos + SAIR” para fluxo:
**Montar rota → Despachar → mapa → status motoboy → fechar**.
## 2. Processo — montar e despachar rota
1. Pedidos `ready` no board
2. Operador em `/despacho` seleciona pedidos
3. `POST /api/routes/preview` (ordem sugerida)
4. `POST /api/routes` cria `DispatchBatch` + `DispatchStop`
5. `PATCH /api/routes/:id/driver` associa motoboy (`Driver`)
6. `POST /api/routes/:id/dispatch` sai para rua
7. Mapa acompanha; `POST /api/routes/:id/ping` atualiza lat/lng
8. Por stop: `POST /api/routes/:id/stops/:orderId/status` (a_caminho/entregue)
9. `POST /api/routes/:id/close` fecha batch
## 3. Processo — motoboy
1. UI `/motoboy`
2. `GET /api/routes/driver/:driverId` / `GET /api/routes/active`
3. Atualiza status das paradas
## 4. Cadastros apoio
- Drivers CRUD `/api/drivers`
- Zonas `/api/zones` · UI `/admin/zonas`
- Ops funnel/ranking/priority `/api/ops/*`
## 5. Aceite
- ✅ Routes API + Despacho/Motoboy pages
- ⚠️ Paridade mapa full-bleed (ver PRD vídeo)
- ⏳ ORS tour produção robusto
## 6. Camada de serviço (RoutesService)
Arquivo: `apps/api/src/routes/routes.service.ts` (~548 linhas)
| Método | Processo |
|--------|----------|
| `preview` | Ordena stops candidatos (sem persistir) |
| `buildStops` / `create` | Cria batch+stops |
| `assignDriver` | Liga Driver |
| `dispatch` | Status em rota |
| `ping` | GPS |
| `setStopStatus` | a_caminho / entregue / falha |
| `close` | Fecha batch |
| `listActive` / `activeForDriver` / `get` | Leituras UI |

View file

@ -0,0 +1,68 @@
# PRD — Estoque / SmartStock
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-ESTOQUE.md` |
| **Módulo** | Insumos, CMV, transferências, turnos |
| **Rotas UI** | `/estoque` `/estoque/smart/*` |
| **APIs** | `/api/estoque/*` `/api/estoque/smart/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Visão de implementação
Dois níveis:
1. **Estoque clássico** (`/api/estoque`) — insumos, ajuste, relatório, preview baixa
2. **SmartStock** (`/api/estoque/smart`) — estações, transferências, picking, turnos, contagens
Ponte com cardápio: BOM (`MenuItemRecipeLine`) e `stockMode`.
## 2. Processo — baixa por venda (conceitual)
1. Pedido confirmado com itens `stockMode=bom`
2. Preview `POST /api/estoque/preview`
3. Consumo grava `RecipeConsumption` / movimentos
4. Alerta se saldo insuficiente (strict mode `PATCH /api/estoque/strict`)
## 3. Processo — SmartStock transferência (dev steps)
1. Estação solicita: `POST /estoque/smart/requests`
2. Central vê `GET /estoque/smart/transfers`
3. `POST .../start-picking` → `PATCH .../picking` linhas
4. `POST .../dispatch` → envio
5. Destino `POST .../receive`
6. Movimentos auditáveis `GET /estoque/smart/movements`
## 4. Processo — turno / fechamento
1. `POST /estoque/smart/shifts/open`
2. Contagens `POST .../counts`
3. Aprovação por insumo `POST .../approve/:ingredientId`
4. `POST .../close`
5. UI: `/estoque/smart/fechamento/:shiftId`
## 5. UI map
- Dashboard, Central, Transferências, Consumo, Movimentos, Estação, Recebimento
## 6. Aceite
- ✅ Módulo SmartStock amplo na API/UI
- ⚠️ Strict/BOM amarrado 100% ao PDV em todos itens
- ⏳ NF compra / inventário físico completo
## 7. SmartStockService (~1838 linhas) — processos chave
| Método | Processo |
|--------|----------|
| `dashboard` / `listStations` / `stationBoard` | Visão |
| `createRequest` | Pedido de reposição |
| `startPicking` / `updatePickingLines` | Separação |
| `dispatchTransfer` / `receiveTransfer` | Envio/recebimento |
| `openShift` / `saveCounts` / `approveCount` / `closeShift` | Fechamento |
| `movements` / `movementDetail` / `moveBalance` | Auditoria saldo |

View file

@ -0,0 +1,100 @@
# PRD — Fase 1 — MVP Cozinha Digital
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-FASE1.md` |
| **Módulo** | PDV + KDS + Expedição (sem rotas ORS) |
| **Rotas UI** | `/pdv` `/pedidos` `/kds/:station` `/etiqueta/:id` |
| **APIs** | `/api/orders/*` `/api/kds/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo da Fase 1 (visão de implementação)
Entregar loop operacional **pedido → produção → pronto**, sem otimização de rotas.
ORS/motoboy tour ficam para despacho (Specs posteriores).
### Escopo entregue
1. PDV cria pedido
2. Central `/pedidos` vê fila
3. KDS multi-estação com claim/bump
4. Label/etiqueta
5. Gate `order.ready` quando tickets fecham
### Fora
App motoboy avançado, iFood, multi-loja, ORS.
---
## 2. Processo ponta a ponta (dev walkthrough)
### A) Criação do pedido (PDV)
1. `POST /api/auth/login`
2. Operador monta carrinho (cardápio)
3. `POST /api/orders` com `origin`, `fulfillment`, items, customer
4. Service cria `Order` + `OrderItem` + `OrderTicket` por estação mapeada
5. Emite eventos Socket.io para KDS/Central
### B) Central de pedidos
1. `GET /api/orders` (+ filtros origin/status)
2. UI `/pedidos` mostra badges (Aplicativo/WhatsApp/Telefone/PDV)
3. `PATCH /api/orders/:id/urgent` · `PATCH .../status` · `PATCH .../payment`
4. Demo digital: `POST /api/orders/demo-digital`
### C) Cozinha (KDS clássico)
1. `GET /api/kds/:station` → fila / comigo / bloqueados
2. `POST /api/kds/:station/claim/:orderId` → claim exclusivo
3. Trabalha item → `POST .../bump` avança ticket
4. Expedição só libera quando demais estações concluíram
5. Auto `order.ready` quando todos tickets fecham
### D) Etiqueta
1. `GET /api/orders/:id/label`
2. UI `/etiqueta/:id` (ESC/POS ou PDF conforme implementação)
---
## 3. Máquina de estados (Order)
```text
created/received → in_kitchen → ready → (despacho/entrega)
↘ cancelled
```
Tickets por estação: `pending → claimed → done` (simplificado).
## 4. Aceite
- ✅ Loop PDV→KDS→ready
- ✅ Claim exclusivo
- ⚠️ SLA timers por categoria (SPEC menciona)
- ⏳ Rotas ORS (não Fase 1)
## 5. Camada de serviço (OrdersService) — o que o código faz
Arquivo: `apps/api/src/orders/orders.service.ts` (~811 linhas)
| Método | Processo |
|--------|----------|
| `create` | Gera código (`nextCode`), persiste Order+Items, cria tickets KDS, emite realtime |
| `list` / `get` | Lista/detalhe com filtros para Central |
| `transition` | Muda status do pedido (máquina de estados) |
| `setUrgent` / `setPayment` | Flags operacionais/financeiras |
| `label` | Payload da etiqueta |
| `trackByHash` | Tracking público sem auth completa |
| `createDemoDigital` | Pedido sintético canal digital |
| `dayPool` | Pool do dia (agrupamento) |
### Erros que o dev deve tratar no front
- 401 sem JWT
- 400 validação items/fulfillment
- 409/422 transição ilegal de status

View file

@ -0,0 +1,65 @@
# PRD — KDS Claim (PEGAR) + pooling
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-KDS-CLAIM.md` |
| **Módulo** | KDS multi-estação clássico |
| **Rotas UI** | `/kds` `/kds/:station` |
| **APIs** | `GET/POST /api/kds/:station*` `/api/kds/ready/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Problema
Sem claim, duas estações pegam o mesmo pedido (CityFoods resolve com PEGAR exclusivo).
## 2. Processo — fila de estação
1. Cozinheiro abre `/kds/:station` (massa|montagem|forno|expedicao…)
2. `GET /api/kds/:station` devolve seções: **Fila / Comigo / Bloqueados**
3. Na Fila, clicar PEGAR **não** claima imediatamente → confirmação (Spec)
4. Confirma → `POST /api/kds/:station/claim/:orderId`
5. Outras estações veem pedido **bloqueado** (`claimedStationId`)
6. Ao concluir → `POST /api/kds/:station/orders/:orderId/bump`
7. Expedição só bumpa quando pré-requisitos ok
8. Ready board: `GET /api/kds/ready/list`
## 3. Processo — pós-pronto
- `POST /api/kds/ready/:orderId/estufa`
- `POST /api/kds/ready/:orderId/dispatch`
- `POST /api/kds/ready/:orderId/deliver`
- `POST /api/kds/ready/batch-dispatch`
## 4. Pooling
Pedidos podem agrupar saída (drawer pooling na UI) antes do despacho.
## 5. Aceite
- ✅ Claim/bump/ready endpoints
- ✅ UI KdsPage seções
- ⚠️ Confirmar UX “confirmação antes do claim” em todos fluxos
## 6. Camada de serviço (KdsService) — claim clássico
Arquivo: `apps/api/src/kds/kds.service.ts` (~1221 linhas)
| Método | Processo |
|--------|----------|
| `stationBoard` | Monta Fila/Comigo/Bloqueados da estação |
| `claim` | Exclusivo: grava claimedStationId/claimedAt; bloqueia peers |
| `bumpOrder` | Avança ticket; pode disparar ready |
| `ensurePrepTasks` | Garante tasks de produção |
| `listReady` | Board de prontos |
| `holdEstufa` | Move para estufa |
| `dispatch` / `batchDispatch` | Sai para despacho |
| `deliver` | Marca entregue no fluxo ready |
### Diálogo tipico Socket
Após claim/bump, server emite eventos para atualizar outras telas KDS sem refresh.

View file

@ -0,0 +1,57 @@
# PRD — KDS Pizzaiolo Modelo B
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-KDS-PIZZAIOLO-MODELO-B.md` |
| **Módulo** | Produção por pizza (montagem ≠ forno) |
| **Rotas UI** | `/kds/producao` |
| **APIs** | `/api/kds/pizzas/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Diferença do KDS clássico
Modelo B trabalha **PrepTask por pizza**, não só ticket por estação genérica.
Montagem e forno têm responsáveis independentes.
## 2. Processo — board pizzaiolo
1. UI `/kds/producao` → `GET /api/kds/pizzas/board`
2. Card por pizza (áreas coloridas, botões grandes)
3. `POST /api/kds/pizzas/:taskId/pegar` — assume montagem
4. `POST .../devolver` — devolve à fila
5. `POST .../enviar-forno` — handoff montagem→forno
6. `POST .../assumir-forno` — outro operador assume forno
7. `POST .../marcar-pronta` — pizza pronta
8. `POST .../transferir` — troca responsável
## 3. Estados típicos da task
```text
fila → em_montagem → no_forno → pronta → (estufa/expedição)
```
## 4. Aceite
- ✅ Endpoints pizzas/* e página KdsPizzaioloPage
- ⚠️ Paridade visual completa com mock Spec
## 5. Camada de serviço — pizzas/*
| Método | Ação do pizzaiolo |
|--------|-------------------|
| `pizzaBoard` | Snapshot do board |
| `pizzaPegar` | Assume card (montagem) |
| `pizzaDevolver` | Devolve à fila |
| `pizzaEnviarForno` | Handoff |
| `pizzaAssumirForno` | Outro user no forno |
| `pizzaMarcarPronta` | Finaliza pizza |
| `pizzaTransferir` | Troca responsável |
| `emitPizza` | Realtime do card |

View file

@ -0,0 +1,39 @@
# PRD — Lacunas vs operação SiriFood (vídeo)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-LACUNAS-VIDEO-SIRIFOOD.md` |
| **Módulo** | Gap analysis operacional |
| **Rotas UI** | `/despacho` `/kds` `/pedidos` |
| **APIs** | — |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Para que serve este PRD
Não descreve um módulo isolado: é o **checklist de lacunas** entre Pizza Digital
e a operação filmada (Siciliana/SiriFood ~70% iFood, despacho como coração).
## 2. Processo de uso (product/dev)
1. Assistir referência SiriFood
2. Percorrer despacho → estufa → conferência → motoboy na nossa UI
3. Marcar cada lacuna da Spec como ✅ mitigada / ⏳ aberta
4. Priorizar backlog (iFood cotação, estufa, conferência)
## 3. Temas típicos da Spec
- Despacho como hub
- Estufa
- Conferência
- Cotação iFood
- Multi-loja
## 4. Status
Documento vivo de gaps — não é feature shippable isolada.

View file

@ -0,0 +1,50 @@
# PRD — SPEC mãe — Pizza Digital (visão produto)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `SPEC.md / docs/SPEC.md` |
| **Módulo** | Produto completo Cozinha Digital + delivery |
| **Rotas UI** | todas as rotas |
| **APIs** | todas as APIs |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Posicionamento
SO da cozinha + delivery próprio (não marketplace). Referência CityFoods + OSS
(kitchenOS, rusterando, URY, MaSoVa, Tasty-Station).
## 2. Sequência oficial S0–S9 (como o time deve ler)
| Sprint | Entrega | PRD detalhado |
|--------|---------|---------------|
| S0–S1 bootstrap | Docker/VM125 | PRD-SPEC-FASE1 |
| S2–S3 KDS | claim/multi-estação | PRD-SPEC-KDS-CLAIM |
| S4 pizzaiolo | Modelo B | PRD-SPEC-KDS-PIZZAIOLO-MODELO-B |
| S5 canais | /pedidos + inbound | PRD-SPEC-CANAIS-DIGITAIS |
| Menu/Estoque | Track M/E | PRD-SPEC-CARDAPIO · ESTOQUE · CARDAPIO-JOINVILLE |
| ACS | matriz/users | PRD-SPEC-MATRIZ-ACESSO · USUARIOS |
| S7–S8 despacho | routes/motoboy | PRD-SPEC-DESPACHO · VIDEO-PARITY |
| Demo | /sim | PRD-SPEC-SIM-OPS-DEMO |
| Gaps iFood | — | PRD-SPEC-LACUNAS-SIRIFOOD |
## 3. Processo operacional completo (happy path)
1. Canal/PDV cria Order
2. KDS produz (clássico e/ou pizzaiolo)
3. Ready → estufa
4. Despacho monta rota → motoboy
5. Entrega → fecha batch
6. Estoque consome BOM
7. Admin gerencia menu/users/acessos
## 4. Aceite de produto (piloto)
- ✅ Fase 1 cozinha no ar
- ⚠️ Canais digitais em evolução
- ⏳ iFood / PWA completo

View file

@ -0,0 +1,69 @@
# PRD — Matriz de Acesso (MVP)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-MATRIZ-ACESSO.md` |
| **Módulo** | Capabilities admin por tenant |
| **Rotas UI** | `/admin/acessos` |
| **APIs** | `/api/access/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Ideia central (dev)
Roles operacionais (`gestor|pdv|kds|despacho`) ≠ capabilities admin.
Capabilities vivem em `UserCapability` e são **revalidadas no Core** a cada ação sensível.
### Caps
`menu.view/manage` · `staff.view/manage` · `permissions.manage` · `owners.manage` · `finance.view`
## 2. Processo — ver minhas permissões
1. Login JWT (`sub`, `storeId`, `role`)
2. `GET /api/access/me` → capabilities efetivas
3. Front esconde/mostra Admin conforme caps
## 3. Processo — editar matriz
1. Usuário com `permissions.manage`
2. `GET /api/access/matrix` carrega templates Perfil×Cap
3. Edita rascunho na UI `/admin/acessos`
4. `PUT /api/access/matrix` salva definição do template (atômico)
5. **Não** propaga sozinho aos users
## 4. Processo — aplicar template a usuários
1. Seleciona staff `GET /api/access/staff`
2. `POST /api/access/apply-template` { userIds, templateKey }
3. Reescreve `UserCapability`
4. Auditoria `AccessAuditLog` (quando habilitada)
## 5. Dependências Core
- `menu.manage` ⇒ `menu.view`
- `staff.manage` ⇒ `staff.view`
- Normalização em `capabilities.ts`
## 6. Aceite
- ✅ API matrix/me/staff/apply
- ✅ UI AccessMatrixPage
- ⚠️ Auditoria completa em todos writes
## 7. Camada de serviço (AccessService)
| Método | Fluxo |
|--------|-------|
| `ensureTemplates` | Garante templates default da loja |
| `getEffectiveCapabilities` | Resolve caps (+ fallback gestor) |
| `assertCapability` | Throws ForbiddenException |
| `getMatrix` / `saveMatrix` | CRUD definição |
| `applyTemplate` | Propaga para users |
| `listStaffForApply` | Alvos |
| `assertTenantKeepsOwner` | Não deixa loja sem owner |
| `setUserCapabilities` | Write direto |

View file

@ -0,0 +1,54 @@
# PRD — Simulação de Operação (Demo)
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-SIM-OPS-DEMO.md` |
| **Módulo** | Motor /sim |
| **Rotas UI** | `/sim` |
| **APIs** | `/api/sim/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Objetivo
Demonstrar ciclo completo Joinville sem operação real: canais → KDS → estufa → rotas → ETA.
## 2. Processo — operar o simulador
1. Login (gestor/ops)
2. Abrir `/sim`
3. `GET /api/sim/status`
4. `POST /api/sim/start` — inicia geração
5. Opcional `POST /api/sim/simulate-turno`
6. Observar `/pedidos`, `/kds/producao`, `/despacho`
7. `POST /api/sim/stop`
8. Limpar: `POST /api/sim/purge`
## 3. Parâmetros típicos (Spec)
Até ~2000 ops/dia · 15 motoboys SIM · cap prep · Joinville.
## 4. Aceite
- ✅ Controller/UI sim
- ⚠️ Calibrar carga para demo comercial sem derrubar VM
## 5. Motor SimService (~1090 linhas)
| Método | Papel no loop |
|--------|----------------|
| `start` / `stop` / `statusRich` | Controle |
| `tick` | Heartbeat do simulador |
| `ingress` | Gera pedidos (canais) |
| `advanceKitchen` | Empurra KDS |
| `dispatchReady` | Cria rotas |
| `completeDeliveries` | Fecha entregas |
| `ensureFleet` / `ensurePizzaiolos` | Seeds SIM |
| `simulateTurno` | Atalho turno |
| `purge` | Limpa dados teste |

View file

@ -0,0 +1,65 @@
# PRD — Usuários, senha e sessão
| Campo | Valor |
|-------|--------|
| **Produto** | Pizza Digital |
| **Versão app auditada** | v0.5.0 |
| **Ambiente** | https://pizza.itecnologys.com · VM125 · loja `pizza-digital-piloto` |
| **Spec de origem** | `docs/SPEC-USUARIOS.md` |
| **Módulo** | Auth + equipe |
| **Rotas UI** | `/login` `/admin/equipe` `/forgot-password` `/reset-password` |
| **APIs** | `/api/auth/*` `/api/users/*` |
| **Data** | 2026-11-09 |
| **Estilo** | PRD operacional detalhado (visão de desenvolvedor) |
| **Audiência** | Dev / QA / Product |
> Como ler: cada seção descreve o **processo real** (o que o sistema faz hoje),
> com passos de usuário, chamadas de API, regras de negócio e estados.
> Status: ✅ construído · ⚠️ parcial · ⏳ especificado / não entregue · 🐛 gap observado.
## 1. Entidades
`User`, `AuthToken`, `PushDevice`, `NotifyLog`, `UserCapability`
## 2. Processo — login
1. UI `/login` (demo: `pdv@pizza.local` / `805353` + storeSlug)
2. `POST /api/auth/login` { email, password, storeSlug }
3. Valida hash bcrypt; incrementa `failedLoginAttempts`
4. 5 falhas → `lockedUntil` +15 min
5. Sucesso → JWT + user + capabilities
6. `GET /api/auth/me` para refresh de sessão
## 3. Processo — política de senha
1. `GET /api/auth/password-policy`
2. Regras: ≥8, 1 upper, 1 lower, 1 dígito, sem local-part email
3. Código: `password-policy.ts`
## 4. Processo — CRUD equipe
1. Cap `staff.view` lista `GET /api/users`
2. Cap `staff.manage` cria `POST /api/users` (role, áreas, jobTitle)
3. Criar gestor extra exige `owners.manage`
4. Pode aplicar template na criação
5. `POST /api/users/:id/send-reset` dispara token reset
## 5. Processo — forgot / reset
1. `POST /api/auth/forgot-password` → resposta genérica
2. Token `password_reset` TTL 60 min
3. `POST /api/auth/reset-password` consome token, limpa lockout
4. `POST /api/auth/change-password` (autenticado)
## 6. Aceite
- ✅ Login/lockout/policy/CRUD/reset stub
- ⏳ SMTP/push produção (RF-USR-10)
## 7. Camada de serviço (AuthService)
| Método | Fluxo |
|--------|-------|
| `login` | storeSlug+email+senha → JWT; lockout |
| `me` | Rehidrata user+caps |
| `requestPasswordReset` | Token genérico |
| `resetPassword` | Consome token |
| `changePassword` | Autenticado |
UsersService: list/meta/create/update/sendReset/pushDevice.

View file

@ -0,0 +1,24 @@
# PRDs — Pizza Digital
PRDs **detalhados** (visão de desenvolvedor): Spec × código/API/UI × processos passo a passo.
App auditado: https://pizza.itecnologys.com · v0.5.0 · 2026-11-09
| PRD | Spec |
|-----|------|
| [PRD-SPEC-MAE.md](PRD-SPEC-MAE.md) | `SPEC.md` |
| [PRD-SPEC-FASE1.md](PRD-SPEC-FASE1.md) | `SPEC-FASE1.md` |
| [PRD-SPEC-CANAIS-DIGITAIS.md](PRD-SPEC-CANAIS-DIGITAIS.md) | `SPEC-CANAIS-DIGITAIS.md` |
| [PRD-SPEC-CARDAPIO.md](PRD-SPEC-CARDAPIO.md) | `SPEC-CARDAPIO.md` |
| [PRD-CARDAPIO-JOINVILLE.md](PRD-CARDAPIO-JOINVILLE.md) | `CARDAPIO-JOINVILLE.md` |
| [PRD-SPEC-ESTOQUE.md](PRD-SPEC-ESTOQUE.md) | `SPEC-ESTOQUE.md` |
| [PRD-SPEC-MATRIZ-ACESSO.md](PRD-SPEC-MATRIZ-ACESSO.md) | `SPEC-MATRIZ-ACESSO.md` |
| [PRD-SPEC-USUARIOS.md](PRD-SPEC-USUARIOS.md) | `SPEC-USUARIOS.md` |
| [PRD-SPEC-KDS-CLAIM.md](PRD-SPEC-KDS-CLAIM.md) | `SPEC-KDS-CLAIM.md` |
| [PRD-SPEC-KDS-PIZZAIOLO-MODELO-B.md](PRD-SPEC-KDS-PIZZAIOLO-MODELO-B.md) | `SPEC-KDS-PIZZAIOLO-MODELO-B.md` |
| [PRD-SPEC-DESPACHO.md](PRD-SPEC-DESPACHO.md) | `SPEC-DESPACHO-CITYFOODS-PARITY.md` |
| [PRD-SPEC-CITYFOODS-VIDEO-PARITY.md](PRD-SPEC-CITYFOODS-VIDEO-PARITY.md) | `SPEC-CITYFOODS-VIDEO-PARITY.md` |
| [PRD-SPEC-LACUNAS-SIRIFOOD.md](PRD-SPEC-LACUNAS-SIRIFOOD.md) | `SPEC-LACUNAS-VIDEO-SIRIFOOD.md` |
| [PRD-SPEC-SIM-OPS-DEMO.md](PRD-SPEC-SIM-OPS-DEMO.md) | `SPEC-SIM-OPS-DEMO.md` |
Cada PRD inclui: artefatos de código, processos numerados, APIs, estados e aceite/gaps.