# Changelog ## 2026-10-08 11:34 CEST — fix(python): return months_to_show from /api/adults and /api/juniors - Go already returned `months_to_show` in the JSON API; Python only passed it to its HTML templates. Backported the key so the API contract matches and `make parity` reports 3/3 routes. - Key files: `legacy/app.py`, `legacy/tests/test_app.py`. ## 2026-10-08 11:34 CEST — fix: VS is always a string, on read and on write - Go rendered numeric sheet cells with `fmt.Sprint`, so a numeric VS came out as `2.609767878e+09`. Text columns of the payments sheet now go through `sheets.CellString` (plain digits); bank inference uses it too. - Both sync implementations now append VS as a text cell (leading apostrophe under `USER_ENTERED`), so Sheets no longer stores it as a number or drops leading zeros. Existing rows are unchanged. - Key files: `go/internal/io/sheets/cell.go`, `go/internal/services/membership/sources.go`, `go/internal/services/banksync/{sync,infer}.go`, `legacy/scripts/sync_fio_to_sheets.py`. ## 2026-10-08 11:33 CEST — refactor: move Python implementation to legacy/, Go is primary - Go (`go/`) is now the primary implementation. The original Python version moved to `legacy/` (`app.py`, `scripts/`, `templates/`, `tests/`, `pyproject.toml`, `uv.lock`, `build/`) and is considered legacy; new features are still built in both. - `CLAUDE.md` rewritten for the Go-first layout, with a "Dual implementation rule" section. - Makefile Python targets keep their names and point at `legacy/`; virtualenv is `legacy/.venv`, Python cache is `legacy/tmp/`; `CREDENTIALS_PATH` is exported pointing at the root `.secret/` file. - CI builds the Python image with `legacy/` as context; the image no longer contains the Makefile. `legacy/.dockerignore` now takes effect and excludes nested `__pycache__`. - Go comments, fixture README, capture script and VS Code launch config updated to the new paths. ## 2026-06-12 19:32 CEST — feat(ci): gitops image-update PR workflow - Added `.gitea/workflows/gitops-update.yaml`: after each successful Go image build, `uh-cli gitops deployment update` opens a PR in `kacerr/home-kubernetes` bumping the `fuj-management` Deployment (namespace `fuj`) to the new image tag. - Supports `workflow_run` auto-trigger and `workflow_dispatch` with `dry_run` / `uh_cli_version` inputs. - Requires `GITOPS_TOKEN` repo secret (Gitea PAT with write+PR access to `home-kubernetes`). ## 2026-05-24 21:58 CEST — feat(fees): update adult monthly rates for 2026-05 through 2026-08 - 2026-05: 700 → 450 CZK; 2026-06/07/08: 600 CZK (new months added). - Mirrored in both `scripts/attendance.py` and `go/internal/domain/fees/fees.go`. ## 2026-05-24 21:42 CEST — feat: multi-account Fio sync + switch QR default to 2502035405/2010 - Added second bank account `2502035405/2010` (IBAN `CZ0820100000002502035405`) to sync. - Both accounts are fetched on every sync; dedup by existing sync_id keeps the payments sheet clean. - QR codes now default to the new account (`CZ0820100000002502035405`). - Go: `config.go` gains hardcoded `Accounts`/`LoadedAccount` slice; `Config.BankAccount` renamed to `Config.QRAccount`; `FioAPIToken` removed (tokens are per-account via `FIO_API_TOKEN_NEW` / `FIO_API_TOKEN_OLD`). - Go: `SyncToSheets` now accepts `[]fio.Client`; new `TestSyncToSheets_MultiAccount` test. - Python: `config.py` gains `ACCOUNTS` / `LOADED_ACCOUNTS`; `fio_utils.py` adds `fetch_transactions_for` and `fetch_transactions_all`; `sync_fio_to_sheets.py` uses `fetch_transactions_all`. - Key files: `go/internal/config/config.go`, `go/internal/services/banksync/sync.go`, `go/cmd/fuj/main.go`, `scripts/config.py`, `scripts/fio_utils.py`, `scripts/sync_fio_to_sheets.py`. ## 2026-05-11 23:58 CEST — fix(reconcile): fill earliest month deficit first in multi-month allocations - Multi-month payment allocation now fills the earliest in-window deficit first and spills any remainder to later months, accounting for prior transactions' contributions to each month. Previously a single transaction was split proportionally to each month's total expected fee, ignoring what earlier transactions had already paid — surfaced by Matyáš Thér's 200+550 case showing 566/183 instead of 500/250. - Files: `scripts/match_payments.py`, `go/internal/domain/reconcile/reconcile.go`, tests, parity fixtures. ## 2026-05-11 22:56 CEST — fix(python): parse Fio 2-digit-year dates + add `make sync-debug` dry-run tool - Fix: `scripts/fio_utils.py` `parse_czech_date` now accepts `DD.MM.YY` / `D.M.YY` in addition to the 4-digit-year variants. Fio's transparent page now mixes both forms in the same response; the 2-digit rows were being silently dropped, which caused `make sync-2026` to miss every recent transfer. Mirrors the Go-side fix from 2026-05-07 (CHANGELOG entry below). - Added `--dry-run` and `--print-fio-table` flags to `scripts/sync_fio_to_sheets.py`, plus a `make sync-debug [DAYS=N]` Makefile target. Mirrors `make go-sync-debug`: fetches from Fio and dedupes against the sheet, prints `STATUS=NEW/DUP` per transaction, and prints per-row `Dry run: would append …` lines + `would sort by date` instead of touching the sheet. - Added always-on stderr diagnostics in `scripts/fio_utils.py`: which fetcher was selected (authenticated API vs. transparent-page scraper with `FIO_API_TOKEN`-unset warning), and raw-vs-after-filter transaction counts on both paths — so this class of "scraper drops everything" bug surfaces immediately. ## 2026-05-08 15:24 CEST — feat(go): M6.7 — single-binary embed verification - Confirmed `embed.FS` wiring is complete: templates parsed via `template.ParseFS(templateFS, ...)`, static assets served via `http.FileServerFS(fs.Sub(staticFS, "static"))`. - Added `go/internal/web/assets_test.go` with two tests: `TestEmbedCompleteness` (walks disk vs embed.FS to catch forgotten files) and `TestStaticAssetsServed` (hits `/static/css/app.css` and all JS files through the mux, asserts 200 + Content-Type + non-empty body + 404 for unknown paths). - Closes M6; single binary confirmed self-contained with no adjacent `templates/` or `static/` required at runtime. - Key files: `go/internal/web/assets_test.go` (new). ## 2026-05-08 14:55 CEST — feat(go): M6.6.1 — Pay-button QR popup modal - Restored the Python `showPayQR` in-page modal UX that was lost in M6.6 (Pay buttons were navigating the tab to the raw `/qr` PNG). - Replaced `Pay` with `