aboutsummaryrefslogtreecommitdiff
path: root/src/utils/tax-calculator.ts
blob: 64b1c0868a4b78bb0c5c7fccf7cbc2ecbfd53b5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
const INSS_TABLE = [
    { upTo: 1_518.0, rate: 0.075 },
    { upTo: 2_793.88, rate: 0.09 },
    { upTo: 4_190.83, rate: 0.12 },
    { upTo: 8_157.41, rate: 0.14 },
] as const;

const INSS_TETO = 908.86;

export function calcularINSS(salarioBruto: number): number {
    if (salarioBruto <= 0) return 0;
    if (salarioBruto > INSS_TABLE[INSS_TABLE.length - 1].upTo) return INSS_TETO;

    let inss = 0;
    let limiteAnterior = 0;

    for (const faixa of INSS_TABLE) {
        const baseNaFaixa = Math.min(salarioBruto, faixa.upTo) - limiteAnterior;
        if (baseNaFaixa <= 0) break;
        inss += baseNaFaixa * faixa.rate;
        limiteAnterior = faixa.upTo;
    }

    return parseFloat(inss.toFixed(2));
}

interface FaixaIRRF {
    upTo: number | null;
    rate: number;
    deduction: number;
}

const IRRF_TABLE: FaixaIRRF[] = [
    { upTo: 2_259.2, rate: 0, deduction: 0 },
    { upTo: 2_826.65, rate: 0.075, deduction: 169.44 },
    { upTo: 3_751.05, rate: 0.15, deduction: 381.44 },
    { upTo: 4_664.68, rate: 0.225, deduction: 662.77 },
    { upTo: null, rate: 0.275, deduction: 896.0 },
];

export function calcularIRRF(salarioBruto: number, inss: number): number {
    const base = salarioBruto - inss;
    if (base <= 0) return 0;

    const faixa = IRRF_TABLE.find((f) => f.upTo === null || base <= f.upTo)!;
    return parseFloat(Math.max(0, base * faixa.rate - faixa.deduction).toFixed(2));
}

export interface ResultadoCalculo {
    salarioBruto: number;
    descontoINSS: number;
    descontoIRRF: number;
    totalDescontos: number;
    salarioLiquidoCalculado: number;
}

export function calcularSalarioLiquido(salarioBruto: number): ResultadoCalculo {
    const descontoINSS = calcularINSS(salarioBruto);
    const descontoIRRF = calcularIRRF(salarioBruto, descontoINSS);
    const totalDescontos = parseFloat((descontoINSS + descontoIRRF).toFixed(2));
    const salarioLiquidoCalculado = parseFloat(
        (salarioBruto - totalDescontos).toFixed(2),
    );
    return { salarioBruto, descontoINSS, descontoIRRF, totalDescontos, salarioLiquidoCalculado };
}

export function formatCurrency(value: number): string {
    return value.toLocaleString('pt-BR', {
        style: 'currency',
        currency: 'BRL',
        minimumFractionDigits: 2,
    });
}

export function formatCurrencyCompact(value: number): string {
    if (Math.abs(value) >= 1_000) {
        return value.toLocaleString('pt-BR', {
            style: 'currency',
            currency: 'BRL',
            minimumFractionDigits: 0,
            maximumFractionDigits: 0,
        });
    }
    return formatCurrency(value);
}