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