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
  • expirationControl sem 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)

CampoValor homologado
ProdutoHML-IND-FARINHA
Quantidade1000 kg
LoteFAR-260828-A
Validade2026-12-15
Depósito001

Depois do confirm:

GET /api/product-lot/{filialId}/by-code/FAR-260828-A
GET /api/product-lot/{filialId}/fefo/HML-IND-FARINHA?quantity=986&locationCode=001
GET /api/inventory/availability/HML-IND-FARINHA/atp?filialId={filialId}&locationCode=001

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

POST /api/production-order/{filialId}

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:

{
  "producedQuantity": 4930,
  "consumptions": [
    {
      "componentCode": "HML-IND-FARINHA",
      "consumedQuantity": 986,
      "lotId": "<id do lote FAR-260828-A>",
      "locationCode": "001",
      "movementKind": "CONSUMPTION"
    }
  ]
}
  • producedQuantity entra no PA com lote novo e genealogia (MP → PA).
  • Perda: movementKind: "LOSS" + reason (≥ 5 caracteres) + lossQuantity. Sem ADJUSTMENT.
  • 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:

"allocations": [{ "fulfillmentMode": "PICKUP_NOW", "quantity": 4500 }]

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.

PassoDocumentoResultado
NF entrada81025114321000 kg FAR-260828-A
OPOP-0000024930 UN, consumo 986 kg
2ª OP 100 UN—release recusou (farinha insuficiente)
DoaçãoDON-000001250 UN
RecallREC-000001farinha RECALLED (genealogia inclui o PA)
Vendapedido 372347 / NFS-45524500 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.