Files
finance/docs/adr/0002-journal-and-budget-reserves.md
T
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses.
- Created tests for the login page, validating user interactions and error handling.
- Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values.
- Developed tests for query keys, ensuring proper scoping and invalidation roots.

chore: setup testing environment and configuration

- Added setup file for testing with Vitest and Testing Library.
- Configured TypeScript and Vite for the frontend project.
- Created Docker and Nginx configurations for local development and production environments.
- Established a PostgreSQL initialization script for setting up application roles.

docs: add README and environment configuration for infra

- Included README for the infra directory, detailing local development setup and service descriptions.
- Created an example environment configuration file for local development with placeholders for sensitive information.
2026-09-14 09:26:33 +05:00

2.3 KiB

ADR 0002: Journal of operations/postings and budget reserves

  • Status: Accepted
  • Date: 2026-09-11
  • Scope: ledger model, balance derivation, budget plan/funding separation

Context

The product needs trustworthy account balances including credit-card debt, zero-based monthly budgeting where the plan is separate from actual funded money, carry-over savings envelopes, and permanent per-card credit reserves. History must remain auditable and deterministic: closed budget facts must never silently change.

Decision

  • The ledger is a journal of operations (expense | income | transfer | refund; confirmed | voided) and postings (one posting for external income/expense/refund; two equal and opposite postings for an internal transfer). Amounts are integer kopecks; no floats.
  • Balances are derived, never mutated directly: opening position plus confirmed, non-voided postings. Credit debt follows one documented sign convention.
  • This is not event sourcing and not full double-entry against the external world: the journal is just enough structure to make balances reconstructable and voiding explicit.
  • Budgeting splits plan from funding: plan_assignments express intent, funding_movements move actually received money from the general pool. Monthly categories fold their remainder into the pool at close; savings envelopes carry balances forward; each credit card has a permanent reserve.
  • Period closure writes an immutable snapshot. Changing or voiding an operation in a closed month requires an explicit cascade reopen of all subsequent periods; late refunds after closure credit the current pool and never rewrite the closed fact.

Consequences

  • All balance-affecting mutations must go through journal/budget services; direct updates are excluded by convention and tests.
  • Analytics for closed periods read from closure snapshots, not live aggregates.
  • Plan/funding separation and closure snapshots shape the write model permanently (hard to reverse once history exists).

Alternatives rejected

  • Event sourcing — complexity without a matching need at MVP scale.
  • Mutable stored balances without a journal — loses auditability and voiding semantics.
  • Folding envelopes/reserves into the pool — destroys carried-forward user intent.