Recebimento + 3-way match
Conferência tripla PC × NF × físico, com aprovação automática quando OK e bloqueio quando divergente
O 3-way match
Antes de qualquer pagamento, três coisas têm que bater:
- Pedido (PC) — o que foi pedido
- Nota Fiscal (NF) — o que foi faturado
- Físico — o que efetivamente chegou
Diferença além da tolerância configurada = pagamento bloqueado até resolver.
Onde acessar
Cada PO em Suprimentos → tab Pedidos ganha um botão "Receber" (visível enquanto status ≠ cancelado e ≠ entregue).
URL direta: /projects/[projectId]/suprimentos/recebimento/[poId]
Fluxo em 3 steps
Step 1 — Validar nota
Upload XML auto-preenche
Suba o XML da NF-e (modelo 55) ou NFS-e — o parser extrai automaticamente:
- Chave de acesso (44 dígitos)
- Número, série, data de emissão
- CNPJ emissor
- Valor total
- Itens
E valida o emissor: se o CNPJ da NF não bate com o supplier do PO, alerta visualmente (potencial fraude/erro de envio).
Campos manuais
Se não tiver XML, pode preencher manualmente. Anexar PDF/imagem da NF é opcional.
Tolerâncias customizáveis
- Quantidade: ± 2% padrão (config). Para commodities (areia, brita) faz sentido tolerância; para itens contados, deve ser 0.
- Preço: ± 0% padrão. Qualquer divergência abre incidente.
Step 2 — Conferir itens
Lista do PC item por item:
- Qtd recebida (pré-preenchido com restante do PC)
- Preço conferido (pré-preenchido com PC)
- Qtd na NF + Preço na NF (separados — pode haver divergência entre NF e físico)
- Tipo de divergência: nenhuma / quantidade / preço / especificação / integridade / atraso / múltiplas
- Severidade: baixa / média / alta / crítica
- Fotos por item (upload para Supabase Storage
procurement-receipts/) - Botão Aceitar / Recusar item
Step 3 — Resumo + 3-way preview
Antes de confirmar, sistema mostra:
- Tabela linha-por-linha: PC × NF × Recebido × match_status
- Banner verde: "Todos os itens conferem. Pagamento liberado automaticamente."
- Banner amarelo: "Divergência detectada: X% sobre o pedido. Pagamento bloqueado até aprovação."
Confirmação
Submete o recebimento. Sistema decide automaticamente:
| Cenário | Resultado |
|---|---|
| Todos itens aceitos sem divergência | tipo='total' (ou parcial), status auto_aprovado |
| Algum item recusado, qtd menor mas aceita | tipo='parcial' ou 'com_divergencia', abre approval |
| Todos recusados | tipo='recusa' |
| Divergência > 5% | Approval recebimento_divergente com urgência alta (diretor) |
Triggers automáticos
Atualiza PO
Trigger SQL recalcula quantidade_recebida em cada PO item. Status do PO transita conforme:
- Todos itens com
quantidade_recebida >= quantidade→entregue - Pelo menos 1 item iniciado →
entregue_parcial - (Comparação item-por-item, não por soma — evita bug de super-entrega de 1 item disparar entrega total)
Realiza orçamento
Quando match_status = 'ok' é gravado, trigger incrementa:
arvore_orcamentaria_itens.quantidade_realizadaarvore_orcamentaria_itens.valor_realizado
Isso reflete em todos os relatórios "Previsto × Comprometido × Realizado" automaticamente.
Entrada automática no estoque
Se o PO tem almoxarifado_destino_id, e recebimento foi auto_aprovado (sem divergência), sistema chama gerar_entrada_compra_recebimento():
- Para cada item recebido com
aceito=trueque tem insumo via árvore, criaestoque_movimentos.entrada_compra - Custo médio ponderado é recalculado por trigger
- Idempotente — se chamada 2x não duplica
Se houve divergência, a entrada NÃO acontece imediatamente. Quando o approval recebimento_divergente for aprovado pelo diretor, callback dispara a entrada automática no estoque.
Atualiza score do fornecedor
Trigger recalcula score de prazo e qualidade.
Geração de CAP
Após recebimento aprovado (auto ou via approval), botão "Gerar CAP" no histórico cria a conta a pagar:
- Valor pelo total da NF (campo
nf_valor_total) - Vencimento conforme condição de pagamento do PO (default 30 dias)
- Suporta parcelamento (3x 30/60/90, etc.)
- Verifica CNDs do fornecedor — retorna alertas se vencidas
Edge cases tratados
- Recebimento parcial: pode receber 50 de 100 hoje, 30 amanhã, 20 depois — cada um gera linha auditável
- Múltiplos recebimentos no mesmo PO: trigger soma corretamente, status do PO progride consistente
- Recebimento sem NF: pode marcar tipo
'recusa'ou registrar com observação para regularização posterior - Item rejeitado por defeito: marca aceito=false, devolve fisicamente, gera incidente
Permissões
| Permissão | Escopo | Default |
|---|---|---|
compras_recebimento:read | project | Todos exceto comercial |
compras_recebimento:write | project | engenheiro+ |
Usuário comum (engenheiro) pode receber. Aprovação de divergência exige gerente/diretor por alçada.