Contrato de flipping¶
Congelado em 2026-04-10 para a implementação em fases. Quebra controlada de payload antigo é permitida. Registro já gravado continua legível. A leitura do formato anterior está em Migração de legado.
Rotas¶
GET /flipping/flipping-projectGET /flipping/flipping-project/{id}POST /flipping/flipping-projectPUT /flipping/flipping-project/{id}DELETE /flipping/flipping-project/{id}POST /flipping/opportunities/parse
Variação fora de flipping-project não é contrato principal. Deal não viaja mais dentro do projeto: a API é /flipping/deals/*.
Feasibility¶
Cada oportunidade carrega opportunity.feasibility.inputs e opportunity.feasibility.results.
Entradas: advertisedPrice, usableArea, referencePricePerM2, purchasePrice, itbiRate, deedAndRegistryRate, renovationRate, renovationCost, condoMonthly, iptuMonthly, utilitiesMonthly, holdingMonths, reserveFundRate, brokerFeeRate, incomeTaxRate.
Resultados: announcedPricePerM2, salePrice, discountVsReference, itbiValue, deedAndRegistryValue, renovationCost, monthlyExpenses, reserveFundValue, investmentTotal, brokerFeeValue, grossProfit, incomeTaxValue, netProfit, roi.
POST e PUT recalculam os resultados. O cliente pode enviar results; o valor persistido é o do servidor. GET devolve entradas normalizadas e resultados coerentes com este modelo.
Cálculo¶
announcedPricePerM2 = advertisedPrice / usableArea
salePrice = referencePricePerM2 * usableArea
discountVsReference = 1 - (purchasePrice / salePrice)
itbiValue = purchasePrice * itbiRate
deedAndRegistryValue = purchasePrice * deedAndRegistryRate
monthlyExpenses = (condoMonthly + iptuMonthly + utilitiesMonthly) * holdingMonths
reserveFundValue = purchasePrice * reserveFundRate
investmentTotal = purchasePrice + itbiValue + deedAndRegistryValue + renovationCost + monthlyExpenses + reserveFundValue
brokerFeeValue = salePrice * brokerFeeRate
grossProfit = salePrice - investmentTotal - brokerFeeValue
incomeTaxValue = max(grossProfit, 0) * incomeTaxRate
netProfit = grossProfit - incomeTaxValue
roi = netProfit / investmentTotal
renovationCost explícito prevalece. Sem ele, o custo é purchasePrice * renovationRate.
Validação¶
usableArea e purchasePrice são maiores que zero. holdingMonths é pelo menos 1. Taxa fica entre 0 e 1. Lucro bruto menor ou igual a zero zera o imposto.
{
"code": "validation_error",
"message": "Invalid feasibility inputs",
"details": {
"field": "reason"
}
}
Status e categoria¶
O tráfego usa a chave do enum, não o rótulo.
Status: CAPTURED, SCHEDULED_VIEW, VISITED, ANALYZED, PROPOSAL_SENT, IN_NEGOTIATION, NEGOTIATED, DISCARDED.
Categoria: OPPORTUNITY e DEAL.
Dinheiro com duas casas. Taxa interna com quatro. roi guarda a precisão no backend e a interface formata. A mesma entrada produz a mesma saída.