Checkpoint: management app redesign, onboarding/signup workflow, and events calendar backend

Large uncommitted body of work accumulated across sessions on this branch --
committing as a checkpoint so it's tracked and future worktree-isolated agents
see the real codebase instead of a stale ancestor commit. Covers the
management app's dedicated Tailwind theme and templates, the club onboarding
requirement/signup workflow (club/services/onboarding.py, requirement/status
models, sign-up dashboard), fee/status auto-activation decoupling, referee
management, and the new events calendar grid service layer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
2026-08-19 23:34:43 +02:00
parent bff685966d
commit adf1120358
157 changed files with 20342 additions and 4008 deletions

View File

@@ -0,0 +1,51 @@
"""Read side of the scheduled-job history for the control panel's Jobs tab and the
Platform dashboard's job log / failed-jobs tile.
``features.jobs.JOB_REGISTRY`` is what a job *is* (label, description, schedule);
``features.models.JobRun`` is what actually happened, written by the Celery signal handlers
in features/signals.py. This module just joins the two for a template.
"""
from datetime import timedelta
from django.utils import timezone
from features.jobs import JOB_REGISTRY
from features.models import JobRun
#: Runs shown per job on the Jobs tab -- enough to see a pattern (a job that fails every
#: third day, say) without the page turning into a full audit log.
RECENT_RUNS = 10
#: What counts as "recent" for the dashboard's failed-jobs KPI tile.
FAILURE_WINDOW_HOURS = 24
#: Rows in the Platform dashboard's job log card.
JOB_LOG_ROWS = 8
def job_overview():
"""One entry per registered job, its most recent runs, and a shortcut to the latest."""
return [
{
"name": name,
"label": meta["label"],
"description": meta["description"],
"schedule": meta["schedule"],
"runs": (runs := list(JobRun.objects.filter(name=name)[:RECENT_RUNS])),
"latest": runs[0] if runs else None,
}
for name, meta in JOB_REGISTRY.items()
]
def recent_job_failures(hours=FAILURE_WINDOW_HOURS):
"""Failures in the last `hours` -- the platform-health "failed jobs" signal. A number
that sits here is exactly what a dead beat schedule or a broken task looks like."""
since = timezone.now() - timedelta(hours=hours)
return JobRun.objects.filter(status=JobRun.Status.FAILURE, started_at__gte=since)
def recent_job_runs(limit=JOB_LOG_ROWS):
"""Every job's runs, most recent first, for the dashboard's Job log card."""
return JobRun.objects.all()[:limit]