# Changelog ## 2026-05-04 12:02 CEST — Go rewrite M1: skeleton + tooling - Created `go/` tree with module `fuj-management/go` (Go 1.26). - `cmd/fuj`: stdlib-flag subcommand dispatcher; `server` and `version` implemented, stubs for M2/M4 commands. - `internal/config`: env loader mirroring `scripts/config.py` (same env var names and defaults). - `internal/logging`: slog setup accepting log level from config. - `internal/web`: `net/http` ServeMux on `:8080`; `middleware/timer.go` logs method/path/status/ms. - `go/build/Dockerfile`: multi-stage (`golang:1.26` → `alpine:3`) producing a static binary image. - Makefile: `web` → `web-py` alias; added `web-go`, `go-build`, `go-test`, `go-run`, `go-lint`. - `.gitea/workflows/build.yaml`: parallel `build-go` job pushing `-go` image. - Gate: `make go-build`, `make go-lint`, `make go-test`, `curl :8080` all pass. ## 2026-05-03 20:37 CEST — Fix Balance column to correctly reflect past-month debt - Balance (and Pay-All) are now computed as `sum(paid − expected)` over past months only, iterating directly over the ledger entries from `reconcile()`. - Previously the balance used `total_balance` (which includes current/future-month activity and out-of-window credits) plus a one-sided current-month debt adjustment. Current-month *surplus* leaked through, making the balance appear less negative than the actual past-month debt. - Pay-All is now `max(0, −balance)` so the two values are derived from a single source and can never disagree. - Affected: `adults_view()` and `juniors_view()` in `app.py`. ## 2026-05-03 19:26 CEST — Fee-aware allocation for multi-month payments - `reconcile()` no longer splits a multi-month payment evenly. Allocation is now per-member with two phases: greedy (if amount ≥ total expected, each month gets exactly its expected fee and overflow → credit) and proportional (otherwise distribute by each month's expected). Fixes the case where e.g. 1250 CZK covering 3 months with mixed fees (750/350/150) marked two months red. - Out-of-window months keep the previous even-split-to-credit behavior. Fallback to even split when all matched months have `expected = 0` (prepayment before attendance is recorded). - Display layer only — no changes to how payments are stored in Google Sheets; `Inferred Amount` still holds the full bank amount. - Files: [scripts/match_payments.py](scripts/match_payments.py), [tests/test_reconcile_exceptions.py](tests/test_reconcile_exceptions.py) (6 new test cases).