Functional Weave
Code in Rust

insurance.excess-apply@1.0.1

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),
  };
}