All checks were successful
Deploy to K8s / deploy (push) Successful in 9s
go/internal/domain/czech.Normalize merged as 20ade6d (PR #4).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.6 KiB
3.6 KiB
Changelog
2026-05-05 23:33 CEST — feat(go/M2.1): port czech.Normalize
- First M2 pure-domain task:
internal/domain/czech.Normalize(NFKD + Mn-strip + lowercase), byte-equivalent to Pythonczech_utils.normalize. - Adds
golang.org/x/text v0.36.0as first external Go dependency. - 13-case table-driven test, all spot-checked against Python before locking.
2026-05-04 23:08 CEST — fix: payment inference exact-match short-circuit
match_members()now short-circuits on whole-word full-name hits; nickname/partial checks only run when no full name is present.- Replaced bare
insubstring checks with_word_in()word-boundary regex throughout, closing the class of bugs where a short nickname (e.g.tov) matches inside another member's surname (ottova). - Added
tests/test_match_members.py(6 cases). Affectsscripts/match_payments.py.
2026-05-04 23:08 CEST — feat: lower adult monthly fee to 700 CZK from April 2026
ADULT_FEE_DEFAULTreduced from 750 → 700 CZK.ADULT_FEE_MONTHLY_RATEnow pins Sep 2025 – Feb 2026 at 750 to preserve historical billing; Mar 2026 stays 350; Apr–May 2026 at 700. Affectsscripts/attendance.py.
2026-05-04 12:02 CEST — Go rewrite M1: skeleton + tooling
- Created
go/tree with modulefuj-management/go(Go 1.26). cmd/fuj: stdlib-flag subcommand dispatcher;serverandversionimplemented, stubs for M2/M4 commands.internal/config: env loader mirroringscripts/config.py(same env var names and defaults).internal/logging: slog setup accepting log level from config.internal/web:net/httpServeMux on:8080;middleware/timer.gologs method/path/status/ms.go/build/Dockerfile: multi-stage (golang:1.26→alpine:3) producing a static binary image.- Makefile:
web→web-pyalias; addedweb-go,go-build,go-test,go-run,go-lint. .gitea/workflows/build.yaml: parallelbuild-gojob pushing<tag>-goimage.- Gate:
make go-build,make go-lint,make go-test,curl :8080all 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 fromreconcile(). - 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()andjuniors_view()inapp.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 Amountstill holds the full bank amount. - Files: scripts/match_payments.py, tests/test_reconcile_exceptions.py (6 new test cases).