# Cota mínima de bipagem (% obrigatório de itens 100% bipados) — PRD bruto

> Este é o ponto de entrada do pipeline `/genesis-feature`.

## Problema / dor

Hoje a execução de missões (separação e carregamento) aceita tanto **bipagem** (scanner)
quanto **manual** (botões +/−). Como o manual está sempre disponível, o operador acaba
digitando tudo e nunca cria o hábito de usar o leitor de código de barras. Queremos
**obrigar que uma fração mínima dos itens da missão seja concluída de fato por scanner**,
para acostumar o usuário ao código de barras.

Exemplo do pedido original: missão com 30 SKUs, exigir que 10% deles (3 itens) sejam
bipados obrigatoriamente.

## Quem usa

- **Operador de separação / carregamento**: executa a missão no app; é quem sofre o
  bloqueio do manual e é empurrado a bipar.
- **Gestor / administrador da empresa (tenant)**: liga/desliga a regra e define o
  percentual obrigatório, por empresa.

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

### Regra (mecânica)

- **N** = nº de SKUs da missão **com código bipável** no snapshot de códigos.
- **Meta** = `ceil(pct/100 × N)` itens que precisam ser concluídos **100% por scanner**
  (todas as unidades via leitura; zero entrada manual).
- **Cota de manuais** = `N − Meta` → quantos itens bipáveis podem receber manual.
  - Cada item bipável **ainda limpo** que recebe a 1ª entrada manual gasta 1 da cota.
  - Cota zerada ⇒ botões +/− **desabilitados** nos itens bipáveis ainda limpos (força o
    scanner naquele item).
  - Itens **sem código** (fora do denominador) e itens **já manchados** continuam
    aceitando manual normalmente.
- Definição de "item 100% por scanner" (autoritativa, server-side):
  `quantidade_bipada_scan == quantidade` **E** `quantidade_bipada_manual == 0`.

Exemplo: 30 itens, 25 com código, pct = 10% → Meta = `ceil(2,5)` = **3 itens 100% bipados**;
cota de manuais = **22**. Ao tentar a 23ª "manchada", o manual bloqueia e exige scanner.

### Configuração (tenant + snapshot)

- Configuração **por empresa** (`companyControl`), com:
  - `ativo` — master on/off (o "fácil habilitar/desabilitar").
  - `pct` — percentual obrigatório (ex.: 10).
  - `ativo_separacao` e `ativo_carregamento` — habilita por fluxo independentemente.
- Default: **desligado** (compatibilidade retroativa + rollout gradual).
- Na **criação da missão**, congela em `missao_logistica.configuracoes.scan_cota`:
  `{ pct, denominador_n, meta_itens, cota_manuais }` — mesmo padrão do snapshot de
  códigos de barras. Mudar a política não afeta missão já gerada (precisa regerar).

### Enforcement (defesa em 2 camadas)

- **Front (tempo real):** os controladores de execução leem a cota do snapshot, mantêm um
  estado mission-wide de itens manchados e **bloqueiam +/−** quando a cota zera.
  **Avisa antes de gastar a última unidade da cota** (modal: "isso vai te obrigar a bipar
  o resto").
- **Servidor (backstop):** ao finalizar a missão, recomputa os itens qualificados (via os
  counters scan/manual) e **recusa finalizar** se `qualificados < meta_itens`. Registra a
  violação. Cobre o caso de o operador burlar o JS (refresh / devtools).

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

- **Não** cobre o fluxo de **retorno** (não valida código hoje — fora de escopo).
- **Não** entra **pesagem/KG**: itens são concluídos por peso, não por scan unitário →
  ficam **fora do denominador**.
- **Não** conta por **unidades**: o % é sempre sobre **SKUs (linhas de item) com código
  bipável**, nunca sobre soma de quantidades.
- **Não** permite **recuperar** um item já manchado (toque manual mancha permanentemente,
  coerente com "100% por scanner").
- **Não** precisa de tela de admin sofisticada — basta a config por empresa.

## Restrições conhecidas

- Reaproveitar a infra de missões existente (`missao_logistica`, `configuracoes` JSONB,
  `MissoesBipagem`, `MissoesStatus`).
- Config por empresa segue o padrão `companyControl: true` + `block_empresa_id`
  (canônico: `Constelacoes/Metas/Crud/Inteligencias/Meta.php`). Sonda V2 (não V1).
- Sem SQL cru; updates em lote via `update()` do model.
- i18n nas **3 línguas** (`pt-br`, `en`, `es`). As mensagens de bipagem atuais estão com
  PT hardcoded (débito conhecido) — as **strings novas** desta feature devem nascer
  internacionalizadas.
- App é o sinal `App` em `Missoes/Logistica/sinais/App`.

## Inspirações / referências (com o que já existe no código)

- Snapshot de códigos na criação: `GestaoMissoesBase::enriquecerCodigosBarras` /
  `processarEnvio` — mesmo ponto para congelar `scan_cota`.
- Persistência scan vs manual já existe: `missao_logistica_extrato` (ações
  `AcaoExtrato::BIPAGEM_SCAN` / `BIPAGEM_MANUAL`) e counters por item
  `missao_logistica_itens.quantidade_bipada_scan` / `quantidade_bipada_manual`
  (referenciados em `MissoesBipagem` — **TL conferir se a migration desses counters já
  está aplicada ou se é débito a criar**).
- Backstop de finalização: `MissoesStatus::finalizarMissao` (já bloqueia missão com itens
  pendentes — adicionar a checagem de cota no mesmo gate).
- Tipos de missão: `TipoMissao` (SEPARACAO=2, CARREGAMENTO=3; PESAGEM=12 é outro tipo →
  naturalmente excluído).
- Controladores de execução (front):
  - Separação: `Missoes/Logistica/sinais/App/html/shared/components/execucao/execucao_card.js`
    (+ `execucao_card.php`, `luz/separacao/item_card.php`).
  - Carregamento: `Missoes/Logistica/sinais/App/html/carregamento/item.js`
    (tem +/− manual via `#btn-contagem-manual`; envia `metodo_entrada`).
- Config por empresa (snapshot de retira/entrega como precedente de chave em
  `configuracoes`): `is_retira`.
- PRD anterior do mesmo domínio: `PRD/bipagem-codigo-barras-fator/`.

## Defaults / decisões já tomadas (brainstorming)

- Denominador = **SKUs com código bipável** (não todos os itens; não unidades).
- "Bipado" = item **100% concluído por scanner** (zero manual).
- Enforcement = **bloquear manual ao estourar a cota** (tempo real), **+ backstop** no
  servidor na finalização.
- Config = **por empresa, snapshot na missão** na criação.
- Disponível em **separação + carregamento**, cada um com toggle próprio.
- UX da cota = **avisar antes de gastar a última unidade** da cota.
- Arredondamento `ceil`; `meta` nunca > `N`; `pct=0`/`N=0`/`ativo=false` ⇒ desligado.

## Pontos em aberto para o Tech Lead

- Onde mora exatamente a Sonda de config por empresa (nova Sonda dedicada vs. estender
  algo existente em `MissaoLogistica`).
- Confirmar estado da migration de `quantidade_bipada_scan` / `quantidade_bipada_manual`
  (aplicada? criar?). Sem esses counters, o backstop precisa derivar do extrato.
- Como o front recebe a cota: via `MissaoPresenter` (junto do snapshot de códigos) →
  `data-*` nos componentes de execução.
- Estado mission-wide de "itens manchados" no front: derivar dos counters por item já
  enviados ao render vs. manter store local; reconciliação após refresh.
- Texto/UX exatos do modal de aviso da última cota e da mensagem de bloqueio.
