Add referee assignment/eligibility system, team bulk-add, member Groups, and referee management dashboard with PDF export

Builds the referee workflow end to end: club-defined RefereeLevel/RefereeProfile
eligibility tied to teams, EventReferee assignment (member or external, with
fee/km payment tracking), an admin dashboard with KPI tiles, date-grouped game
tiles and range filters, and a downloadable payment form PDF modeled on the
club's existing paper document (using Club.legal_name when set). Also lands
team roster bulk-add, member mass-upload with family linking, and the
members.Group model, developed alongside this work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-09 21:39:19 +02:00
parent 86e28c317f
commit 309bd4d83e
54 changed files with 4574 additions and 88 deletions

View File

@@ -27,20 +27,22 @@
{% for authenticator in authenticators %}
{% element tr %}
{% element td %}
{{ authenticator }}
{% if authenticator.wrap.is_passwordless is True %}
{% element badge tags="mfa,key,primary" %}
{% translate "Passkey" %}
{% endelement %}
{% elif authenticator.wrap.is_passwordless is False %}
{% element badge tags="mfa,key,secondary" %}
{% translate "Security key" %}
{% endelement %}
{% else %}
{% element badge title=_("This key does not indicate whether it is a passkey.") tags="mfa,key,warning" %}
{% translate "Unspecified" %}
{% endelement %}
{% endif %}
<div class="flex items-center gap-2">
{{ authenticator }}
{% if authenticator.wrap.is_passwordless is True %}
{% element badge tags="mfa,key,primary" %}
{% translate "Passkey" %}
{% endelement %}
{% elif authenticator.wrap.is_passwordless is False %}
{% element badge tags="mfa,key,secondary" %}
{% translate "Security key" %}
{% endelement %}
{% else %}
{% element badge title=_("This key does not indicate whether it is a passkey.") tags="mfa,key,warning" %}
{% translate "Unspecified" %}
{% endelement %}
{% endif %}
</div>
{% endelement %}
{% element td %}
{% blocktranslate with created_at=authenticator.created_at|date:"SHORT_DATE_FORMAT" %}Added on {{ created_at }}{% endblocktranslate %}.
@@ -51,14 +53,16 @@
{% endif %}
{% endelement %}
{% element td align="right" %}
{% url 'mfa_edit_webauthn' pk=authenticator.pk as edit_url %}
{% element button href=edit_url icon="pencil" tags="mfa,authenticator,edit,tool" %}
{% translate "Edit" %}
{% endelement %}
{% url 'mfa_remove_webauthn' pk=authenticator.pk as remove_url %}
{% element button href=remove_url icon="trash-2" tags="mfa,authenticator,danger,delete,tool" %}
{% translate "Remove" %}
{% endelement %}
<div class="flex items-center justify-end gap-2">
{% url 'mfa_edit_webauthn' pk=authenticator.pk as edit_url %}
{% element button href=edit_url icon="pencil" tags="mfa,authenticator,edit,tool" %}
{% translate "Edit" %}
{% endelement %}
{% url 'mfa_remove_webauthn' pk=authenticator.pk as remove_url %}
{% element button href=remove_url icon="trash-2" tags="mfa,authenticator,danger,delete,tool" %}
{% translate "Remove" %}
{% endelement %}
</div>
{% endelement %}
{% endelement %}
{% endfor %}