Skip to content
CRN-SoftwarePublic

About

Cash-position dashboard: integer-cent treasury reports from bank exports. NestJS + Vue 3 + Nx monorepo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Thoth

CI

Cash-position dashboard for a small company: it turns a raw bank export into a monthly cash-flow statement, a daily balance curve, OHLC-style monthly ranges and runway KPIs.

I built it to follow the treasury of my own consulting company. The repository ships with a fully fictional, generated ledger; real bank data never leaves my machine.

Thoth dashboard

Highlights

  • Integer-cent money. Amounts are parsed from strings into integer cents and stay integers through every aggregation. Floats appear only when formatting for display.
  • Timezone-proof calendar. Transactions are bucketed by their booking date as written in the export (YYYY-MM-DD), never converted to instants, so a +02:00 booking at midnight cannot slip into the previous month.
  • Reconciliation invariants, tested. For every month: opening + net = closing, and category totals add up to the net flow (uncategorized lines are classified by cash direction to keep it so).
  • Fail-fast ingestion. The ledger is validated with a Zod schema at startup. A malformed amount or an unknown category type stops the API instead of producing a wrong report.
  • Pure domain core. All treasury logic lives in a framework-free library shared by the API and the UI; the NestJS and Vue layers stay thin.

Architecture

apps/
  api/          NestJS REST API: GET /api/treasury/report?to=YYYY-MM&months=N
  frontend/     Vue 3 + Vuetify + Chart.js dashboard
libs/
  treasury/     Pure TypeScript domain: parsing, money, calendar, report, KPIs
tools/
  generate-demo-data.mjs   Seeded generator for the fictional ledger
data/
  demo/         Committed fictional ledger (default data source)
  private/      Real exports, git-ignored
flowchart LR
  file[(Ledger JSON)] --> repo[JsonFileTransactionsRepository<br/>Zod validation]
  repo --> ctrl[TreasuryController]
  ctrl --> lib[["@thoth/treasury<br/>buildTreasuryReport()"]]
  ctrl -- TreasuryReport JSON --> ui[Vue dashboard]
  lib -. shared types & formatting .-> ui
Loading

The ledger source is behind a TransactionsRepository port, so the JSON adapter can be replaced by a database or a bank API without touching the domain or the controller.

Getting started

Requirements: Node.js 20+ and npm 10+.

npm install
npm start            # API on :3333, dashboard on http://localhost:4200
Command What it does
npm test Unit and HTTP tests (Vitest + Jest/Supertest)
npm run lint ESLint on every project
npm run typecheck tsc / vue-tsc on every project
npm run build Production builds
npm run demo-data Regenerates the deterministic demo ledger

Using your own data

Point the API at any export that follows the same format (extra fields are ignored):

{
  "id": "5e658d9d-…",
  "occurred_at": "2025-01-15T00:00:00.000+01:00",
  "amount": "-4599",
  "description": "SOFTWARE SUBSCRIPTION",
  "category_name": "Software",
  "category_type": "EXPENSE"
}
THOTH_TRANSACTIONS_FILE=data/private/transactions.json npm start

data/private/ is git-ignored.

API

GET /api/treasury/report

Query Default Constraint
to month of the latest transaction YYYY-MM
months 12 integer 1 – 36

Returns the window, the per-month summary (opening, closing, high, low, income, expenses, net, per-category totals), one balance point per day, and KPIs (closing balance, net change, average monthly spend, runway). Invalid queries get a 400 listing each failing field.

Roadmap

  • Forecast: project recurring flows to estimate the balance for upcoming months
  • Transaction drill-down from a table cell
  • Bank import adapters (CSV, open banking) behind the repository port
  • Persistence (PostgreSQL) once imports are incremental

License

MIT

About

Cash-position dashboard: integer-cent treasury reports from bank exports. NestJS + Vue 3 + Nx monorepo.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages