Partner verteilen gedruckte QR-Codes (Sticker/Flyer); jeder physische Code
ist einzeln rückverfolgbar von Scan bis Registrierung.
Backend:
- partner_qr_batches + partner_qr_codes (Token 8-stellig, ohne 0/O/1/l/I),
users.referred_qr, partner_codes.owner_user_id (+Backfill über referred_by)
- /q/{token}: Scan zählen (scans, first/last_scan_at) → Redirect
/?ref=CODE&qr=TOKEN — dockt am bestehenden Referral-Flow an
- Registrierung: qr_token wird nur zugeordnet, wenn er zum eingelösten
Partner-Code gehört (Manipulationsschutz)
- Admin: Kontingent bestellen (max 500), Liste mit Scans/Registrierungen,
Löschen (Zweiklick), druckfertiges A4-PDF (segno+fpdf2, 3×4 Grid mit
Kurz-URL + laufender Nummer), Code-Besitzer zuordnen
- Partner-Self-Service: /partner/my-qr (+PDF) für Code-Besitzer
Frontend:
- Admin-Partner-Tab: Karte 'QR-Kontingente' (Bestellung, Stats, PDF, Besitzer)
- Partner-Profil: 'Meine QR-Codes' mit Scans/Registrierungen + PDF-Download
- boot.js/app.js speichern ?qr=, Registrierung schickt qr_token mit
Neu: segno==1.6.6 (pure-python QR). Tests: 5 neue (PDF, Scan-Zählung,
Attribution, Fremd-Token-Schutz, Self-Service). Suite: 51 passed.
20 lines
355 B
Text
20 lines
355 B
Text
fastapi==0.115.0
|
|
Pillow==11.2.1
|
|
pillow-heif==0.22.0
|
|
uvicorn[standard]==0.34.0
|
|
python-multipart==0.0.20
|
|
pydantic[email]==2.10.6
|
|
bcrypt==4.3.0
|
|
PyJWT==2.10.1
|
|
httpx==0.28.1
|
|
cryptography==44.0.0
|
|
openai==1.59.2
|
|
anthropic==0.49.0
|
|
pywebpush==2.0.0
|
|
apscheduler==3.10.4
|
|
odfpy==1.4.1
|
|
polyline==2.0.2
|
|
fpdf2==2.8.3
|
|
segno==1.6.6
|
|
python-dateutil>=2.9
|
|
brotli-asgi==1.4.0
|