Task list from the 2026-10-08 repo audit, plus the plan for the two parity fixes found while validating the legacy/ move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.3 KiB
Fix the two Go/Python parity differences
Context
Running make parity against both containers on 2026-10-08 reported
0/3 routes match. Two causes, neither related to the move to legacy/:
- VS rendered in scientific notation by Go. The payments sheet is read
with
UNFORMATTED_VALUE, so a numeric VS cell arrives asfloat64. Go stringifies cells withfmt.Sprint, which prints any float ≥ 1e6 in exponent form (2.609767878e+09). Python already converts integer floats to plain digits for VS (get_strinfetch_sheet_data). VS must always be a plain string. months_to_showmissing from the Python JSON API. Go returns it in/api/adultsand/api/juniors(and it isrequiredin the committed schemas). Python already has the feature in its HTML pages (MONTHS_TO_SHOWis passed to the templates) but never added the key to the API responses. Backport the key so the API contract matches.
Outcome: make parity reports 3/3 routes matching.
Branching
Both are bug fixes that touch legacy/ paths, so they depend on the
uncommitted feat/python-to-legacy work. Commit that branch first (still
awaiting confirmation), then branch fix/api-parity-vs-months-to-show from
it, with one commit per task. Open the MR with tea after the legacy move is
merged, or target it at that branch.
Task 1 — VS (and other text cells) always a plain string in Go
Root cause is getVal in parseTransactionRows
(go/internal/services/membership/sources.go, the fmt.Sprint(row[i])
closure). The same pattern exists in get in
go/internal/services/banksync/infer.go.
- Add
CellString(v any) stringtogo/internal/io/sheets(new small filecell.go; both services already import this package):nil→""float64→strconv.FormatFloat(x, 'f', -1, 64)(never exponent form;2609767878.0→"2609767878",12.5→"12.5")string→ unchanged- anything else →
fmt.Sprint(v)
- Use it in
getValinsources.go. This fixes VS and protects the other text columns (Message, Bank ID, Sender, …) from the same failure.getValcurrently returns"<nil>"for nil cells and the inferred-amount code checks for that literal; simplify that check toiv != "".- Leave
getRaw/FormatDateandparseFloatfor Date and Amount as they are — those must stay numeric.
- Use it in
getinbanksync/infer.go(keeping theTrimSpace), so inference sees the same text the dashboard shows. - Tests:
go/internal/io/sheets/cell_test.go: table test forCellString(large integer float, small integer float, fractional, string with leading zeros, nil).- Extend
TestLoadTransactionsingo/internal/services/membership/sources_test.gowith a row whose VS is2609767878.0and whose Bank ID is an 11-digit float; assert plain digit strings.
- Python: no code change needed —
get_stralready does this for VS. Add one regression test forfetch_sheet_datainlegacy/tests/test_match_payments.py(mock the Sheets service, numeric VS cell →"2609767878") so the two sides are pinned to the same behaviour.
Not included (note for later): VS is written to the sheet with
USER_ENTERED by both sync implementations, so Sheets stores it as a number
and drops leading zeros. Fixing that means writing VS as text and is a
separate change to the sheet's data.
Task 2 — backport months_to_show to the Python JSON API
legacy/app.py only; MONTHS_TO_SHOW is already imported there.
- In
api_adults()andapi_juniors(), add the key to the response: buildout = _unwrap_view_model_for_api(vm), setout["months_to_show"] = MONTHS_TO_SHOW, returnjsonify(out).- Do not add it inside
build_*_view_modelor_unwrap_view_model_for_api: the HTML routes already passmonths_to_show=torender_templatealongside**vm, and a duplicate key would raiseTypeError. /api/paymentsis unchanged; Go does not return the key there.
- Do not add it inside
- Tests in
legacy/tests/test_app.py:- Add
"months_to_show"to the expected key list used bytest_api_adults/test_api_juniors(the tuple near the top of the file), and assert the value is anint.
- Add
- Go: no change. The key and schemas
(
go/tests/fixtures/api-schema/{adults,juniors}.schema.json) already contain it.
Wrap-up
CHANGELOG.mdentry at the top (after confirmation it works), per repo convention.- Copy this plan to
docs/plans/2026-10-08-HHMM-api-parity-vs-months-to-show.md, per the repo's plan-location rule. - Add both items to
docs/plans/2026-10-08-1026-pre-feature-cleanup-tasks.mdas done tasks so the audit list stays complete.
Verification
make go-test-all— unit tests (including the new ones) and parity fixtures pass.make test— Python tests pass, including the new API key and VS tests.cd go && go test ./internal/web/api/...— schema golden test still matches (no schema change expected).- End to end: start
make web-pyandmake web-go, thenmake parity; expect3/3 routes match. Alternatively repeat the two-container run used to find the bugs (make image, Go image fromgo/build/Dockerfile, thengo run ./cmd/parity -py … -go …). - Open
/paymentson :8080 and check the affected transaction's VS shows as plain digits.