Mirror all SPECs and construction docs from pizza-digital, add hub/sidebar links and bidirectional sync scripts.
724 lines
29 KiB
Markdown
724 lines
29 KiB
Markdown
# SPEC — Pizza Digital
|
||
|
||
| Campo | Valor |
|
||
|-------|--------|
|
||
| **Produto** | Pizza Digital |
|
||
| **Versão do SPEC** | **0.3.2** |
|
||
| **Status** | Fase 1 cozinha no ar · **Prioridade seguinte: entrada por canais digitais** |
|
||
| **Data** | 2026-07-23 · rev. matriz acesso 2026-10-19 |
|
||
| **Owner** | Roger / iTecnologys |
|
||
| **Host Dev** | Proxmox BIG · VMID **125** · `10.10.10.125` · user `mini` |
|
||
| **URL pública** | `https://pizza.itecnologys.com` (legado SPEC: pizza.myvexx.com) |
|
||
| **Detalhe Fase 1** | [`docs/SPEC-FASE1.md`](docs/SPEC-FASE1.md) |
|
||
| **Canais digitais** | [`docs/SPEC-CANAIS-DIGITAIS.md`](docs/SPEC-CANAIS-DIGITAIS.md) · §5.5 |
|
||
| **Cardápio** | [`docs/SPEC-CARDAPIO.md`](docs/SPEC-CARDAPIO.md) · RF-MEN · Joinville |
|
||
| **Estoque** | [`docs/SPEC-ESTOQUE.md`](docs/SPEC-ESTOQUE.md) · RF-EST · BOM ↔ menu |
|
||
| **Matriz de acesso** | [`docs/SPEC-MATRIZ-ACESSO.md`](docs/SPEC-MATRIZ-ACESSO.md) · `/acessos` · RF-ACS |
|
||
| **Sequência oficial** | §15 — S0…S9 · Track C · Track M/E · Matriz ACS |
|
||
| **Referência principal** | CityFoods — Cozinha Digital + Cardápio Digital (`@cityfoods_app`) |
|
||
| **KDS / estações** | kitchenOS + restaurant-pos + este SPEC |
|
||
| **Rotas / dispatch** | **rusterando** = referência oficial (ORS, driver tour) — AGPL: modelo operacional, não fork do core |
|
||
| **Repos open-source** | kitchenOS, rusterando, URY Mosaic, MaSoVa, Tasty-Station |
|
||
|
||
---
|
||
|
||
## 1. Visão
|
||
|
||
**Pizza Digital** é uma plataforma de operação de delivery para pizzarias, restaurantes e outras cozinhas, com foco em **Cozinha Digital (KDS)**: eliminar comanda de papel, organizar produção por estações, reduzir erros e acelerar despacho.
|
||
|
||
Não é um marketplace. É o **sistema operacional da cozinha + delivery próprio**, no mesmo espírito da CityFoods:
|
||
|
||
> Cozinha Digital não é sobre robôs — é inteligência e fluxo à prova de falhas, do pedido à entrega.
|
||
|
||
### 1.1 Problema
|
||
|
||
Operações de delivery perdem tempo e clientes por:
|
||
|
||
- Comandas de papel (perda, rasura, leitura ruim)
|
||
- Pedidos de vários canais em telas diferentes
|
||
- Falta de priorização (pedido novo não sai junto de outros prontos)
|
||
- Erros de observação / montagem
|
||
- Motoboys mal roteados (ida e volta na mesma região)
|
||
- Zero métrica de tempo por estação
|
||
|
||
### 1.2 Promessa
|
||
|
||
Uma plataforma única que:
|
||
|
||
1. Recebe pedidos (PDV, cardápio digital, marketplaces)
|
||
2. Distribui por **estações de cozinha** (KDS)
|
||
3. Identifica pedidos por **etiquetas**
|
||
4. Prioriza e agrupa saída
|
||
5. Despacha com **gestão de rotas**
|
||
6. Mede **tempo e produtividade** em tempo real
|
||
|
||
### 1.3 Posicionamento
|
||
|
||
| | CityFoods (referência) | Pizza Digital (nossa) |
|
||
|--|------------------------|------------------------|
|
||
| Foco | Delivery multi-tipo | **Pizzaria primeiro**, depois outras cozinhas |
|
||
| Diferencial citado | “Primeira Cozinha Digital” | Cozinha Digital + templates de estação por tipo de negócio |
|
||
| Mercado | SC / BR SaaS | Começar local / controlado, evoluir para SaaS multi-tenant |
|
||
|
||
---
|
||
|
||
## 2. Objetivos e métricas de sucesso
|
||
|
||
### 2.1 Objetivos de produto (MVP)
|
||
|
||
- Substituir comanda de papel por KDS touch
|
||
- Operar **1 pizzaria piloto** de ponta a ponta (pedido → pronto → despacho)
|
||
- Reduzir erros de montagem / observação
|
||
- Medir tempo médio por estação e por pedido
|
||
|
||
### 2.2 KPIs (piloto)
|
||
|
||
| KPI | Meta inicial (90 dias) |
|
||
|-----|------------------------|
|
||
| Erros de pedido (reclamação / refazer) | −50% vs baseline |
|
||
| Tempo médio pedido → pronto | −20% |
|
||
| Pedidos sem papel na cozinha | 100% no piloto |
|
||
| Atraso de despacho (> SLA) | −30% |
|
||
| Adoção diária do KDS | ≥ 95% dos pedidos passam pelo KDS |
|
||
|
||
### 2.3 Não-objetivos (MVP)
|
||
|
||
- App consumidor nativo (iOS/Android) completo
|
||
- Marketplace próprio
|
||
- Contabilidade / ERP completo
|
||
- Multi-país / multi-moeda
|
||
- IA generativa na cozinha
|
||
|
||
---
|
||
|
||
## 3. Personas e papéis
|
||
|
||
| Papel | Quem | Precisa |
|
||
|-------|------|---------|
|
||
| **Operador KDS** | Cozinheiro / pizzaiolo | Tela grande, bump rápido, ver observações |
|
||
| **Expedição** | Embalador / conferente | Pedido completo, etiqueta, agrupar saída |
|
||
| **Caixa / PDV** | Atendente | Lançar pedido balcão / telefone |
|
||
| **Despachante** | Quem libera motoboy | Agrupar por região, priorizar |
|
||
| **Entregador** | Motoboy | Lista de entregas, status, navegação básica |
|
||
| **Gestor** | Dono / gerente | Métricas, cardápio, usuários, relatórios |
|
||
| **Admin SaaS** (fase 2) | iTecnologys | Multi-loja, billing, suporte |
|
||
|
||
---
|
||
|
||
## 4. Escopo por fases
|
||
|
||
### Fase 0 — Fundação (esta SPEC + bootstrap)
|
||
|
||
- Repositório, monorepo, CI mínimo
|
||
- Modelo de domínio e eventos
|
||
- Ambiente local (Docker)
|
||
|
||
### Fase 1 — MVP Cozinha Digital (core) ✅ em andamento
|
||
|
||
> Detalhe completo: [`docs/SPEC-FASE1.md`](docs/SPEC-FASE1.md) · Host: VM **125** `10.10.10.125`
|
||
|
||
- Pedidos manuais (PDV web)
|
||
- KDS multi-estação (pizzaria)
|
||
- Status: `novo → em_preparo → pronto → despachado → entregue`
|
||
- Priorização / reordenação de fila
|
||
- Etiquetas (impressão ESC/POS ou PDF fallback)
|
||
- Painel gestor básico (tempos)
|
||
- Stack: NestJS + React + Postgres + Redis + Socket.io (Docker na VM 125)
|
||
|
||
### Fase 2 — Delivery operacional (após KDS estável)
|
||
|
||
> Prioridade de construção: **KDS multi-estação primeiro**; delivery/rotas só depois do piloto de cozinha (S5).
|
||
> Referência oficial de dispatch: **[rusterando](https://github.com/holg/rusterando)** (kitchen → driver tour → ORS). Detalhe: §15.1 e §15.2.
|
||
|
||
- Gate `order.ready` → fila de despacho
|
||
- Agrupar por bairro (manual + sugestão) + atribuir motoboy + reordenar saída (“2 cliques” CityFoods)
|
||
- OpenRouteService (padrão rusterando) para ordem da rota
|
||
- Mapa no despacho · PWA entregador · tracking
|
||
- Pagamento/comissão por entrega · fechamento de caixa básico
|
||
|
||
### Fase 3 — Canais digitais e SaaS (PRIORIDADE pós-S5)
|
||
|
||
> Track **C** (canais) começa em paralelo assim que o piloto de cozinha (S5) estiver estável — **não esperar o fim de S6–S8**.
|
||
> Ver §5.5 e [`docs/SPEC-CANAIS-DIGITAIS.md`](docs/SPEC-CANAIS-DIGITAIS.md).
|
||
|
||
- **C1** Cardápio digital público (PWA) + checkout (Pix / dinheiro na entrega)
|
||
- **C1** Pedidos digitais no quadro `/pedidos` com badge de origem
|
||
- **C2** Integração iFood (webhook → pedido normalizado)
|
||
- Multi-tenant / multi-loja
|
||
- Relatórios operacionais avançados
|
||
- Templates de cozinha: pizzaria, hamburgueria, sushi, dark kitchen
|
||
|
||
---
|
||
|
||
## 5. Conceito operacional — Cozinha Digital
|
||
|
||
### 5.1 Estações (template Pizzaria)
|
||
|
||
| Estação | Responsabilidade | Exemplos de itens |
|
||
|---------|------------------|-------------------|
|
||
| **Massa** | Abrir / preparar base | Massa, borda |
|
||
| **Montagem** | Molho, queijo, toppings | Sabores, adicionais |
|
||
| **Forno** | Assar | Pizza em forno |
|
||
| **Expedição** | Embalar, conferir, etiquetar | Pedido completo |
|
||
| **Bebidas** (opcional) | Separar frios | Refrigerante, água |
|
||
|
||
**Princípio KDS (CityFoods — claim exclusivo):**
|
||
|
||
1. A **fila chega para todas** as estações.
|
||
2. Uma estação **escolhe e puxa (PEGAR)** um ou mais pedidos para si.
|
||
3. Com o claim, **as outras estações ficam bloqueadas** de pegar aquele pedido.
|
||
4. Só a estação dona dá **BUMP** (pedido pronto).
|
||
|
||
Regras de mapeamento (histórico / tickets):
|
||
|
||
- Cada item do cardápio mapeia para **1+ estações** (referência de produção)
|
||
- Claim é ao nível do **pedido completo**, não por item
|
||
|
||
### 5.2 Template futuro — outras cozinhas
|
||
|
||
| Tipo | Estações padrão |
|
||
|------|-----------------|
|
||
| Hamburgueria | Grelha · Fritura · Montagem · Expedição |
|
||
| Sushi | Corte · Montagem · Expedição |
|
||
| Dark kitchen genérica | Prep · Quente · Frios · Expedição |
|
||
|
||
### 5.3 Etiquetas
|
||
|
||
Cada pedido (ou item, configurável) gera etiqueta com:
|
||
|
||
- Código curto do pedido (ex: `#A42`)
|
||
- Canal (PDV / iFood / Cardápio)
|
||
- Cliente (nome parcial)
|
||
- Itens resumidos + observações em destaque
|
||
- Horário / timer SLA
|
||
- QR opcional para conferência
|
||
|
||
Objetivo: eliminar grampear comanda ilegível na embalagem.
|
||
|
||
### 5.4 Priorização (inspirado CityFoods “2 cliques”)
|
||
|
||
O despachante/gestor pode:
|
||
|
||
- Reordenar fila de saída
|
||
- Agrupar pedidos da mesma região para sair juntos
|
||
- Marcar pedido como **urgente** (sobresai visualmente no KDS)
|
||
|
||
### 5.5 Entrada por canais digitais (PRIORIDADE)
|
||
|
||
> Detalhe de produto: [`docs/SPEC-CANAIS-DIGITAIS.md`](docs/SPEC-CANAIS-DIGITAIS.md) · RFs: RF-CAN, RF-PED-08/09, RF-MEN-04/06/07, RF-INT-01/03/05
|
||
|
||
**Problema:** pedidos chegam por telefone, WhatsApp e iFood em telas diferentes — a loja digita de novo no PDV e erra.
|
||
|
||
**Promessa:** o cliente pede no canal digital; a loja vê **o mesmo Order** no quadro `/pedidos` e a cozinha trata igual a pedido de balcão.
|
||
|
||
#### Dimensões (substituem `channel` misturado)
|
||
|
||
| Dimensão | Valores | Uso na UI |
|
||
|----------|---------|-----------|
|
||
| `origin` | `pdv` · `cardapio` · `ifood` · `whatsapp` · `telefone` | Badge no card (CARDÁPIO / IFOOD / …) |
|
||
| `fulfillment` | `entrega` · `retirada` · `mesa` | Faixa ENTREGA / RETIRADA (CityFoods) |
|
||
|
||
#### Canais de entrada → um quadro
|
||
|
||
```text
|
||
Cardápio PWA /c/:slug ─┐
|
||
WhatsApp (deep-link) ─┼─► Order Ingest (schema único)
|
||
iFood webhook ─┤ │
|
||
PDV / telefone (staff) ─┘ ▼
|
||
/pedidos (badge origem + fulfillment)
|
||
│
|
||
▼
|
||
KDS · Etiqueta · Despacho
|
||
```
|
||
|
||
#### Track C (após piloto S5; C1 pode prototipar em paralelo)
|
||
|
||
| Track | Entrega |
|
||
|-------|---------|
|
||
| **C1** | Cardápio público + checkout (Pix / pagar na entrega) → `/pedidos` ≤ 500 ms |
|
||
| **C2** | Webhook iFood → normalizador + idempotência |
|
||
|
||
**Regra de ouro:** nenhum canal tem UI de cozinha própria — tudo passa pelo Order bus e pelo `/pedidos`.
|
||
|
||
---
|
||
|
||
## 6. Fluxos principais
|
||
|
||
### 6.1 Fluxo feliz — delivery pizzaria (canal digital ou PDV)
|
||
|
||
```text
|
||
[Cliente] Cardápio /c/:slug | WhatsApp | iFood
|
||
[Staff] PDV /pedidos (+ Novo)
|
||
→ Order Ingest normaliza (origin + fulfillment + itens)
|
||
→ Aparece em /pedidos (badge origem · faixa ENTREGA/RETIRADA)
|
||
→ Roteia itens → estações KDS
|
||
→ Operadores dão claim/bump por estação
|
||
→ Expedição confere + imprime etiqueta (origem + fulfillment)
|
||
→ Pedido = PRONTO
|
||
→ Despacho atribui motoboy / agrupa rota
|
||
→ Entregador: saiu → entregue
|
||
→ Métricas gravadas (tempos por etapa)
|
||
```
|
||
|
||
### 6.2 Estados do pedido
|
||
|
||
```text
|
||
rascunho → confirmado → em_producao → pronto → em_rota → entregue
|
||
↓
|
||
cancelado
|
||
```
|
||
|
||
Estados de **item na estação**:
|
||
|
||
```text
|
||
na_fila → em_preparo → concluido | cancelado
|
||
```
|
||
|
||
### 6.3 Diagrama lógico
|
||
|
||
```text
|
||
Canais Core Operação
|
||
───── ──── ────────
|
||
PDV ──────┐
|
||
Cardápio ─┼─► Order Ingest ─► Router ─► KDS Stations
|
||
iFood ────┘ │ │ │
|
||
│ │ ▼
|
||
│ └──► Labels / Print
|
||
▼
|
||
Order Store ◄── WebSocket fan-out
|
||
│
|
||
▼
|
||
Dispatch / Routes ─► Driver PWA
|
||
│
|
||
▼
|
||
Analytics
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Requisitos funcionais
|
||
|
||
### 7.1 Pedidos (RF-PED)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-PED-01 | Criar pedido no PDV (itens, adicionais, obs, tipo: delivery/balcão/mesa) | Sim |
|
||
| RF-PED-02 | Schema único de pedido independente do canal | Sim |
|
||
| RF-PED-03 | Editar pedido até entrar em produção (política configurável) | Sim |
|
||
| RF-PED-04 | Cancelar pedido com motivo | Sim |
|
||
| RF-PED-05 | Observações em destaque no KDS | Sim |
|
||
| RF-PED-06 | Número sequencial diário + código curto legível | Sim |
|
||
| RF-PED-07 | Ingestão via webhook (iFood etc.) | Track C2 |
|
||
| RF-PED-08 | Campos `origin` + `fulfillment` (em vez de channel misturado) | Track C1 |
|
||
| RF-PED-09 | Pedido digital aparece no `/pedidos` em tempo real (WS) | Track C1 |
|
||
|
||
### 7.2 KDS / Cozinha Digital (RF-KDS)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-KDS-01 | Tela KDS por estação (filtro de área) | Sim |
|
||
| RF-KDS-02 | Atualização em tempo real (WebSocket, sem polling) | Sim |
|
||
| RF-KDS-03 | Timer visual (verde / amarelo / vermelho por SLA) | Sim |
|
||
| RF-KDS-04 | Bump item / bump pedido na estação | Sim |
|
||
| RF-KDS-05 | Multi-estação no mesmo pedido | Sim |
|
||
| RF-KDS-06 | Som/alerta opcional de novo ticket | Sim |
|
||
| RF-KDS-07 | Modo tela cheia / tablet / TV | Sim |
|
||
| RF-KDS-08 | Offline degradado (fila local + sync) | Fase 2 |
|
||
|
||
### 7.3 Etiquetas (RF-ETQ)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-ETQ-01 | Gerar etiqueta ao concluir expedição (ou sob demanda) | Sim |
|
||
| RF-ETQ-02 | Impressão térmica ESC/POS | Sim (com fallback PDF) |
|
||
| RF-ETQ-03 | Layout configurável por loja | Fase 2 |
|
||
|
||
### 7.4 Despacho e rotas (RF-ROT)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-ROT-01 | Lista de pedidos prontos para despacho | Fase 1 (lista simples) |
|
||
| RF-ROT-02 | Atribuir entregador | Fase 2 |
|
||
| RF-ROT-03 | Agrupar por bairro / proximidade | Fase 2 |
|
||
| RF-ROT-04 | Reordenar saída (priorização) | Fase 1 |
|
||
| RF-ROT-05 | App/PWA entregador com status | Fase 2 |
|
||
| RF-ROT-06 | Cálculo de pagamento de entregadores | Fase 3 |
|
||
|
||
### 7.5 Cardápio e PDV (RF-MEN)
|
||
|
||
> Detalhe: [`docs/SPEC-CARDAPIO.md`](docs/SPEC-CARDAPIO.md) · pesquisa [`docs/CARDAPIO-JOINVILLE.md`](docs/CARDAPIO-JOINVILLE.md)
|
||
> Ponte estoque: [`docs/SPEC-ESTOQUE.md`](docs/SPEC-ESTOQUE.md)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-MEN-01 | CRUD categorias, itens, preços, adicionais | Sim |
|
||
| RF-MEN-02 | Mapear item → estações KDS | Sim |
|
||
| RF-MEN-03 | Tempo SLA por categoria/item | Sim |
|
||
| RF-MEN-04 | Cardápio digital público (PWA cliente) | **Track C1** |
|
||
| RF-MEN-05 | Combos / meia-a-meia (pizzaria) | Fase 1 (meia-a-meia) |
|
||
| RF-MEN-06 | Horário de funcionamento / loja aberta-fechada no cardápio | Track C1 |
|
||
| RF-MEN-07 | Áreas de entrega + taxa por bairro no cardápio | Track C1 |
|
||
| RF-MEN-08 | Tamanhos com preço (`broto`/`grande`/…) | Track M1 |
|
||
| RF-MEN-09 | Pausar item (manual ou estoque baixo) | Track M1 |
|
||
| RF-MEN-10 | Ficha técnica (BOM) ligada ao item | Track M1 ↔ EST |
|
||
| RF-MEN-11 | Bebida `stockMode=sku` 1:1 | Track M1 |
|
||
| RF-MEN-12 | Vitamina/suco natural via BOM | Track M1 |
|
||
|
||
### 7.6 Gestão e métricas (RF-GES)
|
||
|
||
| ID | Requisito | MVP |
|
||
|----|-----------|-----|
|
||
| RF-GES-01 | Dashboard: pedidos abertos, atrasados, tempo médio | Sim |
|
||
| RF-GES-02 | Tempo médio por estação | Sim |
|
||
| RF-GES-03 | Relatório de fluxo do pedido (timestamps) | Sim |
|
||
| RF-GES-04 | Usuários, papéis, permissões | Sim |
|
||
| RF-GES-05 | Multi-loja / tenant | Fase 3 |
|
||
|
||
### 7.7 Integrações (RF-INT)
|
||
|
||
| ID | Requisito | Fase |
|
||
|----|-----------|------|
|
||
| RF-INT-01 | Webhook genérico de pedido | Track C1 |
|
||
| RF-INT-02 | iFood (ou agregador BR) | Track C2 |
|
||
| RF-INT-03 | Pagamento online (Pix / dinheiro na entrega) | Track C1 |
|
||
| RF-INT-04 | Impressoras de rede | 1 |
|
||
| RF-INT-05 | Deep-link WhatsApp → cardápio da loja | Track C1 |
|
||
|
||
### 7.8 Canais digitais (RF-CAN)
|
||
|
||
| ID | Requisito | Track |
|
||
|----|-----------|-------|
|
||
| RF-CAN-01 | PWA cardápio público por loja (`/c/:slug`) | C1 |
|
||
| RF-CAN-02 | Carrinho cliente → Order com `origin=cardapio` | C1 |
|
||
| RF-CAN-03 | Escolha fulfillment entrega/retirada no cardápio | C1 |
|
||
| RF-CAN-04 | Taxa / área de entrega no checkout | C1 |
|
||
| RF-CAN-05 | Pedido digital no `/pedidos` ≤ 500 ms (WS) | C1 |
|
||
| RF-CAN-06 | Badge de origem no card (CARDÁPIO / IFOOD / …) | C1 |
|
||
| RF-CAN-07 | Webhook iFood → normalizador | C2 |
|
||
| RF-CAN-08 | Idempotência / dedupe de pedidos externos | C2 |
|
||
|
||
### 7.9 Estoque (RF-EST)
|
||
|
||
> Detalhe: [`docs/SPEC-ESTOQUE.md`](docs/SPEC-ESTOQUE.md) · dispara a partir do Order · pausa o Cardápio
|
||
|
||
| ID | Requisito | Track |
|
||
|----|-----------|-------|
|
||
| RF-EST-01 | CRUD insumos (unidade, min, custo) | E1 |
|
||
| RF-EST-02 | Ficha técnica por MenuItem | E1 |
|
||
| RF-EST-03 | Baixa automática no pedido (`em_producao`) | E1 |
|
||
| RF-EST-04 | Entrada compra / ajuste manual | E1 |
|
||
| RF-EST-05 | Alerta estoque mínimo (WS) | E1 |
|
||
| RF-EST-06 | Pausa automática do item no cardápio | E2 |
|
||
| RF-EST-07 | Estorno em cancelamento elegível | E1 |
|
||
| RF-EST-08 | CMV teórico por dia/item | E2 |
|
||
| RF-EST-13 | Ficha por pizza com qty em **gramas** (38 tipos) | E1 |
|
||
| RF-EST-14 | Catálogo `fichas-pizzas-peso.json` | E1 |
|
||
|
||
**Regra de ouro:** Cardápio declara `stockMode` (`bom`\|`sku`\|`none`); Estoque executa a baixa.
|
||
**Pizzas:** baixa por **peso (g)** por tipo — [`docs/FICHAS-TECNICAS-PESO.md`](docs/FICHAS-TECNICAS-PESO.md).
|
||
|
||
---
|
||
|
||
## 8. Requisitos não-funcionais
|
||
|
||
| ID | Tema | Requisito |
|
||
|----|------|-----------|
|
||
| RNF-01 | Latência KDS | Novo pedido visível na tela ≤ **500 ms** (LAN saudável) |
|
||
| RNF-02 | Disponibilidade | MVP single-node OK; alvo produção 99.5% |
|
||
| RNF-03 | Concorrência | Suportar pico de **60 pedidos/hora** no piloto |
|
||
| RNF-04 | UX cozinha | Touch-first, botões grandes, alto contraste, legível a 1–2 m |
|
||
| RNF-05 | Segurança | Auth JWT/session; senhas hashed; HTTPS; RBAC |
|
||
| RNF-06 | Auditoria | Log de mudanças de status com user + timestamp |
|
||
| RNF-07 | Observabilidade | Logs estruturados + healthcheck |
|
||
| RNF-08 | Idioma | PT-BR nativo |
|
||
| RNF-09 | Deploy | Docker Compose local; caminho claro para VPS/Proxmox |
|
||
| RNF-10 | LGPD | Dados de cliente mínimos; retenção configurável |
|
||
|
||
---
|
||
|
||
## 9. Arquitetura alvo
|
||
|
||
### 9.1 Princípios
|
||
|
||
1. **Order bus / schema único** — todo canal vira o mesmo `Order`
|
||
2. **Event-driven para cozinha** — WebSocket fan-out por loja/estação
|
||
3. **Station routing** — regras no servidor, não na UI
|
||
4. **PWA** — KDS e entregador rodam no browser/tablet
|
||
5. **Começar simples** — 1 processo API + Postgres + Redis; extrair microsserviços só se necessário
|
||
|
||
### 9.2 Stack sugerida (do zero)
|
||
|
||
| Camada | Tecnologia | Motivo |
|
||
|--------|------------|--------|
|
||
| Frontend | React + Vite + TypeScript (PWA) | KDS/PDV touch, ecossistema forte |
|
||
| Realtime | Socket.io ou native WS | Padrão dos KDS de referência |
|
||
| API | NestJS ou Fastify (Node/TS) | Tipagem compartilhada, rapidez |
|
||
| DB | PostgreSQL | Pedidos, auditoria, relatórios |
|
||
| Cache / pubsub | Redis | Tickets abertos + fan-out |
|
||
| Filas (fase 2+) | BullMQ | Webhooks, impressão, retries |
|
||
| Print | ESC/POS (node) + PDF fallback | Etiquetas térmicas |
|
||
| Infra local | Docker Compose | Postgres + Redis + API + Web |
|
||
|
||
Referências de forma (não copy-paste cego):
|
||
|
||
- **kitchenOS** → ingestão + KDS + Redis stream
|
||
- **Tasty-Station** → Socket.io POS↔KDS
|
||
- **rusterando** → **referência oficial** pizzaria + rotas / ORS / driver tour (modelo, não fork AGPL)
|
||
- **URY Mosaic** → multi-kitchen KDS
|
||
|
||
### 9.3 Apps da plataforma
|
||
|
||
| App | URL mental | Usuário |
|
||
|-----|------------|---------|
|
||
| `web-pdv` | `/pdv` | Caixa |
|
||
| `web-kds` | `/kds/:station` | Cozinha |
|
||
| `web-dispatch` | `/despacho` | Despachante |
|
||
| `web-admin` | `/admin` | Gestor |
|
||
| `web-driver` | `/entregador` | Motoboy (fase 2) |
|
||
| `web-menu` | `/m/:slug` | Cliente (fase 3) |
|
||
|
||
Monorepo sugerido:
|
||
|
||
```text
|
||
pizza-digital/
|
||
├── SPEC.md # este documento
|
||
├── docs/
|
||
│ ├── domain.md # glossário e regras
|
||
│ ├── api.md # contratos HTTP/WS
|
||
│ └── ui-kds.md # wireframes textuais
|
||
├── apps/
|
||
│ ├── web/ # PDV + KDS + Admin (rotas)
|
||
│ └── api/
|
||
├── packages/
|
||
│ ├── domain/ # types Order, Station, events
|
||
│ └── escpos/ # impressão
|
||
└── docker-compose.yml
|
||
```
|
||
|
||
---
|
||
|
||
## 10. Modelo de domínio (MVP)
|
||
|
||
### 10.1 Entidades
|
||
|
||
- **Store** — loja
|
||
- **User** — usuário + role
|
||
- **Station** — estação KDS
|
||
- **Category / Product / Modifier** — cardápio ([SPEC-CARDAPIO](docs/SPEC-CARDAPIO.md))
|
||
- **ProductStationRule** — produto → estações
|
||
- **Recipe / RecipeLine** — ficha técnica BOM ([SPEC-ESTOQUE](docs/SPEC-ESTOQUE.md))
|
||
- **Ingredient** — insumo com saldo
|
||
- **StockMovement** — entrada/saída/ajuste
|
||
- **Order** — pedido
|
||
- **OrderItem** — item do pedido (+ modifiers, notes)
|
||
- **StationTicket** — fatia do item/pedido na estação
|
||
- **LabelPrintJob** — job de etiqueta
|
||
- **Courier** (fase 2) — entregador
|
||
- **DispatchBatch** (fase 2) — lote de rota
|
||
|
||
### 10.2 Campos críticos de `Order`
|
||
|
||
```text
|
||
id, store_id, code, channel, type (delivery|pickup|dine_in),
|
||
status, customer_name, customer_phone, address,
|
||
notes, priority, promised_at,
|
||
accepted_at, production_started_at, ready_at,
|
||
dispatched_at, delivered_at, canceled_at,
|
||
created_at, updated_at
|
||
```
|
||
|
||
### 10.3 Eventos (WebSocket)
|
||
|
||
```text
|
||
order.created
|
||
order.updated
|
||
order.canceled
|
||
ticket.upserted
|
||
ticket.bumped
|
||
order.ready
|
||
order.dispatched
|
||
order.delivered
|
||
label.printed
|
||
```
|
||
|
||
Rooms: `store:{id}`, `store:{id}:station:{stationId}`
|
||
|
||
---
|
||
|
||
## 11. Regras de negócio — pizzaria
|
||
|
||
1. **Meia-a-meia**: 1 pizza = 2 sabores; preço = maior sabor (configurável); aparece no KDS como um item com 2 metades.
|
||
2. **Borda / adicionais**: modifiers ligados à montagem (ou massa, se borda recheada).
|
||
3. **Tempo SLA padrão** (editável): Massa 3 min · Montagem 5 · Forno 8 · Expedição 3 — total alvo ~20 min.
|
||
4. **Pedido delivery sem endereço** não confirma.
|
||
5. **Bump na expedição** só liberado se estações anteriores concluídas (ou override gestor).
|
||
6. **Prioridade urgente** não pula forno fisicamente — só sobe na fila visual e alerta.
|
||
|
||
---
|
||
|
||
## 12. UX — KDS (requisitos de interface)
|
||
|
||
- Cards grandes por pedido; código `#A42` enorme
|
||
- Observação do cliente em **cor de alerta**
|
||
- Timer no canto; vira amarelo/vermelho por threshold
|
||
- Botão único: **PRONTO** (item) / **TUDO PRONTO** (estação)
|
||
- Badge do canal (PDV / iFood / …)
|
||
- Sem cards decorativos desnecessários — densidade operacional
|
||
- Funciona em tablet paisagem e TV 32"+
|
||
|
||
---
|
||
|
||
## 13. Segurança e permissões (RBAC)
|
||
|
||
| Recurso | Operador KDS | Expedição | PDV | Despacho | Gestor |
|
||
|---------|--------------|-----------|-----|----------|--------|
|
||
| Ver KDS da sua estação | ✓ | ✓ | — | — | ✓ |
|
||
| Bump tickets | ✓ | ✓ | — | — | ✓ |
|
||
| Criar pedido | — | — | ✓ | — | ✓ |
|
||
| Cancelar pedido | — | — | ✓* | — | ✓ |
|
||
| Despachar | — | ✓ | — | ✓ | ✓ |
|
||
| Cardápio / users | — | — | — | — | ✓ |
|
||
| Métricas | — | — | — | leitura | ✓ |
|
||
|
||
\*cancelar só antes de produção, salvo permissão.
|
||
|
||
---
|
||
|
||
## 14. Critérios de aceite do MVP
|
||
|
||
O MVP está **aceito** quando, em ambiente piloto:
|
||
|
||
1. Atendente cria pedido no PDV com 2 pizzas (1 meia-a-meia) + bebida + observação
|
||
2. Tickets aparecem nas estações corretas em < 1 s
|
||
3. Cada estação conclui seus itens; expedição só libera no fim
|
||
4. Etiqueta é gerada/impressa
|
||
5. Gestor reordena/prioritiza um pedido pronto
|
||
6. Dashboard mostra tempos por estação daquele pedido
|
||
7. Zero uso de papel na cozinha durante o teste supervisionado
|
||
|
||
---
|
||
|
||
## 15. Sequência oficial de implementação (S0–S9)
|
||
|
||
> **Congelado 2026-07-23 (SPEC 0.2.1).**
|
||
> Ordem: **KDS por estação antes de delivery/rotas.**
|
||
> Ciclo inspirado no rusterando: `cart/PDV → kitchen board → driver tour → ORS`.
|
||
> Não forkamos o binário Rust/AGPL; reutilizamos o **modelo operacional** no stack Nest/React.
|
||
|
||
### 15.1 Mapa de sprints
|
||
|
||
| Sprint | Bloco (rusterando) | Entrega Pizza Digital | Status |
|
||
|--------|--------------------|------------------------|--------|
|
||
| **S0** | Foundation | Repo + Docker Compose + domain types + SPEC | ✅ |
|
||
| **S1** | Auth + menu admin | Auth JWT + Store + Cardápio + mapa item→estações | ✅ (`pizza.myvexx.com`) |
|
||
| **S2** | Cart → order | **PDV** + criar pedido + state machine `confirmado→em_producao→pronto` | ✅ |
|
||
| **S3** | Kitchen board | **KDS multi-estação** realtime (bump, timers, rooms Socket.io) | ✅ |
|
||
| **S4** | Ready / expedição | Etiquetas + fila `pronto` + priorização + dashboard tempos | pendente |
|
||
| **S5** | Piloto cozinha | 1 pizzaria estável sem papel (aceite §14) | pendente |
|
||
| **S6** | Driver tour (manual) | Despacho: fila só `pronto` → agrupar bairro → motoboy → reordenar | pendente |
|
||
| **S7** | **ORS** | Gestor de Rotas: `DispatchBatch` + mapa permanente + heurística; ORS com `ORS_API_KEY` | ✅ parcial (ORS opcional) |
|
||
| **S8** | Driver + push | `/motoboy` + rota + GPS ping (+ push staff depois) | ✅ parcial (sem PIN/offline) |
|
||
| **S9 / Track C1** | Public menu / pay | **Cardápio digital** + checkout (Pix / dinheiro) → quadro `/pedidos` | **PRIORIDADE pós-S5** |
|
||
| **Track C2** | Agregadores | iFood webhook → Order normalizado | após C1 |
|
||
|
||
**Gate entre mundos (obrigatório):**
|
||
`order.ready` → fila despacho → batch → ORS *(só a partir de S6/S7)*.
|
||
|
||
### 15.2 Módulo Rotas (CityFoods → Pizza Digital)
|
||
|
||
**Referência oficial de dispatch:** [rusterando](https://github.com/holg/rusterando) (AGPL-3.0).
|
||
|
||
| Subfase | Capacidade | Sprint |
|
||
|---------|------------|--------|
|
||
| MVP rotas | Fila só pedidos `pronto` | S6 |
|
||
| MVP rotas | Agrupar por bairro (manual + sugestão) | S6 |
|
||
| MVP rotas | Atribuir motoboy | S6 |
|
||
| MVP rotas | Reordenar saída (“2 cliques” CityFoods) | S6 |
|
||
| Ampliação | OpenRouteService — ordem ótima da tour | S7 |
|
||
| Ampliação | Mapa no despacho | S7 |
|
||
| Ampliação | PWA entregador + tracking | S8 |
|
||
| Ampliação | Pagamento / comissão por entrega | S8–S9 |
|
||
|
||
Papéis rusterando → Pizza Digital: Admin≈gestor · Kitchen≈kds/estações · Driver≈entregador · Customer≈canal cardápio (S9).
|
||
|
||
### 15.3 Referências por domínio
|
||
|
||
| Domínio | Fonte |
|
||
|---------|--------|
|
||
| KDS / estações / bump | Este SPEC + kitchenOS / Tasty-Station |
|
||
| Despacho / ORS / driver tour | **rusterando** (oficial) + CityFoods Gestor de Rotas |
|
||
| UX “2 cliques” priorização | CityFoods |
|
||
|
||
### 15.4 Design UI
|
||
|
||
Status: **ainda não congelado.** S1 tem UI funcional (login + admin cardápio).
|
||
Antes de S3: wireframes PDV → KDS (touch) → Despacho. Design system em documento separado (`docs/DESIGN.md`) quando existir.
|
||
|
||
---
|
||
|
||
## 16. Riscos
|
||
|
||
| Risco | Mitigação |
|
||
|-------|-----------|
|
||
| Cozinha rejeita tela (hábito do papel) | UX bump mínima + treinamento 1 turno + impressão híbrida opcional |
|
||
| Impressora térmica incompatível | Driver ESC/POS + fallback PDF/A4 |
|
||
| Pico de pedidos derruba WS | Redis pubsub + rooms por loja; load test 60/h |
|
||
| Escopo inchando (virar iFood) | Freeze: MVP = cozinha digital, não marketplace |
|
||
| Integração iFood cedo demais | Só após piloto estável |
|
||
|
||
---
|
||
|
||
## 17. Glossário
|
||
|
||
| Termo | Significado |
|
||
|-------|-------------|
|
||
| **KDS** | Kitchen Display System — tela digital da cozinha |
|
||
| **Bump** | Marcar item/pedido como pronto na estação |
|
||
| **Estação** | Setor de produção (massa, forno, …) |
|
||
| **Ticket** | Representação do trabalho de um item/pedido numa estação |
|
||
| **SLA** | Tempo alvo até alerta de atraso |
|
||
| **Despacho** | Liberação do pedido pronto para entregador |
|
||
| **Canal** | Origem do pedido (PDV, cardápio, iFood, …) |
|
||
| **Cozinha Digital** | Operação completa sem comanda de papel + métricas |
|
||
| **BOM / Ficha técnica** | Lista de insumos por item do cardápio |
|
||
| **stockMode** | `bom` · `sku` · `none` — como o item consome estoque |
|
||
| **CMV** | Custo da mercadoria vendida (teórico via BOM) |
|
||
|
||
---
|
||
|
||
## 18. Decisões em aberto (para fechar com Roger)
|
||
|
||
1. Stack final: **NestJS** ✅ (congelado Fase 1)
|
||
2. Piloto: qual pizzaria / volume médio de pedidos/dia?
|
||
3. Impressora térmica já definida (marca/modelo)?
|
||
4. MVP inclui **mesa/comanda salão** ou só delivery + balcão?
|
||
5. Hospedagem inicial → **Proxmox BIG VM125** (`10.10.10.125`) ✅
|
||
6. Domínio → **`https://pizza.myvexx.com`** ✅
|
||
7. Sequência S0–S9 + rusterando = ref. rotas → **congelado §15** ✅
|
||
8. Design UI/UX (wireframes KDS/PDV/despacho) — em aberto
|
||
|
||
---
|
||
|
||
## 19. Referências
|
||
|
||
- CityFoods Cozinha Digital — https://abre.ai/cityfoods / https://cityfoods.com.br/
|
||
- CityFoods Instagram — https://www.instagram.com/cityfoods_app/
|
||
- kitchenOS — https://github.com/rajeshselvam02/kitchenOS
|
||
- rusterando (**ref. oficial dispatch/ORS**) — https://github.com/holg/rusterando
|
||
- URY / Mosaic — https://github.com/ury-erp/ury
|
||
- MaSoVa — https://github.com/SVamseekar/masova-platform
|
||
- Tasty-Station POS — https://github.com/hey-Zayn/Tasty-Station-POS
|
||
|
||
---
|
||
|
||
## 20. Próximo passo imediato
|
||
|
||
1. **S4** — Etiquetas + priorização + dashboard tempos (fechar cozinha)
|
||
2. **S5** — Piloto pizzaria (cozinha estável)
|
||
3. **Track C1 — entrada digital** — cardápio público → `/pedidos` (§5.5) ← **foco de produto**
|
||
4. **Track E1 / M1** — Estoque + ficha técnica ligados ao cardápio Joinville
|
||
5. Em paralelo ou depois: S6–S8 (rotas) · Track C2 (iFood)
|
||
|
||
---
|
||
|
||
*Documento vivo. Mudanças de escopo devem atualizar versão (ex.: 0.2.0 → 0.2.1) e registrar changelog em `docs/CHANGELOG-SPEC.md`.*
|