First-run setup: upload Bills_Tracker.xlsx and loader_rules.json from the web page when the data folder is empty
build-container / build (push) Successful in 34s
build-container / build (push) Successful in 34s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3dba054dca
commit
6f4ecd42f7
3 files changed
+16
-3
No files matched your search
@@ -55,6 +55,9 @@ def coverage(sts):
|
||||
return dict(months=months, accounts=out)
|
||||
|
||||
def state():
|
||||
if not L.WORKBOOK.exists():
|
||||
return dict(setup=True, data_dir=str(DATA), rules=(DATA / "loader_rules.json").exists(),
|
||||
files=sorted(p.name for p in DATA.glob("*") if p.is_file())[:50])
|
||||
res = L.run_preview(DATA)
|
||||
new = res["new"]
|
||||
rows = [dict(date=f"{r.txn.date:%Y-%m-%d}", account=r.txn.account, desc=r.txn.desc[:60], amount=r.txn.amount, kind=r.kind,
|
||||
@@ -71,6 +74,7 @@ _DATA = {}
|
||||
def workbook_data():
|
||||
"""Read-only snapshot of the Bill Log for the web dashboard (computed from raw cells, not cached formulas)."""
|
||||
from openpyxl import load_workbook
|
||||
if not L.WORKBOOK.exists(): return dict(tx=[], categories=[], excluded=0, updated="", setup=True, data_dir=str(DATA))
|
||||
key = L.WORKBOOK.stat().st_mtime_ns
|
||||
if _DATA.get("key") == key: return _DATA["val"]
|
||||
wb = load_workbook(L.WORKBOOK, read_only=True)
|
||||
@@ -90,7 +94,11 @@ def workbook_data():
|
||||
|
||||
def safe_name(name):
|
||||
name = re.sub(r"[^\w.\- ]", "_", Path(name).name)
|
||||
if Path(name).suffix.lower() not in (".pdf", ".csv"): raise ValueError("Only PDF or CSV files can be added.")
|
||||
if name == "Bills_Tracker.xlsx":
|
||||
if L.WORKBOOK.exists(): raise ValueError("Bills_Tracker.xlsx already exists in the data folder; it won't be overwritten.")
|
||||
return L.WORKBOOK
|
||||
if name == "loader_rules.json": return DATA / name
|
||||
if Path(name).suffix.lower() not in (".pdf", ".csv"): raise ValueError("Only PDF or CSV statements, Bills_Tracker.xlsx (first time only) or loader_rules.json can be added.")
|
||||
p = DATA / name; i = 1
|
||||
while p.exists():
|
||||
p = DATA / f"{Path(name).stem}_{i}{Path(name).suffix}"; i += 1
|
||||
@@ -128,7 +136,9 @@ class H(BaseHTTPRequestHandler):
|
||||
if u.path == "/api/upload":
|
||||
name = parse_qs(u.query).get("name", [""])[0]; data = self.rfile.read(n)
|
||||
with LOCK:
|
||||
p = safe_name(name); p.write_bytes(data)
|
||||
p = safe_name(name)
|
||||
if p.name == "loader_rules.json": json.loads(data) # must be valid JSON
|
||||
DATA.mkdir(parents=True, exist_ok=True); p.write_bytes(data)
|
||||
return self._send(200, {"saved": p.name})
|
||||
self.rfile.read(n)
|
||||
if u.path == "/api/import":
|
||||
|
||||
Reference in new issue
Block a user