0.4.0: spending insights, safety net follow-through, payment method, stale-rate transparency, tests#14
Merged
Merged
Conversation
…sparency, tests Finishes the post-audit roadmap (everything kept). Bumps 0.3.0 -> 0.4.0. Data insight - by_category and forecast (30/60/90-day cash-out) totals-cycle modes - history screen grouped by month with per-month subtotals + the current month's actual-vs-estimate line Features - duplicate a subscription (Shift+D) into a prefilled modal - payment_method field on Subscription (column + migration, CRUD/io round-trip, modal field, filterable, shown on the row) - budget over-commitment warning in the notice board (when income is set) Robustness - stale-rate transparency: get_rate_status -> (rate, fresh|stale|missing); a failed fetch reuses the last-known rate (db.get_last_rate) instead of a fake 1:1, and the title bar shows stale vs missing distinctly Code health / tests - lifted totals + sort math into pure gakkari/totals.py (MainScreen delegates) - GAKKARI_DB env seam in get_conn() so tests use a temp DB - tests/ pytest suite (54 tests: models, totals, io, db) + .github/workflows/ci.yml - moved the UTF-8 stream guard to the top of __main__.main() (fixes --help / --notice em-dash mojibake under a legacy codepage); removed the dead SCREENS dict + redundant CSS_PATH from app.py Docs: CLAUDE.md + README refreshed; version bumped in all three spots. Verified: 54 tests pass; py_compile + import smoke clean; --help/--notice exit 0 under LC_ALL=C. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…I_DB - tests/test_strings.py: assert EN and JA string tables have identical keys (a missing JA key silently falls back to EN), plus t() fallback behavior. - export_modal._default_path now resolves through db._db_path() so the suggested export directory tracks the DB actually in use (addresses the one low-severity finding from the 0.4.0 review). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- docs/index.html: features list updated for 0.4.0 (undo, month-grouped history, by-category + forecast totals, duplicate + payment-method, budget watch, safe-by-default) and the Opus 4.8 credit line; the site is a standalone file, so it does not track the README automatically. - notice_panel tutorial (N off-state): add the global ? Help and Esc Back rows (the new D/u keys were already present), + bind_back string EN/JA. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
0.4.0 — finishing the post-audit roadmap
Implements every kept item from the improvement audit, landed as one release. Branches off
mainafter PR #13 (safety net) was merged; bumps 0.3.0 → 0.4.0.Data insight (mining the renewal_log + categories)
by_categorytotals mode (t) — per-category monthly-equivalent subtotals in base, largest first (top-5 + "+N").forecasttotals mode (t) — concrete, non-amortized 30/60/90-day cash-out (walks each active sub's real billing cycles; cumulative and horizon-inclusive), so clustered annual renewals stop hiding behind the amortized average.h) — per-month subtotal headers; the current month's header also shows your amortized estimate, so actual-so-far reads against what you committed to.Features
D/ Shift+D) — clones the highlighted sub into a prefilled modal (lowercasedstays Delete).payment_methodfield — optional funding source ("which card is this on?"): additive column + migration, full CRUD/CSV/JSON round-trip, a modal field, shown on the row, and matched by the/filter.▲ BASE x over budget (n%)line under the banner, regardless of the active totals mode.Robustness
currency.get_rate_statusreturns(rate, fresh|stale|missing). A failed fetch now reuses the last-known rate of any age (db.get_last_rate) instead of a fake 1:1, and the title bar distinguishes⌛ stale(old-but-real) from⚠ rate(never cached). A genuine 1.0 fetched today reads as fresh, not flagged.Code health & tests
gakkari/totals.py— the money/sort math lifted out of theMainScreengod-object into pure, explicitly-parameterized functions;MainScreendelegates.GAKKARI_DBenv seam inget_conn()(read at call time) so tests/tooling can point at a temp DB.tests/with 57 pytest tests (models date/tax/factor math, totals incl. forecast/by-category, io validation + round-trip, db round-trips + backup rotation, EN/JA i18n key-parity) +.github/workflows/ci.ymlrunning them plus a non-UTF-8-locale CLI smoke (which guards the--help/--noticeem-dash fix) on Python 3.12 / 3.13.__main__.main()(fixes--help/argparse mojibake under a legacy codepage); deadSCREENSdict + redundantCSS_PATHremoved fromapp.py.Docs
CLAUDE.md (data model, totals cycle, rate-freshness, project layout, a 0.4.0 deltas section) and README (features + credits) refreshed.
Verification
py_compile+ import smoke clean;--helpand--noticeexit 0 underLC_ALL=C.🤖 Generated with Claude Code