retail.volumetric-weight@1.0.0
impl/typescript.ts
1,453 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 { type ChargeableWeight } from "./retail_volumetric_weight_types.ts";
/**
* The weight a carrier charges on: the greater of actual and volumetric,
* rounded up to the carrier's billing step.
*
* mm³ / (cm³ per kg) is exactly grams, so everything stays in integers.
*/
export function chargeableWeight(
lengthMm: number,
widthMm: number,
heightMm: number,
actualGrams: number,
divisor: number,
roundUpToGrams: number,
): ChargeableWeight {
for (const d of [lengthMm, widthMm, heightMm]) {
if (!Number.isInteger(d) || d < 1) throw new RangeError(`dimensions must be 1 mm or more, received ${d}`);
}
if (!Number.isInteger(actualGrams) || actualGrams < 0) {
throw new RangeError(`actualGrams must not be negative, received ${actualGrams}`);
}
if (!Number.isInteger(divisor) || divisor < 1) throw new RangeError(`divisor must be 1 or more, received ${divisor}`);
if (!Number.isInteger(roundUpToGrams) || roundUpToGrams < 1) {
throw new RangeError(`roundUpToGrams must be 1 or more, received ${roundUpToGrams}`);
}
const volumetricGrams = roundDiv(lengthMm * widthMm * heightMm, divisor, "up");
const heavier = Math.max(actualGrams, volumetricGrams);
return {
actualGrams,
volumetricGrams,
chargeableGrams: roundDiv(heavier, roundUpToGrams, "up") * roundUpToGrams,
basis: volumetricGrams > actualGrams ? "volumetric" : "actual",
};
}