Mirror all SPECs and construction docs from pizza-digital, add hub/sidebar links and bidirectional sync scripts.
15 KiB
SPEC — Paridade Despacho / Delivery (referência CityFoods)
| Campo | Valor |
|---|---|
| Produto | Pizza Digital |
| Documento | Paridade operacional com CityFoods (expedição + delivery + admin) |
| Versão | 0.2.1 |
| Data | 2026-10-22 |
| Status impl. | P0–P2 + Gestor · UI mapa-first em SPEC-CITYFOODS-VIDEO-PARITY.md |
| Vídeo referência | Siciliana yVtc · Forno Jxau · Despacho KDcD |
| Case | ~R$ 1M/mês · ~70% iFood · hub multi-marca · entrega < 30 min |
| Alinha com | SPEC §15 S4→S8 · SPEC-FASE1 §6 · rusterando (rotas) |
| Fora deste doc | Cardápio público PWA (C1), fidelidade, caixa completo |
0. Objetivo
Elevar o Pizza Digital do estado atual (lista de prontos + SAIR) ao nível das telas CityFoods do vídeo:
- Despacho como cockpit (não só fila)
- Conferência / estufa como etapa formal
- Frota (casa / rua) + atribuição
- Rotas e, depois, marketplace / app entregador
- Admin de zonas, ranking e relatórios operacionais
Princípio de sequência (já na SPEC mãe):
KDS estável → despacho rico → frota → ORS → app motoboy → iFood.
1. Estado atual (baseline Pizza Digital)
| Tela / capacidade | Rota / artefato | Status |
|---|---|---|
| Central de pedidos | /pedidos |
✅ |
| KDS multi-estação | /kds/:station |
✅ |
| Expedição (KDS) | /kds/expedicao · → ESTUFA |
✅ |
| Etiqueta | /etiqueta/:id |
✅ |
| Despacho cockpit | /despacho |
✅ P0–P2 |
| Frota / motoboy | /despacho frota + /api/drivers |
✅ |
| Conferência / estufa | Order.estufaAt + Expedição |
✅ |
| Gestor de Rotas | DispatchBatch · mapa permanente |
✅ (heurística; ORS com ORS_API_KEY) |
| App entregador | /motoboy |
✅ parcial (sem PIN próprio / offline) |
| Zonas / taxas | /admin/zonas |
✅ CRUD (PDV ainda não aplica taxa auto) |
| Ranking / funil / relatório | /ops |
✅ |
| iFood no fluxo | — | ❌ P3 / C2 |
2. Narrativa das telas necessárias (SPEC por tela)
Cada subsecção = uma tela (ou superfície). Inclui: papel, o que o CityFoods mostra no vídeo, requisitos RF, dados, eventos, aceite.
Tela A — Cockpit de Despacho (/despacho)
Papel: operador de despacho / gestor de turno.
No vídeo: “coração operacional” — lista de pedidos + frota + tempos + cores + reordenação.
A.1 O que deve mostrar
| Coluna / bloco | Descrição |
|---|---|
| Frota (topo ou lateral) | Motoboys em casa / rua, nº de entregas ativas |
| Pedido | Código, canal (PDV / App / iFood / WhatsApp), fulfillment |
| Tempos | Hora do pedido · tempo na loja · tempo desde pronto / estufa |
| Estágio visual | Cor: novo · em produção · forno · estufa · em rota |
| Destino | Bairro + endereço curto |
| Itens resumidos | Qtd × sabor (sem ficha completa) |
| Ações | Selecionar · atribuir motoboy · SAIR / batch |
A.2 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-DSP-01 | Listar pedidos em pronto e na_estufa em tempo real (Socket.io) |
S4 / S6 |
| RF-DSP-02 | Exibir canal, código, tempos (pedido / loja / estufa) | S4 |
| RF-DSP-03 | Faixa de cor por estágio de produção espelhado do KDS | S4 |
| RF-DSP-04 | Seleção múltipla de pedidos para batch de saída | S6 |
| RF-DSP-05 | Atribuir entregador antes ou no SAIR | S6 |
| RF-DSP-06 | SAIR → status em_rota + dispatchedAt + entregadorId |
S6 |
| RF-DSP-07 | Reordenar fila de prioridade; persistir; refletir no KDS | S6 |
A.3 Aceite
- Despachante vê, sem sair da tela, quem está livre, o que está na estufa e há quanto tempo.
- Um clique em SAIR com motoboy atribuído remove o pedido da fila de prontos.
Tela B — Conferência / Estufa
Papel: conferente (login próprio).
No vídeo: identifica sabor → imprime etiqueta → pedido vai para estufa no despacho.
B.1 Fluxo
KDS BUMP (forno) → fila Conferência
→ conferente confirma sabores / qtds
→ imprime etiqueta (código + sabores)
→ status na_estufa
→ aparece no Cockpit Despacho como “estufa”
B.2 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-CNF-01 | Tela /conferencia ou modo dedicado em /kds/expedicao |
S4 |
| RF-CNF-02 | Login com papel/área conferente ou despacho |
S4 |
| RF-CNF-03 | Checklist de itens/sabores antes de confirmar | S4 |
| RF-CNF-04 | Confirmar → print etiqueta + na_estufa + evento order.ready enriquecido |
S4 |
| RF-CNF-05 | Pedidos na estufa ordenáveis por tempo parado (alerta visual) | S4 |
B.3 Modelo de estado (ampliação)
em_producao → pronto_cozinha → na_estufa → em_rota → entregue
Compatibilidade: enquanto
na_estufanão existir no enum, usarpronto+ flagholdingStation=estufaou migrar enum (preferível).
B.4 Aceite
- Sem etiqueta confirmada, pedido não entra na fila “estufa” do despacho.
- Tempo parado na estufa é visível e alarmante após N minutos (config loja).
Tela C — Frota / Motoboys
Papel: despacho + gestor.
No vídeo: quem está na casa, quem está na rua, quantas entregas cada um carrega.
C.1 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-FRT-01 | Cadastro de entregador (nome, telefone, ativo, loja) | S6 |
| RF-FRT-02 | Status operacional: casa | rua | offline |
S6 |
| RF-FRT-03 | Contagem de entregas abertas (em_rota) por entregador |
S6 |
| RF-FRT-04 | Painel no cockpit: lista viva atualizada por socket | S6 |
| RF-FRT-05 | Histórico simples: entregas do turno / canceladas | S6–S8 |
C.2 Aceite
- Ao despachar, só aparecem entregadores
casa(ou regra configurável). - Quando o app marcar entrega, status volta a
casase fila zerada.
Tela D — Gestor de Rotas (mapa + batch)
Papel: despacho.
No vídeo / City Pro: montar rota → despachar → acompanhar no mapa (não só preview).
D.0 Fluxo canónico (implementado)
Estufa (seleção ± bairro)
→ Preview mapa (opcional)
→ Montar rota → DispatchBatch status=montada
→ Atribuir motoboy
→ Despachar rota ✈ → status=na_rua · orders em_rota · 1ª parada a_caminho
→ Motoboy: a caminho / entregue por parada (+ ping GPS)
→ Última entrega → status=fechada · motoboy casa
Mapa full-bleed (bloco dominante) em /despacho — ver RF-VID-01…08 em SPEC-CITYFOODS-VIDEO-PARITY: todas as rotas/motoboys, filtro por entregador, pin some ao entregar, CTA Ir para entrega.
D.1 Requisitos
| ID | Requisito | Sprint | Status |
|---|---|---|---|
| RF-ROT-01 | Agrupar seleção por bairro (manual + sugestão) | S6 | ✅ |
| RF-ROT-02 | Sugerir ordem de visita (heurística bairro/CEP) | S6 | ✅ |
| RF-ROT-03 | Otimizar tour com ORS (OpenRouteService) | S7 | ✅ opcional (ORS_API_KEY; senão heurística) |
| RF-ROT-04 | Mapa no despacho com pontos + polyline da rota | S7 | ✅ |
| RF-ROT-04b | Entidade rota persistida montada | na_rua | fechada |
S7 | ✅ DispatchBatch + DispatchStop |
| RF-ROT-04c | Despachar rota (não só SAIR solto) | S7 | ✅ POST /api/routes/:id/dispatch |
| RF-ROT-04d | Tracking motoboy no mapa (ping) | S7–S8 | ✅ POST /api/routes/:id/ping + driver.ping |
| RF-ROT-05 | Comparar custo: frota própria vs marketplace | S7–C2 | ❌ (após iFood) |
D.2 Aceite
- Batch de 2+ pedidos gera rota com código (
Rdd-nn), ordem e motoboy. - Mapa continua visível enquanto a rota está
montada/na_rua. - ORS só quando
ORS_API_KEY+ pedidos com geo/bairro resolvível (Joinville centroides MVP).
API: /api/routes/* · UI: /despacho · Ref.: rusterando (modelo, sem fork AGPL).
Tela E — App / PWA Entregador
Papel: motoboy.
No vídeo / Play Store CityFoods: mapa, detalhes, iniciar e concluir entrega.
E.1 Requisitos
| ID | Requisito | Sprint | Status |
|---|---|---|---|
| RF-MOT-01 | Login entregador (role/área) | S8 | ⚠️ parcial (escolhe motoboy na UI; sem PIN) |
| RF-MOT-02 | Lista / rota ativa do motoboy | S8 | ✅ /motoboy + GET /api/routes/driver/:id |
| RF-MOT-03 | Mapa da rota + deep-link GPS | S8 | ✅ |
| RF-MOT-04 | Marcar “a caminho” / “entregue” | S8 | ✅ por parada da rota |
| RF-MOT-05 | Ping de posição (opt-in geolocation) | S8 | ✅ |
| RF-MOT-06 | Offline tolerante (fila local → sync) | S8+ | ❌ |
E.2 Aceite
entreguevia parada da rota; cockpit atualiza progresso e frota.- Última parada fecha a rota e devolve motoboy a
casase sem fila.
Tela F — Ranking de produção (ao vivo)
Papel: gestor / pizzaiolo.
No vídeo: Cláudio 95, Gil 86… pizzas/noite + tempo médio; remanejo por atraso.
F.1 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-RNK-01 | Bumps KDS creditados ao usuário logado na estação | S4–S5 |
| RF-RNK-02 | Ranking do turno: pizzas, tempo médio, atrasos | S5 |
| RF-RNK-03 | Tela TV/gestor só leitura (opcional) | S5 |
| RF-RNK-04 | Alerta “operador em zona de atraso” (N pedidos late) | S5 |
F.2 Aceite
- Dois logins na mesma estação não misturam contagem.
- Ranking zera/rotaciona por turno (config).
Tela G — Funil operacional (métricas)
Papel: gestor.
No vídeo: tempos produção / forno / estufa / rua; identificar gargalo.
G.1 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-FUN-01 | Timestamps: created, claimed, bumped por estação, estufa, dispatched, delivered | S4 |
| RF-FUN-02 | Dashboard: p50/p90 por etapa do funil (dia/turno) | S5 |
| RF-FUN-03 | Contagem de cancelamentos do período | S5 |
| RF-FUN-04 | Distinto do Pooling comercial (faturado/ticket) — ou abas no mesmo painel gestor | S5 |
G.2 Aceite
- Gestor responde em < 10 s: “o gargalo agora é forno ou estufa ou rua?”.
Tela H — Admin: zonas de entrega
Papel: gestor (Setup).
No CityFoods (site): áreas/bairros + taxas diferenciadas.
H.1 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-ZON-01 | CRUD zona: nome, polígono ou lista de bairros, taxa cents, tempo estimado | S6–S9 |
| RF-ZON-02 | PDV/cardápio aplica taxa pelo bairro/CEP | S9 / C1 |
| RF-ZON-03 | Despacho usa zona para agrupamento | S6 |
| RF-ZON-04 | Fora de zona → bloqueio ou taxa especial | S9 |
Tela I — Admin: relatórios de entrega / equipe
Papel: gestor.
No CityFoods City Pro / Cozinha Digital: relatórios entregas + entregadores + operação cozinha.
I.1 Requisitos
| ID | Requisito | Sprint |
|---|---|---|
| RF-REL-01 | Relatório entregas: qtd, tempo médio, cancelados, por canal | S8 |
| RF-REL-02 | Relatório entregadores: entregas, tempo rua, ranking | S8 |
| RF-REL-03 | Relatório cozinha: pizza/hora, atrasos por estação | S5 |
| RF-REL-04 | Export CSV (padrão estoque) | S5–S8 |
Tela J — Integração marketplace (iFood) no despacho
Papel: sistema + despacho.
No vídeo: cotação API iFood vs própria; ~70% do fluxo.
J.1 Requisitos
| ID | Requisito | Track |
|---|---|---|
| RF-IFO-01 | Webhook iFood → Order normalizado (idempotente) | C2 |
| RF-IFO-02 | Pedido aparece na Central + KDS + Despacho com canal iFood | C2 |
| RF-IFO-03 | Cotação frete marketplace vs frota (UI no batch) | C2 + S7 |
| RF-IFO-04 | Sync status pronto/despachado quando política da loja exigir | C2 |
Só após Central + despacho interno estáveis (gate SPEC mãe).
3. Mapa tela → sprint (resumo executivo)
| Tela | Nome | Sprint / track | Prioridade | Status |
|---|---|---|---|---|
| A | Cockpit Despacho | S4 → S6 | P0 | ✅ |
| B | Conferência / Estufa | S4 | P0 | ✅ |
| C | Frota | S6 | P1 | ✅ |
| D | Gestor de Rotas / mapa | S6 → S7 | P1–P2 | ✅ (ORS opcional) |
| E | App entregador | S8 | P2 | ✅ parcial |
| F | Ranking produção | S5 | P1 | ✅ /ops |
| G | Funil operacional | S4–S5 | P1 | ✅ /ops |
| H | Zonas / taxas | S6–S9 | P2 | ✅ CRUD · ❌ taxa no PDV |
| I | Relatórios | S5–S8 | P2 | ✅ básico |
| J | iFood no fluxo | C2 | P3 | ❌ |
4. Dados (implementados)
Driver { id, storeId, name, phone, active, opsStatus, lastLat?, lastLng?, lastPingAt? }
Order + estufaAt, driverId, lat?, lng?, batchId?, dispatchedAt, deliveredAt, priority
DeliveryZone { storeId, name, neighborhoods[], feeCents, etaMinutes, active }
DispatchBatch {
id, storeId, code, driverId?, status: montada|na_rua|fechada,
method, distanceKm?, depotLat, depotLng, polyline?,
plannedAt, dispatchedAt?, closedAt?
}
DispatchStop {
id, batchId, orderId, seq, lat, lng,
status: pendente|a_caminho|entregue, arrivedAt?, deliveredAt?
}
Ranking usa PrepTask (claimedBy + completedAt). Funil usa timestamps do Order.
5. Eventos Socket
| Evento | Quando | Quem escuta |
|---|---|---|
order.ready |
Estufa / pronto | Despacho |
order.priority |
Reordenação | KDS + Despacho |
order.dispatched |
Despacho de rota / SAIR | Despacho + Frota |
order.delivered |
Entregue | Despacho + Relatórios |
driver.updated |
casa/rua | Cockpit frota |
driver.ping |
GPS motoboy | Mapa despacho |
route.updated |
Montar / parada / fecho | Despacho + Motoboy |
route.dispatched |
Despachar rota | Despacho + Motoboy |
route.closed |
Rota fechada | Despacho + Frota |
6. Critério de “mesmo nível” (definição de pronto)
Paridade operacional com o vídeo atingida quando:
- ✅ Cockpit A em
/despacho - ✅ Conferência B + estufa alimentam o cockpit
- ✅ Frota C no SAIR / despacho de rota
- ✅ Gestor de Rotas D: montar → despachar → mapa permanente
- ✅ Funil G + ranking F em
/ops - ✅ App motoboy E consome a mesma rota
Ainda pode faltar para paridade comercial City Pro: ORS com chave em produção, PIN/offline motoboy, taxa zona no PDV, iFood cotação, multi-loja — P2+/P3.
7. Fora de escopo (neste SPEC)
- Programa de fidelidade CityFoods
- Pop-ups / destaques cardápio
- Caixa completo / fechamento de turno financeiro
- Multi-tenant white-label
- Fork ou cópia de UI proprietária CityFoods (só modelo operacional)
8. Próximo passo
- P3 / C2 — iFood no fluxo (webhook → Central/KDS/Despacho)
- Polimento:
ORS_API_KEYem prod · taxa zona no PDV · PIN motoboy · CSV relatórios
Documento derivado do cruzamento vídeo yVtcgJt0L_Q × pizza.itecnologys.com × SPEC §15. v0.2.0 — Gestor de Rotas documentado pós-implementação.