Functional Weave
Code in Rust

logistics.freight-rate@1.0.1

impl/typescript.ts

4,212 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 { roundDiv } from "./math_round_div.ts";  ← from math.round-div ^1.0.0 · built alongside by fune
import { addMoney } from "./money_add.ts";  ← from money.add ^1.0.0 · built alongside by fune
import { type Money, assertSameCurrency, money } from "./money_amount.ts";  ← from money.amount ^1.0.0 · built alongside by fune
import { applyRate } from "./money_apply_rate.ts";  ← from money.apply-rate ^1.0.0 · built alongside by fune
import { compareMoney } from "./money_compare.ts";  ← from money.compare ^1.0.0 · built alongside by fune
import { type FreightRate, type FuelSurcharge, type FreightQuote } from "./logistics_freight_rate_types.ts";

const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;

function inForce(validFrom: string, validTo: string | null, onDate: string): boolean {
  return onDate >= validFrom && (validTo === null || onDate <= validTo);
}

function roundUpTo(grams: number, step: number): number {
  return roundDiv(grams, step, "up") * step;
}

/** The break's charge at a weight: base plus the per-kilogram element, at least the minimum. */
function charge(rate: FreightRate, ratedGrams: number): Money {
  const variable = roundDiv(ratedGrams * rate.perKgMinor, 1000, "half-up");
  const freight = money(rate.base.minor + variable, rate.base.currency);
  if (rate.minimum !== null && compareMoney(freight, rate.minimum) < 0) return rate.minimum;
  return freight;
}

/**
 * Freight for a consignment on a caller-supplied tariff: the zone's break
 * covering the weight on the ship date, or a heavier break when that is
 * cheaper, plus the fuel surcharge in force that day.
 */
export function freightRate(
  rates: readonly FreightRate[],
  fuelSurcharges: readonly FuelSurcharge[],
  zone: string,
  chargeableGrams: number,
  shipDate: string,
): FreightQuote {
  if (!Number.isInteger(chargeableGrams) || chargeableGrams < 1) {
    throw new RangeError(`chargeableGrams must be 1 or more, received ${chargeableGrams}`);
  }
  if (!ISO_DATE.test(shipDate)) throw new RangeError(`shipDate must be an ISO date (YYYY-MM-DD), received "${shipDate}"`);

  const candidates = rates.filter((r) => r.zone === zone && inForce(r.validFrom, r.validTo, shipDate));
  for (const rate of candidates) {
    if (!Number.isInteger(rate.stepGrams) || rate.stepGrams < 1) {
      throw new RangeError(`stepGrams must be 1 or more, received ${rate.stepGrams}`);
    }
    if (!Number.isInteger(rate.perKgMinor) || rate.perKgMinor < 0) {
      throw new RangeError(`perKgMinor must not be negative, received ${rate.perKgMinor}`);
    }
    assertSameCurrency(candidates[0].base, rate.base);
  }

  const covering = candidates.filter(
    (r) => chargeableGrams >= r.fromGrams && (r.toGrams === null || chargeableGrams <= r.toGrams),
  );
  if (covering.length === 0) {
    throw new RangeError(`no freight rate for zone "${zone}" on ${shipDate} covers ${chargeableGrams} g`);
  }
  if (covering.length > 1) {
    throw new RangeError(`two freight rates for zone "${zone}" on ${shipDate} cover ${chargeableGrams} g`);
  }

  let best = covering[0];
  let bestGrams = roundUpTo(chargeableGrams, best.stepGrams);
  let bestFreight = charge(best, bestGrams);
  // Rates per kilogram fall as weight rises, so a heavier break charged at
  // its first weight can undercut the break the consignment falls in.
  for (const rate of candidates) {
    if (rate.fromGrams <= chargeableGrams) continue;
    const grams = roundUpTo(rate.fromGrams, rate.stepGrams);
    const freight = charge(rate, grams);
    const order = compareMoney(freight, bestFreight);
    if (order < 0 || (order === 0 && grams < bestGrams)) {
      best = rate;
      bestGrams = grams;
      bestFreight = freight;
    }
  }

  let basisPoints = 0;
  if (fuelSurcharges.length > 0) {
    let found: FuelSurcharge | null = null;
    for (const row of fuelSurcharges) {
      if (!inForce(row.validFrom, row.validTo, shipDate)) continue;
      if (found === null || row.validFrom > found.validFrom) found = row;
    }
    // A table that stops short of the date has usually not been updated.
    if (found === null) throw new RangeError(`no fuel surcharge in force on ${shipDate}`);
    basisPoints = found.basisPoints;
  }
  const fuelSurcharge = applyRate(bestFreight, basisPoints, "half-up");
  return {
    zone,
    ratedGrams: bestGrams,
    breakFromGrams: best.fromGrams,
    freight: bestFreight,
    fuelSurchargeBasisPoints: basisPoints,
    fuelSurcharge,
    total: addMoney(bestFreight, fuelSurcharge),
  };
}