Functional Weave
Code in Rust

inventory.stock-turnover@1.0.0

impl/typescript.ts

1,527 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 Money, assertSameCurrency, money } from "./money_amount.ts";  ← from money.amount ^1.0.0 · built alongside by fune
import { type StockTurnover } from "./inventory_stock_turnover_types.ts";

function notNegative(name: string, amount: Money): void {
  if (amount.minor < 0) throw new RangeError(`${name} must not be negative, received ${amount.minor}`);
}

/**
 * Turns, days inventory outstanding and days of cover. Each is one exact
 * division rounded half-up, then made a float, so every language agrees.
 */
export function stockTurnover(openingStock: Money, closingStock: Money, costOfSales: Money, periodDays: number): StockTurnover {
  assertSameCurrency(openingStock, closingStock);
  assertSameCurrency(openingStock, costOfSales);
  notNegative("openingStock", openingStock);
  notNegative("closingStock", closingStock);
  notNegative("costOfSales", costOfSales);
  if (!Number.isInteger(periodDays) || periodDays < 1) {
    throw new RangeError(`periodDays must be a whole number of days, at least 1, received ${periodDays}`);
  }
  const both = openingStock.minor + closingStock.minor;
  const cogs = costOfSales.minor;
  return {
    averageStock: money(roundDiv(both, 2, "half-up"), openingStock.currency),
    turns: both === 0 ? null : roundDiv(cogs * 200, both, "half-up") / 100,
    daysInventoryOutstanding: cogs === 0 ? null : roundDiv(both * periodDays * 10, cogs * 2, "half-up") / 10,
    daysOfCover: cogs === 0 ? null : roundDiv(closingStock.minor * periodDays * 10, cogs, "half-up") / 10,
  };
}