Feature: Dank-Mail an Partner bei bestätigter Registrierung — mit Statistik
Trigger ist die E-Mail-Bestätigung des Geworbenen (nicht die rohe Registrierung — konsistent zur Registrierungen/Versuche-Zählung) und nur beim ersten Verify (Doppelklick auf den Link = keine zweite Mail). Inhalt: Dank + Bilanz (bestätigte Registrierungen gesamt + diesen Monat), bei QR-Herkunft der Sticker (#seq, Kontingent-Label), bei Gründer-Codes die offenen Plätze; CTA zur Partner-Statistik. Versand über das partner@-Konto, Fehler landen in failed_emails (context partner_thank_you). Env-Fund dabei: SMTP_PASS fehlte in BEIDEN .env (nur SMTP_SUPPORT_PASS da) — Partner-Konto-Versand wäre fehlgeschlagen; auf der DS ergänzt. Test: Mail-Capture per monkeypatch, prüft Statistik + Sticker-Nr + Einmaligkeit. Suite grün.
This commit is contained in:
parent
df2f42f8ac
commit
3d7d5dc1c4
7 changed files with 144 additions and 16 deletions
|
|
@ -397,6 +397,85 @@ async def me(user=Depends(get_current_user)):
|
|||
return data
|
||||
|
||||
|
||||
def _notify_partner_registration(user_id: int):
|
||||
"""Dank-Mail an den Partner (Code-Besitzer), wenn ein Geworbener seine
|
||||
E-Mail bestätigt hat — inkl. kleiner Statistik. Best effort."""
|
||||
import html as _html
|
||||
with db() as conn:
|
||||
u = conn.execute(
|
||||
"SELECT referred_by, referred_qr FROM users WHERE id=?", (user_id,)
|
||||
).fetchone()
|
||||
if not u or (u["referred_by"] or 0) >= 0:
|
||||
return # kein Partner-Code im Spiel
|
||||
code_id = -u["referred_by"]
|
||||
pc = conn.execute(
|
||||
"""SELECT pc.code, pc.label, pc.grants_founder, pc.owner_user_id,
|
||||
o.name AS owner_name, o.email AS owner_email
|
||||
FROM partner_codes pc
|
||||
LEFT JOIN users o ON o.id = pc.owner_user_id
|
||||
WHERE pc.id=?""",
|
||||
(code_id,)
|
||||
).fetchone()
|
||||
if not pc or not pc["owner_email"]:
|
||||
return # Code ohne Besitzer → niemand zu benachrichtigen
|
||||
total = conn.execute(
|
||||
"SELECT COUNT(*) FROM users WHERE referred_by=? AND email_verified=1",
|
||||
(-code_id,)
|
||||
).fetchone()[0]
|
||||
month = conn.execute(
|
||||
"""SELECT COUNT(*) FROM users
|
||||
WHERE referred_by=? AND email_verified=1
|
||||
AND strftime('%Y-%m', created_at) = strftime('%Y-%m', 'now')""",
|
||||
(-code_id,)
|
||||
).fetchone()[0]
|
||||
qr_line = ""
|
||||
if u["referred_qr"]:
|
||||
qr = conn.execute(
|
||||
"""SELECT q.seq, b.label FROM partner_qr_codes q
|
||||
JOIN partner_qr_batches b ON b.id = q.batch_id
|
||||
WHERE q.token=?""",
|
||||
(u["referred_qr"],)
|
||||
).fetchone()
|
||||
if qr:
|
||||
qr_line = f"Gekommen über deinen gedruckten QR-Code #{qr['seq']} (Kontingent „{qr['label']}“)."
|
||||
founder_line = ""
|
||||
if pc["grants_founder"]:
|
||||
founders = conn.execute(
|
||||
"SELECT COUNT(*) FROM users WHERE is_founder=1"
|
||||
).fetchone()[0]
|
||||
founder_line = f"Noch {max(0, 100 - founders)} von 100 Gründer-Plätzen frei."
|
||||
|
||||
subject = "🐾 Danke! Neue Registrierung über deinen Partner-Code"
|
||||
_oname = _html.escape(pc["owner_name"] or "Partner")
|
||||
stats_html = (
|
||||
f"<p style='margin:0 0 16px'>Deine Bilanz mit dem Code <b>{pc['code']}</b>:<br>"
|
||||
f"<b>{total}</b> bestätigte Registrierung{'en' if total != 1 else ''} insgesamt · "
|
||||
f"<b>{month}</b> in diesem Monat.</p>"
|
||||
)
|
||||
body_html = f"""
|
||||
<p style="margin:0 0 16px">Hallo <b>{_oname}</b>,</p>
|
||||
<p style="margin:0 0 16px">
|
||||
gerade hat ein neuer Hundefreund seine Registrierung über deinen
|
||||
Partner-Code bestätigt — danke, dass du Ban Yaro weiterträgst! 🎉
|
||||
</p>
|
||||
{f'<p style="margin:0 0 16px">{_html.escape(qr_line)}</p>' if qr_line else ''}
|
||||
{stats_html}
|
||||
{f'<p style="margin:0 0 16px;color:#888">{_html.escape(founder_line)}</p>' if founder_line else ''}"""
|
||||
plain = (f"Hallo {pc['owner_name'] or 'Partner'},\n\n"
|
||||
f"gerade hat ein neuer Hundefreund seine Registrierung über deinen Partner-Code bestätigt — danke!\n"
|
||||
+ (f"\n{qr_line}\n" if qr_line else "")
|
||||
+ f"\nDeine Bilanz mit dem Code {pc['code']}: {total} bestätigte Registrierungen insgesamt, {month} in diesem Monat.\n"
|
||||
+ (f"{founder_line}\n" if founder_line else "")
|
||||
+ f"\nDeine Statistik: {_APP_URL}/#partner-profil\n")
|
||||
try:
|
||||
from routes.outreach import _send_smtp
|
||||
from mailer import email_html
|
||||
html = email_html(body_html, cta_url=f"{_APP_URL}/#partner-profil", cta_label="Meine Partner-Statistik")
|
||||
_send_smtp(pc["owner_email"], subject, plain, "partner", html=html)
|
||||
except Exception as exc:
|
||||
_log_smtp_failure(pc["owner_email"], subject, plain, exc, context="partner_thank_you")
|
||||
|
||||
|
||||
@router.get("/verify-email/{token}")
|
||||
async def verify_email(token: str):
|
||||
with db() as conn:
|
||||
|
|
@ -409,6 +488,9 @@ async def verify_email(token: str):
|
|||
"UPDATE users SET email_verified=1, verification_token=NULL WHERE id=?",
|
||||
(row["id"],)
|
||||
)
|
||||
# Dank-Mail an den Partner — nur beim ERSTEN Bestätigen (Link doppelt geklickt = kein Spam)
|
||||
if not row["email_verified"]:
|
||||
_notify_partner_registration(row["id"])
|
||||
return RedirectResponse(f"{_APP_URL}/#settings?verified=1", status_code=302)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue