mega-plant/lib/cash-float.test.ts
David 1ec52961ee Cash float card, Office role + Slips tab, job card PDF, manual close/delete
- Cash Floats: ledger card (opening balance, top-ups, slips), manual entries, slip photos
- Office access level; clock app Slips tab (photograph a slip, popup for supplier/cost
  code/comments/amount); only Office sees it; per-role route table in lib/clock-access
- Job cards: Machine Service PDF (with Oil block), JC numbers, manual Close job, Delete
- Hide Expenses > Vehicle Costs and Finance (Bastion) from the menu

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:09:57 +02:00

17 lines
896 B
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { cashBalance, hasOpening, parseAmount } from "./cash-float";
test("balance is opening + top-ups minus slips, to the cent", () => {
assert.equal(cashBalance([{ kind: "opening", amount: 1000 }, { kind: "expense", amount: 250.1 }, { kind: "expense", amount: 0.2 }, { kind: "topup", amount: 100 }]), 849.7);
assert.equal(cashBalance([]), 0);
});
test("a card with no opening entry is not started", () => {
assert.equal(hasOpening([{ kind: "expense", amount: 5 }]), false);
assert.equal(hasOpening([{ kind: "opening", amount: 0.01 }]), true);
});
test("amounts accept South African typing and refuse junk", () => {
assert.equal(parseAmount("1 250,50"), 1250.5);
assert.equal(parseAmount("12.345"), 12.35);
for (const bad of ["", "0", "-5", "abc", "99999999"]) assert.equal(parseAmount(bad), null, bad);
});