# 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`](SPEC-CITYFOODS-VIDEO-PARITY.md) | | **Vídeo referência** | [Siciliana yVtc](https://www.youtube.com/watch?v=yVtcgJt0L_Q) · [Forno Jxau](https://www.youtube.com/watch?v=JxauDKXTJr0) · [Despacho KDcD](https://www.youtube.com/watch?v=KDcDTGEw11A) | | **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: 1. **Despacho** como cockpit (não só fila) 2. **Conferência / estufa** como etapa formal 3. **Frota** (casa / rua) + atribuição 4. **Rotas** e, depois, marketplace / app entregador 5. **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_estufa` não existir no enum, usar `pronto` + flag `holdingStation=estufa` **ou** 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 `casa` se 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 - `entregue` via parada da rota; cockpit atualiza progresso e frota. - Última parada fecha a rota e devolve motoboy a `casa` se 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: 1. ✅ Cockpit A em `/despacho` 2. ✅ Conferência B + estufa alimentam o cockpit 3. ✅ Frota C no SAIR / despacho de rota 4. ✅ Gestor de Rotas D: montar → despachar → mapa permanente 5. ✅ Funil G + ranking F em `/ops` 6. ✅ 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 1. **P3 / C2 — iFood** no fluxo (webhook → Central/KDS/Despacho) 2. Polimento: `ORS_API_KEY` em 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.*