Add Pizza-Digital PRD folder (Cardápio Joinville example)

This commit is contained in:
Admin 2026-11-09 21:16:13 +00:00
parent 62a20a2573
commit efea024cbc
2 changed files with 408 additions and 0 deletions

View file

@ -0,0 +1,204 @@
# PRD — Cardápio Joinville (o que a plataforma faz)
| 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) |
---
## 1. Entendimento da demanda
Documentar **cada Spec** não só como intenção, mas como **PRD da plataforma real**:
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`.
---
## 2. Problema e objetivo
### 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.
### 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.
### Fora deste PRD
Saldo de estoque, NF, inventário → [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) / SmartStock.
---
## 3. O que a pesquisa Joinville definiu vs o que existe hoje
| 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 |
---
## 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)
```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ã
```
---
## 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 | ⏳ |
---
## 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*

View file

@ -0,0 +1,204 @@
# PRD — Cardápio Joinville (o que a plataforma faz)
| 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) |
---
## 1. Entendimento da demanda
Documentar **cada Spec** não só como intenção, mas como **PRD da plataforma real**:
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`.
---
## 2. Problema e objetivo
### 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.
### 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.
### Fora deste PRD
Saldo de estoque, NF, inventário → [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) / SmartStock.
---
## 3. O que a pesquisa Joinville definiu vs o que existe hoje
| 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 |
---
## 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)
```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ã
```
---
## 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 | ⏳ |
---
## 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*