# Separação por Endereço WMS ("Separação v2") — PRD bruto

> Este é o ponto de entrada do pipeline `/genesis-feature`.
> Evolução da missão de **Separação** (`TipoMissao::SEPARACAO`): uma **variante nova** guiada pelo **endereço real do produto nas tabelas WMS do Genesis** (`wms_localizacoes` + `wms_movimentos`), mantendo a separação atual **intacta e como default**. Consome a base construída em `PRD/alocacao-wms/` e `PRD/operacao-wms/`.
> Decisões de produto travadas com o dono em **2026-07-02**: fonte do endereço = WMS com fallback legado; execução guia **e valida** o endereço por bipagem; **sem** baixa de saldo (só leitura); ativação por **escolha do gestor por missão** (sem gate por empresa).

## Problema / dor

A separação de hoje se localiza pelo campo legado `produtos.codigo_enderecamento` — um texto livre tipo **"1 andar" / "2 andar"** que só diz o *andar*, não a posição física. Na prática:

- A ordenação da fila agrupa por andar via heurística de string (`BaseExecucaoStrategy::identificarAndar()`: contém "2 ANDAR" ou começa com "2" → andar 2; todo o resto → andar 1). Dentro do andar, a ordem é rota/pedido/nome — **nada guia o operador até a prateleira**.
- O card exibe esse texto como "localização", mas **ninguém valida que o operador pegou o produto no lugar certo** — a bipagem confere só o código de barras do produto, que é o mesmo em qualquer posição do estoque.
- Enquanto isso, o Genesis **já sabe o endereço real** de boa parte dos produtos: as missões de Alocação/Operação WMS registram produto × endereço em `wms_movimentos`, com catálogo de endereços bipáveis em `wms_localizacoes` (código corredor-prateleira-posição). A separação simplesmente **ignora essa base**.

Queremos habilitar uma **separação "v2"**: o gestor escolhe, por missão, uma separação guiada pelo endereço real do WMS — fila ordenada pelo endereço físico, card mostrando o código real, e operador **bipando o endereço ao chegar** antes de bipar o produto. A separação atual (por andar) continua existindo sem nenhuma regressão e continua sendo o default.

## Quem usa

- **Gestor logístico**: na tela de Designação, ao criar missão de separação, escolhe o modo — **v1 (andar, como hoje)** ou **v2 (endereço WMS)**. Vê aviso quando itens da missão não têm endereço WMS registrado.
- **Separador (operador de armazém)**: executa no app (sinal `App`). Na v2, a fila vem ordenada pelo endereço real; ao chegar na posição ele **bipa o endereço** (código de `wms_localizacoes`), o sistema confirma que é o endereço do item, e então ele **bipa o produto** normalmente (mesma mecânica de códigos + fator de hoje).
- **Operação de armazém como um todo**: quanto mais alocações WMS registradas, melhor a v2 funciona — cria o incentivo de manter a base de endereços viva.

## O que precisa fazer (alto nível)

- **Escolha por missão na Designação**: nova opção no fluxo de criação da missão de separação (modo "endereço WMS"). Default permanece a separação atual. Sem gate por empresa — a opção aparece para todos.
- **Resolver o endereço real de cada item**: para cada produto da missão v2, buscar o endereço registrado nas tabelas WMS locais — a referência é a **última alocação confirmada** em `wms_movimentos` (infra já existente: `WmsMovimentoSonda::mapaLocalizacaoConfirmadaPorProduto()`, hoje usada na tela de designação do AlocacaoWms).
- **Fallback legado**: produto **sem** endereço WMS registrado cai no comportamento atual (`codigo_enderecamento` / andar), sinalizado no card como localização legada. A missão v2 é utilizável mesmo com base WMS parcial.
- **Congelar o endereço na criação da missão** (snapshot por item, junto do snapshot de códigos de barras que já existe em `dados_adicionais`): a fila não pode re-resolver endereço a cada pull — o hot path do `obterProximoItem` já é crítico (ver `PRD/separacao-fila-throughput/`).
- **Ordenação/agrupamento pela posição física**: na v2, a fila ordena pelo código do endereço real (percurso de coleta), substituindo o agrupamento por andar. Itens em fallback legado entram no fim (ou agrupados à parte — refinamento do PO).
- **Execução com validação de endereço**: no card do item, o operador bipa primeiro o **endereço**; se for o endereço esperado do item, libera a bipagem do produto; se for outro endereço, feedback de erro. A bipagem do produto em si não muda (snapshot de códigos + fator, `MissoesBipagem`).
- **Exibição**: card mostra o código real do endereço (ex.: `A03-P2-N1`) no lugar do texto "1 andar", com indicação de origem (WMS vs legado).
- **Aviso na criação**: ao montar uma missão v2, mostrar ao gestor quantos/quais itens ficaram sem endereço WMS (seguem via fallback) — sem bloquear a criação.
- **Não-regressão total da v1**: separação atual (strategies, modo_andar, telas, bipagem) permanece intacta e default; a v2 é aditiva.

## O que NÃO precisa fazer (escopo negativo)

- **Não grava movimento de saída nem baixa saldo local WMS.** A v2 é **só leitura** das tabelas WMS (decisão do dono 2026-07-02). A baixa de saldo na separação fica documentada como evolução futura (viraria uma operação de saída em `wms_movimentos`) — fora deste PRD.
- **Não reserva estoque / anti-oversell.** Reafirma a decisão de 2026-06-05 (`PRD/separacao-fila-throughput/`): separação não reserva nem decrementa estoque; estoque contábil vive no ERP.
- **Não lê saldo oficial do WMS externo.** Continua não existindo read API; a fonte é o registro local do Genesis (`fonte='local'`), com o aviso padrão quando saldo for exibido.
- **Não migra nem remove o `codigo_enderecamento` legado.** Ele continua sendo a fonte da v1 e o fallback da v2.
- **Não cria gate por empresa.** A escolha é por missão, disponível para todos (decisão do dono 2026-07-02).
- **Não mexe em carregamento, conferência, pesagem ou nas demais missões** — só a separação ganha a variante.
- **Não muda a mecânica de bipagem do produto** (snapshot `codigos_barras` + fator + `MissoesBipagem`) nem o claim multi-operador (`SKIP LOCKED`) — intocados.
- **Não gerencia layout de armazém** — `wms_localizacoes` é só consultada/validada, não editada por esta feature.

## Restrições conhecidas

- **Encaixe como variante, não tipo novo**: `ExecucaoStrategyFactory` já resolve chave composta `SEPARACAO:VARIANTE` (`PADRAO`, `ENDERECO`, `ROTA`) — a v2 entra como variante nova + marcação em `missao_logistica.configuracoes`, sem inflar `TipoMissao` nem criar sinal novo. Criação segue o par `SeparacaoStrategy` / `GestaoMissoesSeparacao` existente.
- **Fonte do endereço é a infra WMS existente**: `WmsMovimentoSonda` (agregação local; `mapaLocalizacaoConfirmadaPorProduto`, `saldoPorLocalizacaoProduto`) e `WmsLocalizacaoSonda::buscarPorCodigo()` para validar o endereço bipado (só ativos). O WMS externo é o **dono do saldo oficial** — qualquer exibição de saldo carrega o aviso `fonte='local'`.
- **Hot path intocável**: `obterProximoItem` já faz ~10 queries por pull; a resolução de endereço **não pode** adicionar I/O por pull. Resolver na criação (snapshot no item) e ordenar por dado materializado. Atenção à interação com a Frente C do `PRD/separacao-fila-throughput/` (materialização de ordem) — a variante v2 deve nascer "materializável".
- **Roteamento do scanner**: códigos de endereço e de produto **não têm formato distinguível** — no AlocacaoWms a distinção é por estado da UI (`item.js`: sem endereço ativo → bip é endereço; com endereço ativo → bip é produto). O card v2 precisa da mesma disciplina de estado (espelhar o padrão, não inventar prefixo de código).
- **Multi-operador é normal**: vários operadores na mesma missão com `SKIP LOCKED` (decisão 2026-06-05) — a validação de endereço é por item/operador e não pode travar o vínculo missão-operador.
- **Modelos V1**: `MissaoLogistica`/`MissaoLogisticaItem` são Inteligencias (V1) — ajustes pontuais ok, sem migração de modelo aqui. Consultas WMS novas usam as Sondas V2 existentes.
- **Padrões de banco**: PostgreSQL (`gx_goldie`/`dev_gx_goldie`); colunas `block_*` sem `DEFAULT` (framework preenche via `customerControl`); writes via `create()`/`update()` do model, sem raw SQL.
- **i18n**: strings novas nas telas (badge de endereço, erros de bipagem de endereço, aviso de fallback) via `show()` nas 3 línguas.

## Inspirações / referências

- **`AlocacaoWms` (fluxo endereço-primeiro)** — referência direta da UX de bipagem de endereço: roteamento por estado em `App/html/alocacaowms/item.js`, consulta via `ConsultarEnderecoLaboratorio` (aviso `fonte='local'`), validação por `WmsLocalizacaoSonda`.
- **`WmsMovimentoSonda::mapaLocalizacaoConfirmadaPorProduto()`** — já responde "qual o endereço confirmado de cada produto"; é a semente da resolução de endereço da v2.
- **`SeparacaoEnderecamentoStrategy` + `ExecucaoStrategyFactory`** — o mecanismo de variante (`SEPARACAO:*`) onde a v2 se pluga; a strategy atual é o espelho do que a v2 substitui (andar → endereço real).
- **`GestaoMissoesBase::enriquecerCodigosBarras()`** — precedente do snapshot congelado na criação (`dados_adicionais['codigos_barras']`); o snapshot de endereço segue o mesmo padrão.
- **`MissoesBipagem`** — validação autoritativa da bipagem de produto (intocada; a v2 só adiciona o passo de endereço antes).
- **`PRD/separacao-fila-throughput/`** — restrições de hot path e decisões de escopo herdadas (multi-operador, sem reserva de estoque).
- **`PRD/operacao-wms/`** — contexto e contratos das tabelas `wms_movimentos`/`wms_localizacoes`.

## Estrutura de dados mínima (por item da missão v2)

- Endereço WMS resolvido (código de `wms_localizacoes`) **ou** marcação de fallback legado — congelado na criação (ex.: em `dados_adicionais`, como o snapshot de códigos).
- Origem da localização: `wms` | `legado` (dirige badge, ordenação e exigência de bipagem de endereço).
- Marcação do modo da missão (ex.: `configuracoes` da missão) indicando a variante v2.
- Registro da validação de endereço na execução (endereço bipado, quando, por quem) — mecanismo exato (extrato / `dados_coletados`) é decisão do TL.

## Notas

- **Nomenclatura**: evitar "v2" literal no código — já existe uma classe JS `SeparaçãoV2` em `App/html/separacao/item.js` (modo livre da separação atual) e "V2" também nomeia a geração Sondas/arquitetura. Sugerido tratar como **"Separação por Endereço WMS"** (ex.: variante `SEPARACAO:WMS`); "v2" fica só como apelido de produto.
- **Produto em múltiplos endereços**: a regra inicial é usar a **última alocação confirmada** (o que `mapaLocalizacaoConfirmadaPorProduto` já devolve). Refinamentos (maior saldo, endereço mais próximo na rota de coleta, picking fracionado em 2 endereços) ficam para o PO avaliar — não travar o MVP por isso.
- **Realocação durante a missão**: o snapshot congela o endereço na criação; se o produto for realocado no meio da missão, o card pode apontar para o endereço antigo. Mitigação (re-resolver ao bipar endereço divergente? botão "atualizar endereço"?) é dúvida em aberto.
- **Endereço errado ≠ beco sem saída**: definir com o PO o escape quando o operador não encontra o produto no endereço esperado (bipar mesmo assim com ocorrência? pular item? seguir sem validar com registro no extrato?). O fluxo de ocorrência da separação existe e deve ser o caminho natural.
- **Semântica da quantidade**: nada muda — a v2 não mexe em quantidade/saldo; a validação de endereço é um *gate* de localização, não um movimento.

## Dúvidas em aberto pro PO

1. **Ordem de percurso**: ordenar pelo código do endereço alfabeticamente resolve, ou existe uma ordem de percurso física (serpentina por corredor) que o código não expressa? MVP proposto: ordenação alfabética pelo código + itens legados no fim.
2. **Interação com a variante `SEPARACAO:ROTA`**: missão v2 ainda respeita prioridade de rota do romaneio (rota primeiro, endereço depois) ou o percurso físico vence? Proposta: endereço vence dentro da missão v2; confirmar com a operação.
3. **Escape de endereço divergente** (ver Notas): ocorrência, pulo, ou confirmação forçada com auditoria?
4. **Realocação no meio da missão** (ver Notas): aceitar defasagem do snapshot no MVP?
5. **Aviso na criação**: listar itens sem endereço WMS é suficiente, ou o gestor precisa de ação em massa (ex.: "criar missão de alocação com esses itens")?
