# Missão de Operação WMS — PRD bruto

> Este é o ponto de entrada do pipeline `/genesis-feature`.
> Evolução/generalização de `PRD/alocacao-wms/` — a missão deixa de ser exclusiva de "alocação" e passa a ser um **componente reutilizável do WMS**.

## Problema / dor

Hoje existe a missão **Alocação WMS** (registrar a localização física de um produto bipando endereço + produto). Ela funciona, mas está **acoplada ao conceito "alocação"**: o tipo de missão, a tabela, o handler, as strategies e os hooks só sabem falar de "alocar produto em endereço".

A operação de armazém, porém, precisa do **mesmo esqueleto de execução** (operador bipa endereço e/ou produto, sessão livre sem ordem obrigatória, registro append-only, integração com WMS/ERP depois) para vários cenários além da alocação:

- **Alocação** de produtos em endereços (o que já existe).
- **Inventário de um endereço**: contar tudo o que está fisicamente num endereço específico.
- **Inventário de um conjunto de produtos**: contar produtos específicos onde quer que estejam.
- **Conferência de estoque por localização**: validar o que está registrado num endereço contra o que o operador vê.
- **Validação de ocupação dos endereços**: marcar endereços como ocupados/vazios/condição.

Sem generalizar, cada novo cenário viraria um sinal/tabela/handler duplicado — replicando bipagem, saldo local, integração e cron. O objetivo é **uma missão WMS genérica**, configurável pela operação desejada, reaproveitando a infraestrutura de missões logísticas já existente.

## Quem usa

- **Gestor logístico / WMS**: cria a missão escolhendo **qual operação** (alocação, inventário de endereço, inventário de produtos, conferência, validação de ocupação) e o **escopo** (produtos, endereços, ou nada — sessão livre); designa responsável(is).
- **Operador de armazém**: executa a missão no aplicativo (sinal `App`), bipando endereço e/ou produto e informando quantidade quando a operação exige.
- **ERP / WMS externo**: recebe os movimentos confirmados via integração **push** (Genesis empurra; não há leitura do saldo oficial nesta fase).

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

- Gestor cria missão do tipo **Operação WMS** e escolhe a **operação** (`operacao_tipo`) + escopo na tela de Designação.
- Operador abre a missão no app; a tela de execução se adapta à operação (bipar endereço, bipar produto, pedir quantidade, conferir, marcar ocupação).
- Toda confirmação grava um **movimento** num histórico append-only por tenant, com produto/endereço/quantidade/origem/status, carregando o `operacao_tipo`.
- Validação no momento da confirmação (missão ativa, operador com permissão, endereço existente quando aplicável, regras específicas da operação).
- Movimentos confirmados são **empurrados** para ERP e base WMS, com estado de integração (pendente/enviado/falha) por movimento — sem sumiço silencioso de falhas.
- Missão tem ciclo de vida normal (criada/disponível → em andamento → parcialmente concluída → concluída/cancelada); execução parcial e retomável, sem sequência obrigatória.
- A alocação atual continua funcionando **sem regressão** — ela passa a ser apenas `operacao_tipo = alocacao`.

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

- **Não** lê o saldo oficial do WMS externo (sem read API nesta fase). Genesis é a fonte da contagem e **empurra**; comparação contado × oficial fica fora de escopo.
- **Não** movimenta/abate estoque financeiro — registra movimento físico/localização, não transfere quantidade contábil.
- **Não** gerencia layout de armazém (não cria/edita corredores, prateleiras, posições por UI — a base de endereços é só consultada para validação).
- **Não** substitui os campos legados de andar 1 / andar 2 do produto.
- **Não** quebra a missão de Alocação WMS existente nem migra dados de missões já criadas (`tipo_missao_id` e `referencia_tipo` permanecem).

## Restrições conhecidas

- Deve reaproveitar a infraestrutura de missões (`missao_logistica`, `TipoMissao`, `MissoesBipagem`, padrão Handlers/Strategies/Factories) — não criar sinal novo isolado.
- Tipo de missão **genérico único** + discriminador `configuracoes.operacao_tipo` (decisão de produto), evitando inflar o enum `TipoMissao` com um case por operação.
- Persistência **unificada**: a tabela append-only de alocação (`wms_alocacoes`) é generalizada para `wms_movimentos` com coluna `operacao_tipo` — não criar tabela por operação.
- Integração **push** via Hook Strategy já em uso (`HookSincronizadorBase`); cron de retry já existe (`crons/wms_alocacao_integracao.php`).
- Banco PostgreSQL (`gx_goldie`/`dev_gx_goldie`); colunas `block_*` sem `DEFAULT` (preenchidas pelo framework via `customerControl`); writes via `update()`/`create()` do `ModelInteligencia` (sem raw SQL).
- O aplicativo é o sinal `App` em `Missoes/Logistica/sinais/App`.

## Inspirações / referências

- `PRD/alocacao-wms/` — base direta (esta feature generaliza aquela). Reusar contexto, ACs e fluxo de bipagem de dois códigos.
- `TipoMissao::INVENTARIO` + `InventarioExecucaoStrategy` — missão sem sequência obrigatória; o inventário "fino" existente pode ser absorvido como `operacao_tipo` no futuro.
- `DesignacaoStrategyFactory` / `MissaoListaStrategyFactory` — padrão registry (enum → classe) a espelhar para o **registry de operações**.
- `WmsAlocacaoSonda` — base do `WmsMovimentoSonda` (histórico append-only, saldo local, gate de integração por status).

## Estrutura de dados mínima por movimento

- ID da missão, ID do item (quando houver), **operacao_tipo**
- ID do produto (quando aplicável), código da localização WMS (quando aplicável)
- Quantidade (semântica varia por operação — ver notas)
- Operador responsável, data/hora
- Status do movimento (confirmado / cancelado)
- Origem da leitura (código de barras / manual)
- Estados de integração ERP e WMS (pendente / enviado / falha) + timestamps + erro

## Notas

- A **semântica de `quantidade` muda por operação**: na alocação é o quanto foi alocado (acumula); no inventário é a **contagem absoluta** num momento; na conferência é o conferido; na validação de ocupação pode ser nula. O Genesis grava o evento; como é push-only, o WMS/ERP decide como aplicar — isso é documentado no contrato.
- Conferência e validação, na fase push-only, comparam contra o **dado local do Genesis** (o que o Genesis registrou), não contra o saldo oficial do WMS. A comparação contado × oficial depende de read API e fica para uma fase posterior.
- Decisão de tipo **não-quebrante**: manter o case/`id`/valor `ALOCACAO_WMS` existentes e generalizar via `operacao_tipo` (default `alocacao`) + relabel — detalhado no techplan.
- O cron de integração já filtra por `status='confirmada'`; movimentos cancelados (voltar atrás) nunca são empurrados.
