# SPEC — Cardápio (Menu) | Campo | Valor | |-------|--------| | **Produto** | Pizza Digital | | **Capítulo** | SPEC §7.5 RF-MEN · domínio Menu* | | **Versão** | 0.1.0 | | **Data** | 2026-10-19 | | **Owner** | Roger / iTecnologys | | **Pesquisa regional** | [`CARDAPIO-JOINVILLE.md`](CARDAPIO-JOINVILLE.md) | | **SPEC irmã (obrigatória)** | [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) — ficha técnica / BOM | | **Canais** | [`SPEC-CANAIS-DIGITAIS.md`](SPEC-CANAIS-DIGITAIS.md) — PWA `/c/:slug` | --- ## 1. Objetivo Ser a **fonte única da verdade** do que a loja vende: categorias, itens, preços, tamanhos, modifiers (borda/meia-a-meia) e mapeamento para KDS. O cardápio **não guarda saldo**. Saldo, compra e baixa ficam no **Estoque**. A ponte é a **ficha técnica (BOM)**: cada item do menu consome 1+ insumos. ```text Cardápio (o que vende) ──BOM──► Estoque (o que tem) │ │ ▼ ▼ PDV / PWA / iFood alerta / bloqueio / CMV │ ▼ Order → KDS ``` --- ## 2. Escopo ### Inclui - Categorias e itens (CRUD gestor) - Preços por tamanho (Broto / G / Gigante) ou SKU por tamanho - Meia-a-meia, bordas, adicionais - Map item → estações KDS + componentes (tags) - Disponibilidade: ativo / pausado / esgotado (via Estoque) - Cardápio Joinville piloto (tradicionais, especiais SC, doces, bebidas) - Exposição ao PDV, Central, PWA público e (futuro) iFood ### Não inclui (Estoque) - Quantidade em prateleira, NF de compra, inventário físico → [`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) --- ## 3. Modelo de dados (alvo) ```text MenuCategory id, storeId, name, sortOrder, active, channelVisibility[] MenuItem ← já existe (Prisma) id, storeId, categoryId, name, description priceCents ← preço base (ou ver Size) halfHalf, active, sortOrder stations[] · components[] MenuItemSize (novo — Track M1) id, menuItemId, sizeCode ← broto|media|grande|gigante diameterCm, slices, maxFlavors priceCents, active MenuModifier (borda / adicional) id, storeId, name, priceCents, kind ← borda|extra|bebida_combo stationCodes[] Recipe (ficha técnica) ← vive na SPEC-ESTOQUE, FK menuItemId id, menuItemId, sizeCode? lines[] → Ingredient + qty + unit ``` ### Tamanhos padrão Joinville (congelar no piloto) Referência de prato de mesa (~25 cm) + diâmetro / fatias comerciais SC: | sizeCode | Nome UI | cm | Fatias | ≈ pratos | Sabores máx. (split) | Fator preço (base = Grande) | |----------|---------|----|--------|----------|----------------------|------------------------------| | `broto` | Broto | 25 | 4 | 1 | **1** | 0,55 | | `pequena` | Pequena | 30 | 6 | 1,5 | **1** | 0,70 | | `media` | Média | 35 | 8 | 2 | **2** | 0,85 | | `grande` | Grande | 40 | 12 | 2,5 | **3** | 1,00 | | `gigante` | Gigante | 45 | 16 | 3 | **4** | 1,20 | | `familia` | Família | 50 | 20 | 3,5 | **4** | 1,35 | **Regras de split:** Broto e Pequena = inteira (1 sabor). Média até 2. Grande até 3. Gigante e Família até 4. Preço = **maior sabor** × fator do tamanho (+ borda). **Default comercial:** `grande` (40 cm). Catálogo em `GET /api/menu/sizes` e no sheet do PDV. --- ## 4. Categorias piloto (já no seed) | # | Categoria | Papel | |---|-----------|--------| | 1 | Pizzas Tradicionais | Sabores · preço base Grande; tamanho no pedido | | 2 | Especiais Joinville | Diferencial SC | | 3 | Pizzas Doces | Pós-salgada | | 4 | Refrigerantes | Acompanhamento | | 5 | Sucos | Natural + caixa | | 6 | Energéticos | Acompanhamento | | 7 | Vitaminas · frutas c/ leite | Feitas na hora | | 8 | Bordas e extras | Modifiers | --- ## 5. Requisitos (RF-MEN + extensão) | ID | Requisito | Fase | |----|-----------|------| | RF-MEN-01 | CRUD categorias, itens, preços, adicionais | ✅ parcial | | RF-MEN-02 | Mapear item → estações KDS | ✅ | | RF-MEN-03 | SLA por categoria/item | Fase 1 | | RF-MEN-04 | Cardápio digital público PWA | Track C1 | | RF-MEN-05 | Meia-a-meia / combos | ✅ split multi-sabor por tamanho | | RF-MEN-06 | Horário loja aberta/fechada | Track C1 | | RF-MEN-07 | Áreas entrega + taxa | Track C1 | | RF-MEN-08 | Tamanhos Broto→Família + preço por fator | ✅ PDV + `/menu/sizes` | | RF-MEN-09 | Pausar item (manual ou por estoque baixo) | **M1** | | RF-MEN-10 | Ficha técnica obrigatória p/ item produzido | **M1** → Estoque | | RF-MEN-11 | Bebida 1:1 → 1 unidade de SKU estoque | **M1** | | RF-MEN-12 | Vitamina/suco natural → BOM (fruta + leite + gelo) | **M1** | | RF-MEN-13 | Sync disponibilidade → PWA/PDV ≤ 2 s | Track C1+M1 | | RF-MEN-14 | Preço meia-a-meia = maior sabor (config) | ✅ regra | | RF-MEN-15 | Cada pizza com BOM em **gramas** (catálogo Joinville 38) | **M1** ↔ EST-13 | --- ## 6. Ponte Cardápio ↔ Estoque | Evento cardápio | Efeito estoque | |-----------------|----------------| | Criar/editar `MenuItem` produzido | Exigir `Recipe` (ou marcar `stockMode=none`) | | Pedido `confirmado` / `em_producao` | Reserva ou baixa (política EST) | | Pedido `cancelado` antes da produção | Estorna reserva | | Saldo < `minStock` de insumo crítico | Item → `paused` ou badge “esgotado” | | Compra / ajuste no Estoque | Recalcula disponibilidade do menu | Detalhe de baixas, **pesos em g por tipo de pizza**, unidades e alertas: **[`SPEC-ESTOQUE.md`](SPEC-ESTOQUE.md) §4–4.1** · [`FICHAS-TECNICAS-PESO.md`](FICHAS-TECNICAS-PESO.md) · [`data/fichas-pizzas-peso.json`](data/fichas-pizzas-peso.json). ### `stockMode` por item | Modo | Uso | Exemplo | |------|-----|---------| | `bom` | Consome receita | Pizza Calabresa G | | `sku` | 1 item = 1 unidade SKU | Coca 2L, Red Bull | | `none` | Sem controle | Observação / taxa | --- ## 7. Regras de negócio 1. Item `active=false` ou `paused` **não aparece** no PDV/PWA (gestor ainda vê no admin). 2. Meia-a-meia: ambos sabores precisam estar disponíveis; baixa BOM proporcional (½ + ½) — ver Estoque. 3. Borda é `MenuModifier` com BOM própria (catupiry/cheddar). 4. Vitamina: sempre `stockMode=bom` (leite + fruta + gelo); se faltar fruta → pausa só aquele sabor. 5. Preços em **centavos BRL**; UI pt-BR (`formatBRL`). --- ## 8. Track M — implementação | ID | Entrega | Dependência | |----|---------|-------------| | **M0** | Seed Joinville (pizzas + bebidas) no ar | ✅ | | **M1** | `Recipe` + `Ingredient` + baixa no pedido | SPEC-ESTOQUE E1 | | **M2** | Admin UI ficha técnica + pausa auto | M1 | | **M3** | `MenuItemSize` multi-preço | M0 | | **M4** | Cardápio PWA lê só itens disponíveis | C1 + M1 | --- ## 9. Critérios de aceite 1. Gestor lista/edita categorias e itens no admin (ou seed + API). 2. PDV mostra categorias Joinville com preços BRL. 3. Todo item `stockMode=bom|sku` tem ficha ou SKU ligado (M1). 4. Coca 2L sem saldo → some/pausada no PDV em ≤ 2 s (M1). 5. Pizza sem mussarela no estoque → Calabresa e Mussarela pausam (M1). 6. SPEC-ESTOQUE referencia este doc e vice-versa (sem requisitos órfãos). --- ## 10. Fora de escopo (agora) - Cardápio multi-idioma - Fotos HD / CMS marketing - Precificação dinâmica por horário - Marketplace multi-loja --- *SPEC satélite. Versão do produto pai: SPEC.md. Cruzamento obrigatório com SPEC-ESTOQUE.*