Month lifecycle: Planning, Active, Closed with reconciliation gate #16
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/15-month-lifecycle"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #15 (will be manually closed on merge).
Summary
Each month now moves through three explicit states. Closing requires the applied balance to be exactly
$0.00. Nothing is swept automatically; the target row is just a hint about where leftover dollars should go.MonthStateenum added;state,activated_at,closed_atcolumns onmonthvia alembic batch migrationPOST /month/YYYY-MM/activatemoves Planning -> Active, stampsactivated_atPOST /month/YYYY-MM/closevalidatesapplied_zero == 0, moves Active -> Closed, stampsclosed_atPOST /month/YYYY-MM/reopenmoves Closed -> Active, nullsclosed_at_require_editable_monthdisabledwith a hover tooltip when balance isn't$0.00.Test plan
uv run pytestpasses (102/102, +20 new)uv run alembic upgrade headapplies and downgrades cleanlySchema change
Out of scope
POST /month/{ym}/activate, /close, /reopen each return 204 with HX-Redirect so the page re-renders in the new state. All existing mutation routes now go through _require_editable_month, which 400s on closed months. Month nav grows a state badge and a context-appropriate lifecycle button. Close is rendered with a disabled attribute and tooltip when applied zero != 0. On closed months, name / planned / applied / notes inputs carry the disabled attribute; delete buttons, add forms, and the target form are omitted entirely. Refs #15 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>