Skip to content

Rework debts: every debt type, projections, strategies, and a redesigned UI - #54

Merged
RaihanStark merged 9 commits into
mainfrom
rework-debt
Jul 11, 2026
Merged

Rework debts: every debt type, projections, strategies, and a redesigned UI#54
RaihanStark merged 9 commits into
mainfrom
rework-debt

Conversation

@RaihanStark

Copy link
Copy Markdown
Owner

Summary

Reworks the Debts module from BNPL-only into full debt tracking — the #1 item on the post-1.0 roadmap. Existing .financy files migrate automatically (schema v8 → v9, column-adds only, with the usual pre-migration backup); BNPL debts behave exactly as before.

Debt types

  • BNPL / installments — unchanged behavior, now with a principal/interest split on every installment (existing rows backfilled as 100% principal).
  • Amortizing loans (mortgage, auto, student, personal) — schedule generated from principal + APR; every payment posts a 3-leg split (principal draws the liability down, interest is expensed as paid), so the liability account always equals remaining principal. Extra payments shorten the term (default) or lower the payment, with a live payoff/interest-saved preview.
  • Revolving credit (cards, lines of credit) — attach the card account you already track (history stays yours; deleting the debt detaches, never deletes) or create one. Credit limit and utilization, minimum-payment rule, and a monthly statement review that proposes an editable interest charge — never auto-posted. Card payments are budget-neutral transfers so envelopes never double-count.
  • Informal IOUs — a balance with an optional due date; pay any amount, optionally recording which account the borrowed cash landed in.

Projections & strategies

  • Per-debt payoff date and interest remaining, with explicit feasibility (a minimum payment that can't beat the interest reports as such instead of looping).
  • Snowball vs avalanche comparison for any extra monthly amount: payoff order, debt-free date, total interest, cheapest plan highlighted.
  • Overview dashboard: total owed, balance-weighted APR, due now, projected debt-free date.

UI (desktop + mobile parity)

  • Desktop Debts screen: dashboard cards + a compact table (kind, APR, balance, progress/utilization bar, status); a row opens the debt's detail in a dialog that repaints itself after every mutation and closes if the debt is deleted.
  • Type-driven add form: pick a kind and only its essentials appear (e.g. loan = name, principal, APR, term) with a live plan preview; everything optional folds into an Advanced setup accordion with working defaults.
  • Mobile mirrors it all: per-kind cards and detail pages, statement review, extra payments, strategies page.

Fixes

  • Deleting a debt no longer destroys user transactions that were linked to installments — they're restored to their original postings first.
  • AmortizedPayment rounds up so a solved payment never spills into an extra installment past the requested term.

Engineering notes

  • Interest math is integer minor-units throughout (half-up kernel shared by schedules, projections, and strategy simulations — they can never drift apart); APR stored as basis points; only the annuity solve uses a transient float, rounded once.
  • ~60 new tests: amortization goldens and rounding edges, the balance == unpaid-principal invariant across pay/link/undo/extra sequences, a real v8→v9 migration test, budget-gating regressions, strategy ordering, and view/dialog lifecycle tests.
  • Demo data now seeds a mid-term car loan, the demo card attached as a revolving debt, and a partly-repaid IOU.
  • CHANGELOG updated under [Unreleased]; ROADMAP moves in-depth debt management to shipped.

🤖 Generated with Claude Code

…rojections

Schema v9 adds per-type debt fields (APR in basis points, loan payment/
principal, revolving statement profile, informal due date) and a principal/
interest split on installments (existing BNPL rows backfilled as 100%
principal). New amortization engine (integer half-up interest kernel, annuity
payment solve, balance-walk schedule generation with residual-absorbing final
payment). Loans book principal-only originations and pay via 3-leg splits
(principal draws the liability, interest is expensed as paid), with extra
payments that shorten the term or re-amortize. Revolving debts attach or
create an on-budget card account with no schedule or envelope; interest lands
via a monthly statement-review flow, payments are budget-neutral transfers.
Informal debts are envelope-backed balances with arbitrary payments. Payoff
projections, snowball-vs-avalanche comparison, and an overview aggregate
(weighted APR, 12-month history) run as pure simulations sharing the interest
kernel, capped with explicit feasibility flags. DeleteDebt now restores
linked transactions' original postings and detaches (never deletes) revolving
history.
…gies

The Debts screen gains an overview dashboard (total owed, balance-weighted
APR, due now, debt-free date, 12-month trend) and a statement-review banner.
Each debt kind gets its own detail pane: loans show principal/interest
columns, payoff pills and an extra-payment dialog with live preview;
revolving cards show utilization, minimum due, statement review and recent
activity; informal IOUs show the owed balance with arbitrary payments. The
add/edit form is type-driven — pick a kind and only its fields appear, with
a live plan preview (computed payment or term, payoff date, total interest).
A strategies dialog compares snowball vs avalanche with payoff order and
totals. The Add Transaction 'Pay debt' path now handles schedule-less debts
with a free amount defaulted to the minimum due or remaining balance.
The Debts tab header now shows total owed, weighted APR, and the debt-free
date; cards are per-kind (schedule progress, card utilization with minimum
due, IOU balance with due date), with a statement-review banner and a payoff
strategies page. The add/edit form is type-driven with a live plan preview.
Detail pages match the desktop: loans get payoff/interest figures, the
principal/interest split per installment and an extra-payment page; cards
get balance vs limit, statement review, record-payment and recent activity;
IOUs get arbitrary payments and settlement state. Deleting a revolving debt
explains that the account and its transactions stay.
… debt rework

The demo document gains a mid-term car loan, upgrades its credit card to a
tracked revolving debt by attaching the existing account, and adds a
partly-repaid IOU. AmortizedPayment now rounds up so a solved payment never
spills into an extra installment past the requested term, and an informal
debt's due date now serves as its payoff projection so the dashboard's
debt-free date covers IOUs. CHANGELOG under [Unreleased]; ROADMAP moves
in-depth debt management from 'upcoming' to shipped; README feature list and
usage notes updated.
The dashboard keeps the four stat cards (total owed, average APR, due now,
debt-free by); the 12-month history line and its core plumbing
(DebtOverview.History, debtHistory, MonthBalance) are dropped.
…dion

Adding a debt now asks only for the bare minimum per kind — BNPL: name,
total, installments, first due; loan: name, principal, APR, term; card:
name, balance, APR; IOU: name, amount — each with its live plan preview.
Everything optional (lender, pay-from account, dates, frequency, card
statement/minimum profile, attach-account, deposited-to, note) folds into a
collapsed 'Advanced setup' accordion with defaults that just work: pay-from
picks the first account, dates default to today, frequency to Monthly,
statement day to 1. Desktop and mobile alike; edit forms are unchanged.
The tab-per-debt master/detail becomes a single compact table — one row per
debt with kind, APR, balance, a progress/utilization bar, and a status line
(next due, overdue count, statement to review, min due, settled) tinted when
it needs attention. Tapping a row selects it and opens its detail pane below;
the selection persists across rebuilds like the old tabs did. Detail panes
drop their inner scrolls to flow with the page. Mobile is unchanged.
Tapping a table row now opens the debt's detail pane in a popup. A single
per-store subscriber repaints the open dialog after every store mutation —
paying, undoing, editing, statements — and closes it when the debt itself is
deleted from within. The Debts screen is left as just the dashboard and the
compact table.
@RaihanStark
RaihanStark merged commit fa4534c into main Jul 11, 2026
3 checks passed
@RaihanStark
RaihanStark deleted the rework-debt branch July 11, 2026 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant