impl/typescript.ts
2,473 bytes · the TypeScript implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { addDays } from "./dates_add_days.ts"; ← from dates.add-days ^1.0.0 · built alongside by fune
import { addMonths } from "./dates_add_months.ts"; ← from dates.add-months ^1.0.0 · built alongside by fune
import { age } from "./dates_age.ts"; ← from dates.age ^1.0.0 · built alongside by fune
import { lengthOfService } from "./hr_length_of_service.ts"; ← from hr.length-of-service ^1.0.0 · built alongside by fune
import { roundDiv } from "./math_round_div.ts"; ← from math.round-div ^1.0.0 · built alongside by fune
import { type Money, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { WEEK_PAY_CAPS, WEEK_PAY_CAPS_HISTORY } from "./payroll_redundancy_pay_data.ts"; ← this capability’s own data, compiled from data/week-pay-caps.json into the same file by fune build
import { type RedundancyPay } from "./payroll_redundancy_pay_types.ts";
function weekPayCap(relevantDate: string): number {
for (const row of WEEK_PAY_CAPS) {
if (relevantDate >= row.validFrom && (row.validTo === null || relevantDate <= row.validTo)) return row.capMinor;
}
if (WEEK_PAY_CAPS_HISTORY !== "full") {
let earliest: string | null = null;
for (const row of WEEK_PAY_CAPS) if (earliest === null || row.validFrom < earliest) earliest = row.validFrom;
if (earliest !== null && relevantDate < earliest) {
throw new RangeError(
`no statutory week's pay cap for ${relevantDate}: this build was installed with history=${WEEK_PAY_CAPS_HISTORY}, ` +
`so it only carries caps from ${earliest}. Reinstall with history=full for older dismissals.`,
);
}
}
throw new RangeError(`no statutory week's pay cap for ${relevantDate}`);
}
/**
* ERA 1996 s.162 redundancy pay. Years are reckoned backwards from the
* relevant date and each is priced by the age on its first day, so the rate
* steps up only for years spent wholly at 22 or 41 and over.
*/
export function statutoryRedundancyPay(birthDate: string, startDate: string, relevantDate: string, weeklyPay: Money): RedundancyPay {
if (weeklyPay.minor < 0) throw new RangeError(`weeklyPay must not be negative, received ${weeklyPay.minor}`);
const cap = weekPayCap(relevantDate);
const weeklyPayUsed = money(Math.min(weeklyPay.minor, cap), weeklyPay.currency);
const serviceYears = lengthOfService(startDate, relevantDate).years;
const eligible = serviceYears >= 2;
const yearsCounted = eligible ? Math.min(serviceYears, 20) : 0;
let halfWeeks = 0;
for (let k = 1; k <= yearsCounted; k++) {
const firstDay = addDays(addMonths(relevantDate, -12 * k), 1);
const ageThen = age(birthDate, firstDay);
halfWeeks += ageThen >= 41 ? 3 : ageThen >= 22 ? 2 : 1;
}
const amount = money(roundDiv(halfWeeks * weeklyPayUsed.minor, 2, "half-up"), weeklyPay.currency);
return { eligible, serviceYears, yearsCounted, halfWeeks, weeklyPayUsed, amount };
}