impl/typescript.ts
2,101 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 { type Money, assertSameCurrency, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { type ExcessSettlement } from "./insurance_excess_apply_types.ts";
/**
* The claim payout after the excess, capped at the policy limit.
*
* The excess is the compulsory and voluntary excess together, and a loss
* smaller than it pays nothing. Where the limit sits relative to the excess is
* a policy wording question, so the caller says which: by default the limit
* caps what is paid after the excess; with excessWithinLimit the excess is
* taken off the loss after the limit, so it erodes the limit.
*/
export function applyExcess(
loss: Money,
compulsoryExcess: Money,
voluntaryExcess: Money,
policyLimit: Money | null,
excessWithinLimit: boolean
): ExcessSettlement {
const hasLimit = policyLimit !== null && policyLimit !== undefined;
assertSameCurrency(loss, compulsoryExcess);
assertSameCurrency(loss, voluntaryExcess);
if (hasLimit) assertSameCurrency(loss, policyLimit);
if (loss.minor < 0) throw new RangeError(`loss must not be negative, received ${loss.minor}`);
if (compulsoryExcess.minor < 0 || voluntaryExcess.minor < 0) {
throw new RangeError("excess must not be negative");
}
if (hasLimit && policyLimit.minor < 0) {
throw new RangeError(`policyLimit must not be negative, received ${policyLimit.minor}`);
}
const excess = compulsoryExcess.minor + voluntaryExcess.minor;
let payout: number;
let limitApplied = false;
if (excessWithinLimit) {
let covered = loss.minor;
if (hasLimit && policyLimit.minor < covered) {
covered = policyLimit.minor;
limitApplied = true;
}
payout = Math.max(covered - excess, 0);
} else {
payout = Math.max(loss.minor - excess, 0);
if (hasLimit && policyLimit.minor < payout) {
payout = policyLimit.minor;
limitApplied = true;
}
}
const c = loss.currency;
return {
totalExcess: money(excess, c),
excessApplied: money(Math.min(excess, loss.minor), c),
payout: money(payout, c),
limitApplied,
uninsured: money(loss.minor - payout, c),
};
}