Operação — NF, OP e venda
Fluxo do dia a dia com lote: entrada, ordem de produção, apontamento, FEFO, ATP e faturamento. Inclui o caso pão homologado.
Pré-requisito: produto com lotControl, BOM ativo, flags conforme a etapa. Headers Authorization, x-company-id, x-filial-id em toda chamada.
1. NF de entrada
A NF grava lote e validade no item (nLote / lotCode, dVal / expirationDate). Ao confirmar, o sistema cria ou incrementa FALOT01 e lança FAPOB com lot_id.
Com industrial.lot-enforcement ON e lotControl:
- item sem lote → 400
expirationControlsem validade → 400
Com industrial.quality.inbound-quarantine ON, o lote nasce QUARANTINE (fora do ATP). Senão, nasce ACTIVE.
Tipo de movimento de entrada precisa afetar estoque. Política de capitalização (NONE vs imobilizado) é outro assunto — o lote físico segue o movimento de estoque.
Exemplo (caso pão)
| Campo | Valor homologado |
|---|---|
| Produto | HML-IND-FARINHA |
| Quantidade | 1000 kg |
| Lote | FAR-260828-A |
| Validade | 2026-12-15 |
| Depósito | 001 |
Depois do confirm:
O ATP deve acompanhar o FEFO nos lotes ACTIVE (API 1.0.169). Se o razão ainda mostrar físico 0 e o lote tiver quantidade, o ATP usa o lote.
2. Ordem de produção
Corpo mínimo: produto PA, bomId (ou o vigente), quantidade planejada, UM, datas, sourceLocation / targetLocation.
Conferir no retorno: bomId preenchido e itens FAPO02 congelados.
Liberar
POST /api/production-order/release/{id} — reserva estoque. Com enforcement, a reserva carrega lot_id (FEFO). Sem saldo ACTIVE suficiente → 400.
Duas OPs no último quilo: uma consegue; a outra recusa (lock do razão).
Apontar
POST /api/production-order/report/{id}
Com industrial.production-lot-consumption ON:
producedQuantityentra no PA com lote novo e genealogia (MP → PA).- Perda:
movementKind: "LOSS"+reason(≥ 5 caracteres) +lossQuantity. SemADJUSTMENT. - Sobra / amostra:
RETURN/SAMPLE.
Com a flag OFF, o body legado { "producedQuantity": 4930 } ainda divide o BOM proporcionalmente.
Encerrar
POST /api/production-order/complete/{id}
Com industrial.mass-balance.enforce ON, o complete usa yieldTolerancePercent do BOM. Exemplo HML: previsto 5000 UN / 1000 kg, produzido 4930 / consumo 986 kg → desvio 1,4% < 5% → OK.
3. Venda / saída
Saída com lotControl e enforcement: o writer chama FEFO ou abate o lote informado. Lote QUARANTINE / BLOCKED / RECALLED / vencido → 400.
Alguns tenants (granularidade de item v2) exigem alocação no pedido:
No fulfill, use fulfillmentAllocationId de GET /sales-order/fulfillment/{id}. Isso é regra de venda, não da flag industrial — mas a baixa de estoque ainda passa pelo lote.
Kardex do PA: origem PRODUCTION na entrada da OP; EXIT_DOCUMENT na NF de saída; DONATION na doação.
4. Caso pão (referência HML)
Números reais de homologação (Sanclerlandia, 2026-08-29). Não copiar os documentos para produção.
| Passo | Documento | Resultado |
|---|---|---|
| NF entrada | 8102511432 | 1000 kg FAR-260828-A |
| OP | OP-000002 | 4930 UN, consumo 986 kg |
| 2ª OP 100 UN | — | release recusou (farinha insuficiente) |
| Doação | DON-000001 | 250 UN |
| Recall | REC-000001 | farinha RECALLED (genealogia inclui o PA) |
| Venda | pedido 372347 / NFS-4552 | 4500 UN |
| Saldos | — | farinha 14 kg RECALLED; pão 180 UN ACTIVE |
ATP validado depois do fix 1.0.169: pão 180, farinha 0. FEFO do pão aloca HMLINDPAO-260829-01. FEFO da farinha recusa.
Se o recall rodar antes da venda, o PA congela. Para faturar é preciso POST /product-lot/:id/release com motivo — o playbook assume venda primeiro.
5. Central
/apps/stock/central e GET /api/industrial/dashboard/{filialId} — OPs, produção e perdas do dia, lotes, QA, recalls OPEN, doações POSTED. Sem flag. Sem card inventado de OP em QA.
