Accounts tab and page: savings and mortgage balances kept separate from spending and the budget
build-container / build (push) Successful in 44s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-21 15:59:21 -04:00
1 parent 20317b14c9
commit 1f556bccfa
8 files changed
+205 -15

No files matched your search

+20 -4
View File
@@ -71,7 +71,7 @@ def state():
return dict(coverage=coverage(res["statements"] + L.archived_statements()), skipped=[dict(file=f, why=w) for f, w in res["skipped"]],
duplicates=[dict(file=a, same_as=b) for a, b in res["dups"]],
bad=[dict(file=f, parsed=p, stated=s) for f, p, s, ok in res["checks"] if not ok],
already=res["already"], new=rows, archivable=(0 if new else len([x for x in res["statements"] if x.file not in res["bad"]])), summary=sm, statements=len(res["statements"]),
already=res["already"], new=rows, accounts_new=len(res["snaps"]), archivable=(0 if (new or res["snaps"]) else len([x for x in res["statements"] if x.file not in res["bad"]])), summary=sm, statements=len(res["statements"]),
excel_open=(DATA / "~$Bills_Tracker.xlsx").exists() or (DATA / ".~lock.Bills_Tracker.xlsx#").exists(),
backups=sorted(p.name for p in L.BACKUPS.glob("*.xlsx"))[-5:] if L.BACKUPS.exists() else [])
@@ -151,6 +151,21 @@ class H(BaseHTTPRequestHandler):
if not L.WORKBOOK.exists(): return self._send(200, {"setup": True})
return self._send(200, B.compute(workbook_data(), month))
except Exception as e: return self._send(500, {"error": str(e)})
if u.path == "/accounts":
f = HERE / "app_accounts.html"
return self._send(200, f.read_bytes().replace(b"__TOKEN__", TOKEN.encode()) if f.exists() else b"app_accounts.html missing", "text/html; charset=utf-8")
if u.path == "/api/accounts":
with LOCK:
try:
if not L.WORKBOOK.exists(): return self._send(200, {"setup": True, "rows": []})
from openpyxl import load_workbook
wb = load_workbook(L.WORKBOOK, read_only=True, data_only=True)
try: rows = L.account_rows(wb)
finally: wb.close()
for r in rows:
for k in ("date", "due"): r[k] = r[k].isoformat() if r[k] else None
return self._send(200, {"rows": rows})
except Exception as e: return self._send(500, {"error": str(e)})
if u.path == "/api/budget_history":
with LOCK:
try:
@@ -197,12 +212,13 @@ class H(BaseHTTPRequestHandler):
if u.path == "/api/import":
with LOCK:
res = L.run_preview(DATA)
if not res["new"]: return self._send(200, {"message": "Nothing new to import."})
out = L.apply(res["new"])
if not res["new"] and not res["snaps"]: return self._send(200, {"message": "Nothing new to import."})
out = L.apply(res["new"], snaps=res["snaps"])
try: filed = L.archive_statements()["moved"]
except Exception: filed = 0
tail = f" Filed {filed} statement(s) into Statements/year/month." if filed else ""
return self._send(200, {"message": f"Added {out['log_rows']} rows to the Bill Log and {out['excluded_rows']} to Excluded Transfers.{tail}",
acc = f" Recorded {out['accounts']} savings/loan balance(s) on the Accounts tab." if out["accounts"] else ""
return self._send(200, {"message": f"Added {out['log_rows']} rows to the Bill Log and {out['excluded_rows']} to Excluded Transfers.{acc}{tail}",
"backup": Path(out["backup"]).name, "new_payees": out["new_payees"]})
if u.path == "/api/archive":
try: