# Missão de Operação WMS — Spec

## Contexto e problema
A missão **Alocação WMS** já existe e funciona, mas está acoplada ao conceito de "alocação". A operação de armazém precisa do mesmo esqueleto (bipar endereço e/ou produto, sessão livre, registro append-only, integração push posterior) para outros cenários: inventário de endereço, inventário de conjunto de produtos, conferência de estoque por localização e validação de ocupação. Esta feature transforma a missão num **componente WMS genérico**, configurável pela operação (`operacao_tipo`), reaproveitando toda a infraestrutura de missões logísticas e mantendo a alocação atual sem regressão. A integração com o WMS externo permanece **push-only** (Genesis é a fonte; empurra os movimentos; não lê o saldo oficial).

## Escopo
- ✅ Faz parte:
  - Tipo de missão **genérico** ("Operação WMS") configurável por `operacao_tipo`: `alocacao`, `inventario_endereco`, `inventario_produtos`, `conferencia_localizacao`, `validacao_ocupacao`.
  - Seleção da operação **e do escopo** na tela de Designação (produtos / endereços / conjunto de produtos / sessão livre), conforme a operação escolhida.
  - Execução no app adaptada à operação (bipar endereço, bipar produto, pedir quantidade, conferir, marcar ocupação), em sessão livre e retomável.
  - Persistência unificada em histórico append-only por tenant (`wms_movimentos`), carregando `operacao_tipo`, produto, endereço, quantidade, origem, status e estados de integração.
  - Validação na confirmação por operação (missão ativa, operador com permissão, endereço existente quando aplicável, regras específicas).
  - Propagação **push** dos movimentos confirmados para ERP e base WMS, com rastreio de estado por movimento.
  - Saldo **local** (soma dos movimentos confirmados) exibido como referência (`fonte=local`), com aviso de que o oficial é do WMS.
  - **Não-regressão** da Alocação WMS: ela passa a ser `operacao_tipo = alocacao` com paridade comportamental.
- ❌ Fora de escopo:
  - Leitura do saldo oficial do WMS externo (read API) e divergência contado × oficial.
  - Movimentação/abate de estoque contábil.
  - Gerenciamento de layout de armazém (criar/editar endereços por UI).
  - Alterar os campos legados de andar 1 / andar 2.
  - Renomear/migrar `tipo_missao_id` ou `referencia_tipo` de missões já existentes.

## Operações suportadas (mapa)
| `operacao_tipo` | Escopo na Designação | Execução (operador) | Quantidade | O que registra | Push (operação) |
|---|---|---|---|---|---|
| `alocacao` | produtos (ou vazio / livre) | bipa endereço + produto | opcional (livre) / nula (só endereçar) | vínculo produto × endereço | `registrar_localizacao` |
| `inventario_endereco` | 1+ endereços | bipa endereço → conta os produtos presentes | obrigatória (contagem) | contagem **absoluta** por produto naquele endereço | `sync_contagem` |
| `inventario_produtos` | conjunto de produtos | bipa produto → informa endereço + qtd | obrigatória | contagem por produto (qualquer endereço) | `sync_contagem` |
| `conferencia_localizacao` | endereço(s) | bipa endereço → confere presentes vs registrado-local | opcional | confirmação / divergência **local** | `push_conferencia` |
| `validacao_ocupacao` | endereços | bipa endereço → marca ocupado/vazio/condição | n/a | status de ocupação do endereço | `push_ocupacao` |

> Push-only: conferência e validação comparam contra o dado **local** do Genesis, não contra o saldo oficial do WMS.

## User stories

### US1 — Gestor cria missão de Operação WMS escolhendo a operação
**Como** gestor logístico/WMS **eu quero** criar uma missão escolhendo a operação (alocação, inventário de endereço, inventário de produtos, conferência, validação de ocupação) e o escopo **para** despachar a operação certa ao operador.

**Critérios de aceite:**
- AC1.1: Na criação, o gestor escolhe "Operação WMS" e seleciona uma `operacao_tipo` entre as suportadas.
- AC1.2: O escopo de seleção se adapta à operação: produtos (alocação / inventário de produtos), endereços (inventário de endereço / conferência / validação de ocupação), ou nada (sessão livre, quando a operação permite).
- AC1.3: O gestor pode atribuir um ou mais operadores OU deixar a missão disponível para captura por operador habilitado.
- AC1.4: A `operacao_tipo` escolhida é persistida em `missao_logistica.configuracoes.operacao_tipo`.
- AC1.5: Ao criar, a missão nasce em status "criada/disponível"; itens (quando há escopo) entram pendentes.
- AC1.6: Quando a operação **exige** escopo (ex.: inventário de endereço sem nenhum endereço), a criação é bloqueada com mensagem; quando a operação permite sessão livre (ex.: alocação), criar sem itens é aceito.

### US2 — Operador executa com a UI adaptada à operação
**Como** operador de armazém **eu quero** que a tela de execução se ajuste à operação **para** bipar/contar/conferir corretamente.

**Critérios de aceite:**
- AC2.1: A tela lê `operacao_tipo` da missão e renderiza o fluxo correspondente (campos de endereço/produto/quantidade conforme o mapa).
- AC2.2: A execução é livre (sem ordem obrigatória), parcial e retomável; sair e voltar não perde o progresso.
- AC2.3: Itens já processados ficam visualmente distintos dos pendentes.
- AC2.4: Para operações que exigem quantidade (`inventario_*`), a confirmação só habilita com quantidade informada; para `validacao_ocupacao` não há quantidade.

### US3 — Operação: Alocação (paridade com hoje)
**Como** operador **eu quero** bipar endereço e produto e confirmar **para** registrar onde o item está.

**Critérios de aceite:**
- AC3.1: Bipa endereço e produto em qualquer ordem; confirmação habilita com os dois informados (no modo "só endereçar", a quantidade é nula).
- AC3.2: Endereço inexistente na base de validação é rejeitado com mensagem (a alocação tolera endereço não cadastrado conforme regra atual — manter o comportamento vigente).
- AC3.3: Ao confirmar, grava movimento `operacao_tipo=alocacao` (vínculo produto × endereço) e o produto aparece no painel "produtos neste endereço".
- AC3.4: O comportamento atual (modos livre/enderecamento, remover produto do endereço, X para limpar) é preservado.

### US4 — Operação: Inventário de um endereço
**Como** operador **eu quero** bipar um endereço e contar os produtos presentes **para** registrar o inventário daquele endereço.

**Critérios de aceite:**
- AC4.1: Após bipar o endereço, a tela mostra os produtos que o Genesis tem registrados ali (referência local) e permite contar/adicionar produtos efetivamente encontrados.
- AC4.2: Para cada produto, o operador informa a **quantidade contada** (absoluta); confirmar grava movimento `operacao_tipo=inventario_endereco`.
- AC4.3: Bipar um produto não previsto naquele endereço é permitido (inventário descobre divergências) e entra como contagem nova.
- AC4.4: A missão cobre 1+ endereços; concluir um endereço permite seguir para o próximo.

### US5 — Operação: Inventário de um conjunto de produtos
**Como** operador **eu quero** contar produtos específicos onde quer que estejam **para** inventariar um conjunto definido pelo gestor.

**Critérios de aceite:**
- AC5.1: A missão traz a lista de produtos do escopo; o operador bipa o produto, informa o endereço e a quantidade contada.
- AC5.2: Confirmar grava movimento `operacao_tipo=inventario_produtos` com produto + endereço + quantidade.
- AC5.3: Um produto do escopo pode ser contado em mais de um endereço (estoque dividido).

### US6 — Operação: Conferência de estoque por localização
**Como** operador **eu quero** conferir o que está num endereço contra o registrado **para** confirmar ou apontar divergência.

**Critérios de aceite:**
- AC6.1: Após bipar o endereço, a tela mostra o que o Genesis tem registrado ali (saldo local) e o operador confirma presença/ausência (e quantidade quando informada).
- AC6.2: Confirmar grava movimento `operacao_tipo=conferencia_localizacao` com o resultado (conferido / divergente) **relativo ao dado local**.
- AC6.3: Fica explícito na UI que a referência é o dado local do Genesis, não o saldo oficial do WMS.

### US7 — Operação: Validação de ocupação de endereços
**Como** operador **eu quero** marcar cada endereço como ocupado/vazio/condição **para** validar a ocupação física do armazém.

**Critérios de aceite:**
- AC7.1: Após bipar o endereço, o operador marca o estado de ocupação (ex.: ocupado / vazio / avariado); não há quantidade.
- AC7.2: Confirmar grava movimento `operacao_tipo=validacao_ocupacao` com o estado escolhido.

### US8 — Sistema valida regras de negócio na confirmação
**Como** gestor **eu quero** que o sistema valide cada confirmação **para** garantir consistência.

**Critérios de aceite:**
- AC8.1: Confirmação bloqueada se a missão não estiver ativa (cancelada/concluída).
- AC8.2: Confirmação bloqueada se o operador não tiver permissão para executar a missão.
- AC8.3: Regras específicas por operação (quantidade obrigatória no inventário; endereço requerido na conferência/validação) são aplicadas pelo **adapter da operação**.
- AC8.4: Toda confirmação rejeitada exibe o motivo específico e não altera o estado.

### US9 — Sistema propaga os movimentos (push) para ERP e WMS
**Como** integrador (ERP/WMS externo) **eu quero** receber os movimentos confirmados **para** manter o WMS sincronizado.

**Critérios de aceite:**
- AC9.1: Todo movimento confirmado gera envio para ERP e para a base WMS, carregando `operacao_tipo` no payload.
- AC9.2: Cada movimento mantém estado de integração ERP e WMS (pendente/enviado/falha) independentes.
- AC9.3: Falha de integração fica registrada/visível e entra em retry; não some silenciosamente.
- AC9.4: O payload ERP usa o identificador compatível com o legado (`importacao_id` ↔ `codigomd5`).
- AC9.5: Movimentos cancelados (voltar atrás) nunca são empurrados (gate por status já existente).

### US10 — Missão reflete progresso e conclusão
**Como** gestor **eu quero** acompanhar o status conforme os itens são processados.

**Critérios de aceite:**
- AC10.1: Ao primeiro movimento, a missão passa para "em andamento".
- AC10.2: Parte processada / parte pendente reflete "parcialmente concluída".
- AC10.3: A conclusão é **explícita** pelo operador (sessão livre não auto-conclui por contagem de itens) — manter o comportamento atual da alocação.
- AC10.4: Missão cancelada não aceita novos movimentos.
- AC10.5: Operador pode sair e retomar sem perder progresso.

## Personas envolvidas
| Persona | Papel | Ponto de contato |
|---|---|---|
| Gestor logístico/WMS | Cria a missão, escolhe operação + escopo, designa, acompanha | Tela de criação/Designação |
| Operador de armazém | Executa a operação (bipa/conta/confere/valida) | Aplicativo (sinal `App`) |
| ERP / WMS externo | Recebe os movimentos confirmados (push) | Integração via hook (consumidor) |

## Dados / entidades-chave (alto nível)
- **Missão de Operação WMS** — instância de missão logística genérica; carrega `operacao_tipo` em `configuracoes`.
- **Item da missão** — quando há escopo (produto ou endereço a processar); pode ser dinâmico (criado na execução, como na alocação).
- **Movimento WMS** — registro append-only do evento (produto/endereço/quantidade/origem/status + integração + `operacao_tipo`).
- **Produto / Localização WMS** — usados para identificação e validação (a localização é só consultada).

## Regras de negócio
1. A operação registra movimento físico/localização; nunca movimenta nem abate estoque contábil.
2. O `operacao_tipo` define o fluxo de execução, as validações e o payload de push (via adapter).
3. A semântica de `quantidade` é por operação (delta na alocação; absoluta no inventário; n/a na validação de ocupação).
4. Só missões ativas aceitam novos movimentos.
5. O operador precisa de permissão para executar a missão.
6. Execução sem sequência obrigatória; parcial e retomável; conclusão explícita.
7. Todo movimento confirmado é empurrado para ERP e WMS, com rastreio de integração independente.
8. Movimentos cancelados não são integrados.
9. A origem da leitura (código de barras / manual) é registrada em cada movimento.
10. Integração é push-only nesta fase; nenhuma decisão depende de leitura do saldo oficial do WMS.

## Métricas de sucesso
- Nº de operações WMS distintas em uso (cobertura: além de alocação, inventário/conferência/validação efetivamente sendo criadas).
- % de missões de Operação WMS concluídas vs criadas, por `operacao_tipo`.
- % de movimentos com integração ERP e WMS confirmada (sem pendência/falha residual).
- Zero regressão da Alocação WMS (testes de baseline continuam passando).

## Dúvidas em aberto
- [ ] **Inventário absoluto vs delta no push**: o `sync_contagem` envia a contagem absoluta e o WMS substitui, ou envia delta? *Assunção: absoluta; o WMS/ERP decide como aplicar (push-only).* 
- [ ] **Estados de ocupação** (`validacao_ocupacao`): qual o conjunto canônico (ocupado / vazio / avariado / bloqueado)? Definir no techplan/adapter.
- [ ] **Conferência sem saldo oficial**: confirmar que "conferir contra o local" é suficiente para o valor de negócio nesta fase, ou se a conferência deve esperar a read API. *Assunção: vale como v1 (aponta divergência vs registrado-local).* 
- [ ] **Reaproveitar `TipoMissao::INVENTARIO` (id 11)**: absorver o inventário "fino" existente como `operacao_tipo` ou deixá-lo intocado por ora? *Assunção: deixar intocado; inventário aqui nasce sob a Operação WMS.* 
- [ ] **Seletor de operação na Designação**: dropdown único de operação dentro de "Operação WMS", ou um card por operação no wizard? Decisão de UX para o frontend.
