Files
fuj-management/CHANGELOG.md
Jan Novak 97f568f49f feat: Lower adult monthly fee to 700 CZK from April 2026
Pin Sep 2025 – Feb 2026 at 750 CZK in ADULT_FEE_MONTHLY_RATE so
historical billing is unchanged; new default 700 CZK applies to
2026-04 onward. March 2026 stays at 350.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 23:08:54 +02:00

39 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
## 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 `in` substring 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). Affects `scripts/match_payments.py`.
## 2026-05-04 23:08 CEST — feat: lower adult monthly fee to 700 CZK from April 2026
- `ADULT_FEE_DEFAULT` reduced from 750 → 700 CZK.
- `ADULT_FEE_MONTHLY_RATE` now pins Sep 2025 Feb 2026 at 750 to preserve historical billing; Mar 2026 stays 350; AprMay 2026 at 700. Affects `scripts/attendance.py`.
## 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 `<tag>-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).