Existe um design tentador onde close_quote retorna 409 Conflict se alguma linha não tem estoque. Limpo. Seguro. Errado.
O apelo é óbvio: nunca prometa o que não pode entregar. Cada linha de cotação fechada é respaldada por inventário físico. O sistema é conservador, o almoxarifado fica feliz, e nada fica negativo. Mas esse design tem uma premissa escondida — que o inventário é estático e que o time comercial não sabe coisas que o sistema não sabe. As duas premissas são falsas.
Por que está errado Venda acontece antes do armazém pegar o ritmo. Um comercial fecha cotação sexta à noite; o recebimento de entrada é terça. A cotação é legítima, o cliente está pagando, a equipe sabe que o produto está vindo. Bloquear o fechamento força uma dança de reagendamento que cria mais problemas do que resolve.
A consequência real da imposição estrita de estoque no fechamento é que os times comerciais constroem workarounds. Criam produtos 'dummy' para absorver a reserva. Fecham a cotação em ambiente de teste e mandam o PDF por email. Escrevem o pedido no papel e lançam quando o estoque chega. Cada workaround é pior que o problema — cria inventário sombra, compromissos não rastreados, e um sistema paralelo que o sistema real não consegue ver.
A resposta do Quotery
POST /api/quotes/{id}/close/ nunca dá 409 em disponibilidade. Sempre fecha, reserva o que tem, e devolve um array shortages com cada produto em falta. O frontend renderiza um banner claro; o comercial age com informação, não com erro.
O array shortages é a chave. Não é só um booleano 'estoque insuficiente' — é uma lista estruturada de exatamente quais produtos estão em falta e em quanto. O frontend renderiza um banner âmbar: '3 produtos têm estoque disponível insuficiente. Déficit total: 47 unidades em 2 fornecedores.' O comercial pode clicar para ver cada produto, sua quantidade disponível atual, a quantidade reservada, e a lacuna. Decide então: prosseguir e emitir ordem de compra, dividir a cotação entre disponível agora e backorder, ou ligar para o cliente e ajustar.
Onde a gente SIM impõe
Entrega é diferente. Uma nota de entrega que deixaria on_hand negativo É rejeitada no post. Você pode reservar o que não existe; você não pode expedir o que não existe. É aí que a restrição pertence — um passo depois, uma transição à frente.
Essa é a distinção crítica. Reserva é promessa; entrega é cumprimento. Promessas podem ser feitas contra inventário futuro. Cumprimento só pode acontecer contra inventário físico. Colocando a restrição forte na entrega em vez de na cotação, a gente dá flexibilidade ao time comercial sem deixar o almoxarifado expedir produto que não tem. As duas operações têm invariantes diferentes porque servem a propósitos diferentes. O sistema impõe cada uma no ponto certo.
