Split platform signups, and rework the club table into health

The platform signups chart gets the same stacked new/returning split as the club
one. "First season" is keyed on (club, member), never the member alone: the same
person can be new at one club while renewing at another, and collapsing that would
file their second club's very first signup as a renewal.

The dashboard's club table stops reporting vanity counts. A member total says
nothing you can act on; "no coach", "nothing scheduled", "€ owed" and "no admins"
each name something somebody has to go and fix. Columns are now active members,
unpaid members, money owed, teams (flagging those nobody can pick a squad for),
upcoming events, and admins -- with No season / Dormant badges on the club itself.

Every column is annotated in ONE query, each aggregate in its own subquery. That
is not stylistic: aggregates spanning different joins multiply each other's rows,
so a Sum of orders sitting next to a Count of memberships returns the club's debt
multiplied by its membership count. A test pins €100 against three memberships and
would catch it coming back as €300.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 01:17:26 +02:00
parent 639807b2d2
commit 192fe5ad0e
5 changed files with 203 additions and 31 deletions

View File

@@ -2945,6 +2945,9 @@
.mb-10 {
margin-bottom: calc(var(--spacing) * 10);
}
.ml-1 {
margin-left: var(--spacing);
}
.ml-2 {
margin-left: calc(var(--spacing) * 2);
}
@@ -3602,6 +3605,12 @@
font-size: 0.75rem;
}
}
.badge-xs {
@layer daisyui.l1.l2 {
--size: calc(var(--size-selector, 0.25rem) * 4);
font-size: 0.625rem;
}
}
.otp-lg {
@layer daisyui.l1.l2 {
font-size: 2rem;