Last active
January 22, 2024 16:04
-
-
Save lucaspar/2c20754b37920217678cebb64170cb7a to your computer and use it in GitHub Desktop.
Cálculo de IR em JavaScript com teste unitário.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Fonte: https://gist.github.com/lucaspar/2c20754b37920217678cebb64170cb7a */ | |
/** | |
* Calcula o imposto de renda sobre o valor de rendimentos tributáveis, | |
* conforme tabela progressiva do ano tributário de 2023, seguindo a | |
* incidência mensal do imposto sobre a renda de pessoas físicas (IRPF). | |
* | |
* @params {Number} rendimentos Renda a ser tributada, em R$. | |
* @returns {Number} imposto a pagar sobre `rendimentos`, em R$. | |
**/ | |
function IRRF(rendimentos, aplicarDescontoSimplificado = false) { | |
// Aliquotas à partir de maio de 2023: | |
// Fonte: https://www.gov.br/receitafederal/pt-br/assuntos/meu-imposto-de-renda/tabelas/2023 | |
const aliquotas = [0, 0.075, 0.15, 0.225, 0.275]; // aliquotas de IR | |
const bases = [2112.00, 2826.65, 3751.05, 4664.68, Infinity]; // bases de calculo | |
// novo desconto simplificado mensal, introduzido em 2023, corresponde à | |
// 25% da faixa inicial da base de calculo e é opcional. | |
const descontoSimplificado = 0.25 * bases[0]; | |
// aplicar desconto simplificado, se solicitado | |
if (aplicarDescontoSimplificado) { | |
rendimentos -= descontoSimplificado; | |
} | |
// Aliquotas anteriores para referência: de 2016 à abril de 2023 | |
// Fonte: https://www.gov.br/receitafederal/pt-br/assuntos/meu-imposto-de-renda/tabelas/2016 | |
// const aliquotas_antigas = [0, 0.075, 0.15, 0.225, 0.275]; // aliquotas de IR | |
// const bases_antigas = [1903.98, 2826.65, 3751.05, 4664.68, Infinity]; // bases de calculo | |
// calcula tamanho das faixas de tributacao conforme rendimentos | |
const faixas = bases.map(function(b, i, arr) { | |
// a faixa atual eh no maximo o valor da base de calculo | |
var faixa = Math.min(rendimentos, b) | |
// se a base nao for a primeira, precisamos subtrair o valor da base anterior | |
if (i !== 0) { | |
faixa -= arr[i - 1]; | |
} | |
// bases maiores que rendimentos podem resultar em faixas negativas, por isso zeramos essas | |
faixa = Math.max(faixa, 0); | |
return faixa; | |
}); | |
// calcula imposto conforme a aliquota de cada faixa e soma ao valor total | |
const imposto = faixas.reduce( function(sum, f, i) { | |
// calcula imposto da faixa multiplicando sua aliquota | |
const impFaixa = (f * aliquotas[i]); | |
return sum += impFaixa; | |
}, 0 ); | |
// imposto a pagar sobre rendimentos | |
return imposto; | |
} | |
/** | |
* Testa função IRRF com valores previamente simulados. | |
* Referências: | |
* - Alíquotas: https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/tributos/irpf-imposto-de-renda-pessoa-fisica#tabelas-de-incid-ncia-mensal | |
* - Simulador: https://www27.receita.fazenda.gov.br/simulador-irpf/ | |
* | |
* @returns {Boolean} Verdadeiro se teste foi bem sucedido. | |
**/ | |
function testIRRF() { | |
const depoisDe2023 = true | |
// se verdadeiro, usa tabela de 2023 em diante e desconto simplificado, | |
// senao usa valores de 2016 à abril de 2023 | |
let groundTruths | |
// valores de teste | |
const inputs = [1500.00, 2500.00, 3500.00, 4500.00, 5500.00, 2826.67, 2826.68, 2826.69]; | |
if (depoisDe2023) { | |
// valores-verdade obtidos por simulacao | |
groundTruths = [ 0.00, 0.00, 75.40, 241.97, 482.34, 14.00, 14.00, 14.00]; | |
} else { | |
// valores de 2016 à abril de 2023 | |
groundTruths = [ 0.00, 44.7, 170.20, 376.37, 643.14, 69.20, 69.20, 69.21]; | |
} | |
// calcula IR | |
const resultsNew = inputs.map(function(v) { | |
const res = IRRF(v, depoisDe2023); | |
return Math.round(100 * res) / 100; | |
}); | |
const isApproved = resultsNew.reduce(function(passedPrevious, r, i) { | |
// avalia resultado | |
const passedCurrent = (r === groundTruths[i]); | |
if (!passedCurrent) { | |
// debug test case | |
console.error("FAILED - test case", i + 1, "expected", groundTruths[i], "but got", r); | |
} | |
// sticky false: previous and current tests must have been successful | |
return passedPrevious && passedCurrent; | |
}, true); | |
if (isApproved) { | |
console.log("IR test result: SUCCESS"); | |
} | |
return isApproved; | |
} | |
testIRRF(); |
2023-12-20
- Atualizado com alíquotas a partir de maio de 2023 e novo desconto simplificado.
2022-08-04
- Atualizadas referências com links quebrados.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Implementação em JavaScript do cálculo do Imposto de Renda sobre rendimentos mensais conforme tabela progressiva de 2023 da Receita Federal + teste de implementação conforme simulações de cálculo.
Referências:
Contribuições são bem-vindas. 🙂