UNPKG

saldo

Version:

Portuguese salary calculator library

155 lines (134 loc) 5.02 kB
import { SituationUtils } from "@/config/schemas"; import { TaxRetentionTable } from "@/tables/tax-retention"; import { validateNumberOfHolders, validateMarriedAndNumberOfHolders, validateDependents, } from "@/dependent-worker/validators"; import { Twelfths, DependentWorkerResult, SimulateDependentWorkerOptions, } 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, }: SimulateDependentWorkerOptions): DependentWorkerResult { 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, }; }