v1.0.368
fix(banks): honor account annotations and stop matching type on bare substrings
The Banks account list carried its own copy of the account-type inference,
and that copy had two defects the server-side categorizer did not:
-
It ignored the user's annotation entirely. An account explicitly annotated
ascredit-cardstill rendered whatever the name heuristic guessed, so the
override that exists specifically to correct a bad guess had no effect on
the badge. -
It matched bare substrings:
name.toLowerCase().includes('chk'). That also
matches the "chk" letter run inside an ordinary word — a surname of the
pas-CHK-e shape, for instance. Since the bank names business credit cards
after the cardholder, two business cards were labeled Checking, with the
amount owed rendered as a negative cash balance.
Extract the classifier to server/account-classify.ts (pure, so the frontend
imports it per the no-src-imports convention) and have both the snapshot route
and the Banks view use it:
- annotation.type always wins over any name guess
- name matching is word-boundary anchored, so CHK only matches as a token
- a negative balance is never depository; unknown ones read "Liability" and
flag as needing annotation - the account row now renders the annotation note, which is the only thing
distinguishing two cards the bank gives the same cardholder name - the annotation derives its options from one exported list, so they cannot drift from the union the API accepts Snapshot/debt totals are unchanged — the server categorizer was already correct, and moved over verbatim. fix(gold): stop pricing metals at $0 when futures markets are closed Metals spot prices come from Yahoo's spark endpoint using futures tickers (GC=F et al). Those pits are closed all weekend, so on Sat/Sun Yahoo returns timestamp: [], close: null while still carrying chartPreviousClose. The parser read only the intraday series, came back with an empty price map, and spotPrices[metal] || 0 turned "unknown" into "worthless". That wrote a goldValue of 0 into the day's portfolio snapshot — permanently — and dented totalValue by the same amount, which is why the history charts craterd on Sundays. It didn't happen every Sunday only because the in-process price cache (5 min TTL) is returned on failure, so a warm container masked it. data.ts: fall back close[last] -> meta.regularMarketPrice -> chartPreviousClose / previousClose, and throw on a payload that yields no usable prices rather than quietly returning a map of zeros. scheduler.ts: a metal that cannot be priced is never valued at $0. If any held metal is unpriced, carry the last known-good goldValue forward and log why, instead of writing a hole into history. Existing zeroed rows were backfilled separately in the data dir.