import test from "node:test"; import assert from "node:assert/strict"; import { calcularIndicadoresSecundario, calcularSimulacao, listarPerfisFluxoScpDefault, montarFluxoClienteScp, simularModoConversaoScpConsorcio, simularSecundarioComPerfilScp, } from "../src/index.js"; const baseInput = { credito_desejado: 300000, parametros: { id_plano: "PADRAO", nome_plano: "Plano Padrao Imovel", prazo_meses: 180, taxa_administracao_total: 0.15, fundo_reserva_mensal: 0.0005, seguro_prestamista: 0.035, }, tem_lance: false, }; test("calcula parcela integral com valores esperados", () => { const result = calcularSimulacao(baseInput); assert.equal(result.prazo, 180); assert.equal(result.credito, 300000); assert.ok(result.parcela_integral.total > 0); assert.equal(Number(result.parcela_integral.fundo_comum.toFixed(2)), 1666.67); }); test("calcula cenario com lance e reduz prazo", () => { const result = calcularSimulacao({ ...baseInput, tem_lance: true, lance_percentual: 0.3, }); assert.ok(result.valor_lance); assert.equal(result.valor_lance, 90000); assert.ok(result.prazo_apos_lance); assert.ok(result.prazo_apos_lance < result.prazo); }); test("falha quando prazo_meses for invalido", () => { assert.throws(() => { calcularSimulacao({ ...baseInput, parametros: { ...baseInput.parametros, prazo_meses: 0, }, }); }, /prazo_meses/); }); test("calcula payback do secundario com offset apos ultima contemplacao", () => { const fluxos = []; for (let i = 0; i < 10; i += 1) { fluxos.push(-100); } for (let i = 0; i < 50; i += 1) { fluxos.push(20); } const result = calcularIndicadoresSecundario({ fluxos_mensais: fluxos, meses_pos_ultima_contemplacao: 3, }); assert.equal(result.caixa_maximo_negativo, -1000); assert.equal(result.payback_meses, 63); assert.equal(result.regras_aplicadas.fee_sobre_volume_reduzido_70, true); }); test("deduz portabilidade e fee com parcela reduzida em 70% do volume", () => { const result = calcularIndicadoresSecundario({ fluxos_mensais: [-1000, 500, 700], transacoes_portabilidade: [ { valor: 100000, contemplada: true }, { valor: 100000, contemplada: false }, ], volume_contratado: 300000, fee_percentual: 0.02, percentual_cartas_parcela_reduzida: 1, }); assert.equal(result.custo_portabilidade, 1500); assert.equal(result.custo_fee_parcela_reduzida, 4200); assert.equal(result.custo_total_deducoes, 5700); assert.equal(result.fluxo_ajustado[0], -6700); }); test("valida entradas invalidas no secundario", () => { assert.throws(() => { calcularIndicadoresSecundario({ fluxos_mensais: [-100, 100], percentual_cartas_parcela_reduzida: 1.2, }); }, /percentual_cartas_parcela_reduzida/); }); test("calcula tir mensal e anual no secundario", () => { const result = calcularIndicadoresSecundario({ fluxos_mensais: [-1000, 1100], }); assert.ok(result.tir_mensal !== null); assert.ok(result.tir_anual !== null); assert.ok(Math.abs(result.tir_mensal - 0.1) < 1e-6); }); test("lista perfis SCP default com clientes entregues", () => { const catalogo = listarPerfisFluxoScpDefault(); assert.ok(catalogo.clients.length >= 6); assert.ok(catalogo.patterns.length >= 2); assert.ok(catalogo.clients.find((c) => c.client_id === "extrato_investidor_6")); }); test("monta fluxo SCP parametrizado por escala e deslocamento", () => { const fluxo = montarFluxoClienteScp({ client_id: "extrato_investidor_6", escala_fluxo: 0.5, deslocamento_meses: 2, novo_client_id: "cliente_novo", novo_client_name: "Cliente Novo", }); assert.equal(fluxo.client_id, "cliente_novo"); assert.equal(fluxo.client_name, "Cliente Novo"); assert.equal(fluxo.source_client_id, "extrato_investidor_6"); assert.ok(fluxo.pontos.length > 10); assert.equal(fluxo.pontos[0].periodo, "2021-04-01"); }); test("simula secundario com perfil SCP default", () => { const result = simularSecundarioComPerfilScp({ client_id: "extrato_investidor_6", fee_percentual: 0.02, volume_contratado: 100000, percentual_cartas_parcela_reduzida: 0.5, }); assert.equal(result.fluxo_cliente.client_id, "extrato_investidor_6"); assert.ok(result.fluxo_ajustado.length > 10); assert.ok(typeof result.caixa_maximo_negativo === "number"); }); test("simula modo conversao fechado SCP -> imovel + secundario", () => { const result = simularModoConversaoScpConsorcio({ client_id: "extrato_investidor_6", valor_imovel_base: 600000, desconto_imovel_percentual: 0.15, percentual_entrada_imovel: 0.25, agio_consorcio_percentual: 0.1, taxa_custos_transacao_percentual: 0.02, fee_percentual: 0.02, volume_contratado: 120000, percentual_cartas_parcela_reduzida: 0.5, }); assert.ok(result.modo_conversao); assert.equal(result.modo_conversao.valor_imovel_com_desconto, 510000); assert.equal(result.modo_conversao.valor_entrada_imovel, 127500); assert.ok(typeof result.modo_conversao.lucro_projetado_conversao === "number"); });