Functional Weave
Code in TypeScript

banking.cheque-amount-words@1.0.0

impl/typescript.ts

1,567 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, money } from "./money_amount.ts";  ← from money.amount ^1.0.0 · built alongside by fune
import { formatMoney } from "./money_format.ts";  ← from money.format ^1.0.0 · built alongside by fune
import { amountInWords } from "./text_number_to_words.ts";  ← from text.number-to-words ^1.0.0 · built alongside by fune
import { type ChequePenceStyle, type ChequeWording } from "./banking_cheque_amount_words_types.ts";

/** The abbreviation written after pence as figures: 50p, 50c. */
const MINOR_SUFFIX: { [code: string]: string } = { GBP: "p", EUR: "c", USD: "c" };

/**
 * The amount lines of a cheque. The words come from text.number-to-words,
 * capitalised and closed with "only" so nothing can be added after them; the
 * figures come from money.format.
 */
export function chequeAmountWords(amount: Money, penceStyle: ChequePenceStyle): ChequeWording {
  if (amount.minor <= 0) {
    throw new RangeError(`a cheque amount must be greater than zero, received ${amount.minor}`);
  }
  let body: string;
  if (penceStyle === "words") {
    body = amountInWords(amount);
  } else if (penceStyle === "figures") {
    // The pounds are always in words, even when there are none, so the line
    // never starts with a figure that could be altered.
    const major = Math.floor(amount.minor / 100);
    const minor = amount.minor % 100;
    body = amountInWords(money(major * 100, amount.currency));
    if (minor > 0) {
      body += ` and ${minor}${MINOR_SUFFIX[amount.currency]}`;
    }
  } else {
    throw new RangeError(`unknown pence style "${penceStyle}": expected words or figures`);
  }
  const words = `${body.charAt(0).toUpperCase()}${body.slice(1)} only`;
  return { words, figures: formatMoney(amount) };
}