UNPKG

saldo

Version:

Portuguese salary calculator library

72 lines (71 loc) 4.83 kB
import { SituationUtils } from "../config/schemas"; import { TaxRetentionTable } from "../tables/tax-retention"; import { validateNumberOfHolders, validateMarriedAndNumberOfHolders, validateDependents, } from "../dependent-worker/validators"; import { Twelfths, } from "../dependent-worker/schemas"; import { LunchAllowance, } from "../dependent-worker/lunch-allowance"; import { getPartnerExtraDeduction, getTwelfthsIncome, getDisabledDependentExtraDeduction, } from "../dependent-worker/calculations"; export function simulateDependentWorker({ income, married = false, disabled = false, partnerDisabled = false, location = "continente", numberOfHolders = null, numberOfDependents = null, numberOfDependentsDisabled = null, dateStart = new Date(2025, 0, 1), // JS months are 0-indexed dateEnd = new Date(2025, 11, 31), // JS months are 0-indexed socialSecurityTaxRate = 0.11, twelfths = Twelfths.TWO_MONTHS, lunchAllowanceDailyValue = 10.2, lunchAllowanceMode = "cupon", lunchAllowanceDaysCount = 22, }) { const lunchAllowance = new LunchAllowance(lunchAllowanceDailyValue, lunchAllowanceMode, lunchAllowanceDaysCount); // Validate input validateNumberOfHolders(numberOfHolders); validateMarriedAndNumberOfHolders(married, numberOfHolders); validateDependents(numberOfDependents, numberOfDependentsDisabled); // Partner with disability results in extra deduction let extraDeduction = getPartnerExtraDeduction(married, numberOfHolders, partnerDisabled); // Holidays and Christmas income distributed over the year const twelfthsIncome = getTwelfthsIncome(income, twelfths); // Income for tax calculation const taxableIncome = income + lunchAllowance.taxableMonthlyValue; // Income for gross salary and social security const retentionIncome = taxableIncome + twelfthsIncome; // Gross salary per month const grossIncome = retentionIncome + lunchAllowance.taxFreeMonthlyValue; // The situation to determine the tax bracket const situation = SituationUtils.getSituation(married, disabled, numberOfHolders, numberOfDependents === null ? undefined : numberOfDependents // Python None is undefined here ); if (!situation) { throw new Error(`Could not determine situation for the given parameters: married=${married}, disabled=${disabled}, numberOfHolders=${numberOfHolders}, numberOfDependents=${numberOfDependents}`); } // Load the corresponding tax retention table const taxRetentionTable = TaxRetentionTable.load(dateStart, dateEnd, location, situation.code); // Find the tax bracket for the taxable income const bracket = taxRetentionTable.find_bracket(taxableIncome); if (!bracket) { throw new Error(`Could not find tax bracket for taxable income: ${taxableIncome} in table ${situation.code} for location ${location}`); } // Extra deduction for dependents with disability extraDeduction += getDisabledDependentExtraDeduction(taxRetentionTable, numberOfDependentsDisabled || 0); // Calculate the tax, social security and net salary const tax = bracket.calculate_tax(taxableIncome, twelfthsIncome, numberOfDependents || 0, extraDeduction); const socialSecurity = retentionIncome * socialSecurityTaxRate; const netSalary = grossIncome - tax - socialSecurity; const yearlyLunchAllowance = lunchAllowance.monthlyValue * 11; const yearlyGrossSalary = income * 14 + yearlyLunchAllowance; // Calculate yearly net salary correctly by simulating what the base monthly salary would be // without twelfths distribution and then multiplying by 14 months const baseMonthlyTaxableIncome = income + lunchAllowance.taxableMonthlyValue; const baseMonthlyGrossIncome = baseMonthlyTaxableIncome + lunchAllowance.taxFreeMonthlyValue; // Calculate tax for base monthly income (without twelfths distribution) const baseBracket = taxRetentionTable.find_bracket(baseMonthlyTaxableIncome); if (!baseBracket) { throw new Error(`Could not find tax bracket for base taxable income: ${baseMonthlyTaxableIncome}`); } const baseMonthlyTax = baseBracket.calculate_tax(baseMonthlyTaxableIncome, 0, // No twelfths for base calculation numberOfDependents || 0, extraDeduction); const baseMonthlySocialSecurity = baseMonthlyTaxableIncome * socialSecurityTaxRate; const baseMonthlyNet = baseMonthlyGrossIncome - baseMonthlyTax - baseMonthlySocialSecurity; const yearlyNetSalary = baseMonthlyNet * 14; return { taxableIncome: taxableIncome, grossIncome: grossIncome, tax, socialSecurity: socialSecurity, socialSecurityTax: socialSecurityTaxRate, netSalary: netSalary, yearlyNetSalary: yearlyNetSalary, yearlyGrossSalary: yearlyGrossSalary, lunchAllowance: lunchAllowance, }; }