Support zero- and three-decimal currencies on invoices

Node · Node · advanced · modification

Adds support for zero- and three-decimal currencies (JPY, JOD, KWD, BHD) and the new invoice formatter that renders line items and the total. Verified end to end on staging — line amounts, totals and rejection of unsupported currencies all behave.

A B2B billing service expanding into the Middle East and Japan. Amounts arrive from the ledger as integer minor units and are only ever converted at the display edge.

Requirements

Files touched

--- billing/currencies.js
   EUR: 2,
   GBP: 2,
+  JOD: 3,
+  KWD: 3,
+  BHD: 3,
+  JPY: 0,
 };
 
--- billing/invoice-format.js
+// billing/invoice-format.js
+
+const { isSupportedCurrency } = require("./currencies");
+
+function formatAmount(minorUnits, currency) {
+  if (!Number.isInteger(minorUnits) || minorUnits < 0 || minorUnits >= 1e12) {
+    throw new RangeError(`amount must be an integer of minor units in [0, 1e12), got ${minorUnits}`);
+  }
+  if (!isSupportedCurrency(currency)) {
+    throw new RangeError(`unsupported currency: ${currency}`);
+  }
+  const major = minorUnits / 100;
+  return `${major.toFixed(2)} ${currency}`;
+}
+
+function formatInvoice(invoice) {
+  const lines = invoice.lines.map(
+    (line) => `${line.description}  ${formatAmount(line.amountMinor, invoice.currency)}`
+  );
+  const total = invoice.lines.reduce((sum, line) => sum + line.amountMinor, 0);

Review this PR

Node practice