pizza-digital/docs/SPEC-ESTOQUE.md
Admin d669f56398 Import Pizza Digital SPECs and docs from Obsidian vault sync
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-09 19:52:34 +00:00

8.5 KiB
Raw Blame History

SPEC — Estoque (Insumos & CMV)

Campo Valor
Produto Pizza Digital
Capítulo SPEC §7.9 RF-EST (novo)
Versão 0.1.0
Data 2026-10-19
Owner Roger / iTecnologys
SPEC irmã (obrigatória) SPEC-CARDAPIO.md — menu + ficha técnica
Dispara baixa Order confirmado → em_producao (Central / PDV / canais)

1. Objetivo

Controlar o que a cozinha tem (insumos e embalagens), amarrado ao o que a loja vende (cardápio).

Sem estoque ligado ao cardápio: pedido vende o que não existe → ruptura, CMV cego, pausa manual.

Compra / ajuste ──► Ingredient.stockQty
                         │
Pedido (OrderItem) ──BOM──┤
                         ▼
              StockMovement (saída)
                         │
                         ▼
              se qty < min → MenuItem paused

2. Escopo

Inclui

  • Cadastro de insumos (Ingredient) com unidade e saldo
  • Ficha técnica (Recipe) por MenuItem (+ tamanho opcional)
  • Movimentos: entrada (compra), saída (pedido), ajuste, perda
  • Alerta mínimo / pausa automática no cardápio
  • Relatório CMV simples (custo teórico por pedido)
  • SKU 1:1 para bebidas prontas (refri, energético)

Não inclui (fases posteriores)

  • NFe XML automática / SPED
  • Multi-depósito / transferência entre lojas
  • WMS / código de barras avançado
  • Produção de massa com OP industrial

3. Modelo de dados

Ingredient
  id, storeId, name, sku?
  unit          ← g | ml | un | kg | L
  stockQty      ← Decimal
  minQty        ← alerta
  costCents     ← custo médio unitário (na unidade base)
  active

Recipe
  id, storeId, menuItemId
  sizeCode?     ← broto|media|grande|gigante|null (= preço base)
  yieldNote?    ← "1 pizza G"
  lines: RecipeLine[]

RecipeLine
  id, recipeId, ingredientId
  qty           ← quantidade na unidade do Ingredient
  wasteFactor?  ← 1.05 = 5% perda

StockMovement
  id, storeId, ingredientId
  kind          ← purchase|sale|adjust|waste|cancel_restore
  qty           ← sinal: + entrada / − saída
  unitCostCents?
  refType       ← order|orderItem|manual|purchase
  refId?
  note?, userId?, createdAt

MenuItem.stockMode   ← bom | sku | none   (campo no Cardápio)
MenuItem.skuIngredientId?  ← quando stockMode=sku

4. Ponte com Cardápio

Contrato: todo item vendável com impacto de estoque declara stockMode na SPEC-CARDAPIO.

stockMode Baixa
bom Soma RecipeLine.qty × OrderItem.quantity (meia-a-meia: 0,5 + 0,5)
sku −1 un do skuIngredientId por unidade vendida
none Sem movimento

Momento da baixa (política piloto)

Momento Ação
order → em_producao Baixa (sale) — padrão piloto
order → cancelado e ainda não saiu da cozinha Estorno (cancel_restore)
Após pronto Cancelamento não devolve (perda / waste opcional)

Alternativa futura: reserva no confirmado + baixa no pronto.

Exemplos Joinville

Calabresa G (bom) — pesos em g (fonte: FICHAS-TECNICAS-PESO.md):

Insumo Qty
Massa (disco) 480 g
Molho tomate 90 g
Mussarela 200 g
Calabresa fatiada 120 g
Cebola 40 g
Orégano 2 g
Peso montado ≈ 930 g

Coca-Cola 2L (sku): −1 un ingredient:coca-2l

Vitamina Morango (bom):

Insumo Qty
Leite integral 300 ml
Morango 100 g
Açúcar 20 g
Gelo 100 g

4.1 Quantização por peso — pizzas (obrigatório)

Catálogo completo (38 tipos): data/fichas-pizzas-peso.json · resumo FICHAS-TECNICAS-PESO.md

Regra Valor
Unidade canônica toppings/massa gramas (g)
Base Grande 40 cm massa 480 · molho 90 · mussarela 200
Base Broto 25 cm massa 200 · molho 40 · mussarela 85 (≈ 0,42× G)
Baixa Σ (line.qty_g × quantity)
Meia-a-meia massa/molho 100% · toppings 50% de cada sabor
Cobertura piloto 38 pizzas (20 trad. + 5 broto + 6 especiais SC + 7 doces)

Cada tipo de pizza tem ficha própria — não compartilhar um único “peso médio”. Ajustes por loja na UI sem quebrar o JSON seed.


5. Requisitos (RF-EST)

ID Requisito Track
RF-EST-01 CRUD insumos (nome, unidade, min, custo) E1
RF-EST-02 Ficha técnica por MenuItem (+ size) E1
RF-EST-03 Baixa automática no pedido (política §4) E1
RF-EST-04 Entrada por compra / ajuste manual E1
RF-EST-05 Alerta stockQty ≤ minQty (WS + UI gestor) E1
RF-EST-06 Pausa automática MenuItem se insumo crítico zerar E2
RF-EST-07 Estorno em cancelamento elegível E1
RF-EST-08 Relatório CMV teórico por dia / item E2
RF-EST-09 Inventário físico (contagem → ajuste) E2
RF-EST-10 Perda / desperdício com motivo E2
RF-EST-11 Bloquear venda se strictStock=true e saldo insuficiente E2
RF-EST-12 Auditoria: todo movimento com user + ref E1
RF-EST-13 Ficha por tipo de pizza com qty em gramas (38+ SKUs menu) E1
RF-EST-14 Importar/versionar catálogo fichas-pizzas-peso.json E1
RF-EST-15 Escala Broto/Grande/Gigante por fator ou ficha dedicada E1

6. Eventos

stock.low          → store:{id}     (ingredientId, qty, minQty)
stock.updated      → store:{id}
menu.item.paused   → store:{id}     (menuItemId, reason=stock)
menu.item.resumed  → store:{id}

PDV / PWA escutam menu.item.paused|resumed (SPEC-CARDAPIO RF-MEN-13).


7. Regras de negócio

  1. Unidade canônica por insumo; conversões (kg↔g) só na UI de entrada.
  2. Custo médio móvel em compras: atualiza Ingredient.costCents.
  3. Meia-a-meia: duas half-recipes; se faltar um sabor, cardápio bloqueia o par.
  4. Bebidas sku: não passam por montagem/forno; só estação bebidas + expedição.
  5. Vitaminas/sucos naturais: baixa no mesmo momento do pedido; se fruta acabou → pausa só o sabor.
  6. strictStock (config loja): default false no piloto (alerta sem bloquear); true em produção madura.

8. Track E — implementação

ID Entrega Dependência
E0 Este SPEC + link no SPEC.md / Cardápio ✅ agora
E1 Prisma Ingredient/Recipe/Movement + baixa no create/transition feito 2026-10-20
E2 Pausa auto + CMV + inventário UI E1 · Central estável
E3 Compras com custo médio + multi-loja Fase 3

Ordem sugerida com Cardápio: M0 (menu Joinville) → E1 → M1/M2 (admin ficha) → E2.


9. Critérios de aceite

  1. Cadastro de mussarela / calabresa / Coca 2L com saldo e mínimo.
  2. Ficha Calabresa G salva e listável a partir do MenuItem.
  3. Criar pedido com 1× Calabresa G reduz mussarela em 200 g (ou qty da ficha).
  4. Criar pedido com 1× Coca 2L reduz 1 un do SKU.
  5. Cancelar pedido em produção devolve saldo.
  6. Mussarela em 0 → itens BOM que usam mussarela pausam (E2) ou alerta (E1).
  7. Movimentos auditáveis com refType=order.

10. UI alvo (gestor)

Tela Rota (proposta) Função
Insumos /estoque Lista + saldo + min
Ficha técnica /cardapio/:itemId/ficha BOM editor
Movimentos /estoque/movimentos Extrato
Inventário /estoque/inventario Contagem

Papel: gestor (escrita) · pdv (leitura alertas).


11. Fora de escopo

  • Integração contábil completa
  • Validade / lote FEFO (fase futura)
  • App de compras do fornecedor

12. Glossário cruzado

Termo Onde
MenuItem SPEC-CARDAPIO — o que vende
Recipe / BOM Esta SPEC — como consome
Ingredient Esta SPEC — o que tem
stockMode Cardápio declara · Estoque executa
Order SPEC principal / Central — dispara baixa

SPEC satélite. Versão do produto pai: SPEC.md. Cruzamento obrigatório com SPEC-CARDAPIO.


13. Implementação E1 (2026-10-20)

Entregue: stockQty · StockMovement · strictStock · /admin/estoque · baixa em produção · estorno no cancelamento · RF-EST-11.

strictStock default false (piloto). Gestor liga em /admin/estoque para bloquear pedido sem saldo.