You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

4.6 KiB

Reconciliation checkpoints design

Purpose

Add a local reconciliation workflow that compares an institution-reported balance with Gizmoduck's ledger for one account on one date. It gives the owner auditable confidence in account balances without changing transactions, creating clearing state, or depending on a particular import format.

Scope

The first version supports every active bank or credit-card account and any chosen as-of date. It records immutable balance checkpoints, shows their current status, and preserves their original calculation for audit.

It does not clear individual transactions, lock a reconciled period, infer a balance from source files, create card statements, or modify financial rows. Those capabilities remain future enhancements.

Domain model

Add ReconciliationCheckpoint to the finance domain:

Field Meaning
account Active account being checked; protected from deletion.
as_of_date Inclusive posting-date boundary for the comparison.
institution_balance Balance shown by the bank or card institution, in the account currency. Zero is valid.
ledger_balance_at_creation Sum of account transaction amounts through as_of_date when the checkpoint was recorded.
difference_at_creation institution_balance - ledger_balance_at_creation.
timestamps Immutable creation and update timestamps inherited from the existing base model.

There is deliberately no uniqueness constraint on (account, as_of_date). Entering a corrected balance creates another checkpoint rather than rewriting or deleting history. The latest checkpoint by creation time is the active checkpoint for that account and date.

The reconciliation service owns creation. It validates the account is active, accepts decimal-safe balances including zero, calculates the ledger snapshot in one database transaction, saves the checkpoint, and writes the existing AuditEvent with the human actor and outcome. No imported source text or institution credentials are persisted.

Current status and drift

When displaying a checkpoint, Gizmoduck recalculates the account's live ledger balance through the inclusive as_of_date. It compares that value with the stored institution balance.

  • Reconciled: the live difference is zero.
  • Difference: the live difference is nonzero and the original checkpoint also did not reconcile.
  • Changed since reconciliation: the original checkpoint reconciled, but later backdated activity changed the live ledger balance.

The checkpoint continues to retain its original ledger balance and difference. This makes late imports and dated manual entries visible without mutating the historical record. Opening balances participate in the ledger sum exactly like other transactions; reports still exclude them from income and spending.

Owner workflow

Add a Reconciliation navigation entry and page.

The page lists active accounts with their most recent checkpoint date and live status. The owner can select an account, choose an as-of date, and enter the institution balance. Before submission, the form shows the current ledger balance and difference for confirmation. Saving records the immutable checkpoint and redirects to the account's reconciliation history.

History shows each checkpoint's as-of date, institution balance, original ledger balance, original difference, current ledger balance, current difference, created time, and status. Amounts never cross currency boundaries. The existing dashboard retains account balances and gains only a compact latest reconciliation status per account.

Error handling and security

Invalid dates and money values receive field-level form errors. Archived or missing accounts are rejected by the domain service and translated to the existing safe owner-facing error messages. Forms use the existing CSRF protection and fixed local HUMAN/local-owner actor. Database exceptions and financial source data are never exposed in responses.

Verification

Use only synthetic data. Tests cover:

  • exact bank and credit-card reconciliation, including a zero institution balance;
  • an initial difference and a later corrected checkpoint for the same date;
  • a backdated transaction changing a previously reconciled checkpoint;
  • opening balances in reconciliation totals;
  • archived account rejection and audit behavior;
  • migration constraints, owner form validation, CSRF protection, account history, and dashboard status rendering.

Run focused domain and web tests, the full pytest suite, Django migration and system checks, and the existing PostgreSQL permission check.