QR-Stats: Registrierungen (bestätigt) vs. Versuche (unbestätigt) + Account-Detail-Liste
Rene: Statistik zählte alles in einen Topf (3 statt 2) und zeigte nicht, WER sich registriert hat. Jetzt: - registrations = email_verified=1, attempts = unbestätigte Versuche — Versuche werden bei späterer Bestätigung automatisch zu Registrierungen - Admin: 👥-Button pro Kontingent klappt Account-Liste auf (Name, E-Mail, Datum, ✓ bestätigt/⏳ Versuch, Sticker-Nr #seq) — lazy geladen, admin-only (personenbezogene Daten); Partner sehen weiter nur Zahlen (Registr. +N) - Test deckt Versuch→Bestätigung-Übergang und Detail-Endpoint ab
This commit is contained in:
parent
f604ab7c4f
commit
970480c1d6
9 changed files with 110 additions and 26 deletions
|
|
@ -575,13 +575,17 @@ def _qr_new_token(conn) -> str:
|
|||
|
||||
|
||||
def _qr_batch_stats(conn, batch_id: int) -> dict:
|
||||
"""Registrierungen = E-Mail bestätigt; Versuche = registriert, aber (noch) unbestätigt."""
|
||||
row = conn.execute(
|
||||
"""SELECT COUNT(*) AS codes, COALESCE(SUM(q.scans),0) AS scans,
|
||||
(SELECT COUNT(*) FROM users u
|
||||
JOIN partner_qr_codes q2 ON q2.token = u.referred_qr
|
||||
WHERE q2.batch_id = ?) AS registrations
|
||||
WHERE q2.batch_id = ? AND u.email_verified = 1) AS registrations,
|
||||
(SELECT COUNT(*) FROM users u
|
||||
JOIN partner_qr_codes q2 ON q2.token = u.referred_qr
|
||||
WHERE q2.batch_id = ? AND u.email_verified = 0) AS attempts
|
||||
FROM partner_qr_codes q WHERE q.batch_id = ?""",
|
||||
(batch_id, batch_id)
|
||||
(batch_id, batch_id, batch_id)
|
||||
).fetchone()
|
||||
return dict(row)
|
||||
|
||||
|
|
@ -713,6 +717,27 @@ def delete_qr_batch(batch_id: int, user=Depends(require_admin)):
|
|||
return None
|
||||
|
||||
|
||||
@router.get("/admin/partner/qr-batches/{batch_id}/registrations")
|
||||
def qr_batch_registrations(batch_id: int, user=Depends(require_admin)):
|
||||
"""Accounts, die über dieses Kontingent kamen — inkl. unbestätigter Versuche.
|
||||
Admin-only (personenbezogene Daten)."""
|
||||
with db() as conn:
|
||||
if not conn.execute(
|
||||
"SELECT id FROM partner_qr_batches WHERE id=?", (batch_id,)
|
||||
).fetchone():
|
||||
raise HTTPException(404, "Kontingent nicht gefunden.")
|
||||
rows = conn.execute(
|
||||
"""SELECT u.id, u.name, u.email, u.email_verified, u.created_at,
|
||||
q.seq, q.token
|
||||
FROM users u
|
||||
JOIN partner_qr_codes q ON q.token = u.referred_qr
|
||||
WHERE q.batch_id = ?
|
||||
ORDER BY u.created_at DESC""",
|
||||
(batch_id,)
|
||||
).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
|
||||
@router.get("/admin/partner/qr-batches/{batch_id}/pdf")
|
||||
def qr_batch_pdf_admin(batch_id: int, user=Depends(require_admin)):
|
||||
from fastapi.responses import Response
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue