The club page now leads with its own numbers that should be zero, then the health signals underneath. - Teams with no coach. Not a statistic but a defect in the club's setup: with nobody in a management position the access service grants no authority over that team, so nobody can pick the squad. A physio does not count -- the query keys on Position.management_position, and on this season only. - Unrostered members: active, paid, and on no team. - Unpaid money bucketed by age. "€250 overdue past 60 days" drives a phone call; "€250 outstanding" does not. - Renewal rate -- last season's actives who signed up again. Exactly computable because memberships are season-scoped. - Turnout, plus the share who never responded. Silence is not an absence, so it is excluded from turnout and reported separately: no-response is the leading indicator, since it measures whether members use the app at all. Two of these return None rather than a number, deliberately: a club in its first season has not failed to renew anyone, and a season with no past events has no turnout. Rendering either as 0% would libel the club, so the page says why instead. Money is pinned to two decimals -- SQLite's Sum() drops trailing zeros, so an aggregate rendered "€250" next to a "€0.00" constant on the same card. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
10 KiB
10 KiB