diff --git a/backend/main.py b/backend/main.py index bed3d6f..d145e80 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "939" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "942" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 69dceeb..09ab0b8 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -124,9 +124,12 @@ async def action_items(user=Depends(require_mod)): users_today = conn.execute( "SELECT COUNT(*) FROM users WHERE DATE(created_at)=DATE('now')" ).fetchone()[0] - upgrades_pending = conn.execute( - "SELECT COUNT(*) FROM upgrade_requests WHERE fulfilled_at IS NULL" - ).fetchone()[0] + try: + upgrades_pending = conn.execute( + "SELECT COUNT(*) FROM upgrade_requests WHERE fulfilled_at IS NULL" + ).fetchone()[0] + except Exception: + upgrades_pending = 0 return { "jobs_pending": jobs, "breeder_pending": breeders, @@ -1147,19 +1150,87 @@ async def fulfill_upgrade_request(req_id: int, user=Depends(require_admin)): tier_labels = {"pro": "Ban Yaro Pro", "breeder": "Züchter"} tier_label = tier_labels.get(req["tier"], req["tier"]) + tier_price = {"pro": "29 €/Jahr", "breeder": "49 €/Jahr"}.get(req["tier"], "") + + _features_pro = [ + ("users", "Mehrere Hunde", "Bis zu 10 Hunde mit getrennten Trainings-, Gesundheits- und Ernährungsdaten"), + ("fork-knife", "Ernährung", "Kalorienbedarf-Rechner, BARF-Guide, vollständige Giftliste, KI-Ernährungsberater"), + ("paw-print", "Gassi-Treffen", "Hundefotos & Rasse der Teilnehmer sichtbar, Fotos hochladen und teilen"), + ("chat-circle-dots", "Direktnachrichten & Chat", "Schreibe direkt mit anderen Hundebesitzern"), + ("handshake", "Playdate", "Spielkameraden in der Nähe finden und verabreden"), + ("airplane", "Reise-Checkliste", "Editierbare Checkliste + EU-Länder-Einreiseregeln"), + ("note-pencil", "Notizblock mit KI", "KI erkennt Muster in deinen Notizen und macht Vorschläge"), + ("map-trifold", "Erweiterte Karten-Layer", "Regenradar, Temperatur-Layer und weitere Kartenmodi"), + ] + _features_breeder = [ + ("check-circle", "Alle Pro-Features inklusive", "Mehrere Hunde, Ernährung, Gassi-Community, Chat, Playdate, Reise, Karten"), + ("tree-structure", "Zuchtkartei", "Gesundheitstests (HD, ED, OCD, Augen, Herz, Patella, ZTP), Gentests (MDR1, PRA, DM, vWD), Titel"), + ("notebook", "Wurfverwaltung", "Würfe und Welpen verwalten, Gewichtsverlauf, Fotos, Kaufvertrag automatisch ausfüllen"), + ("list-bullets", "Warteliste", "Interessenten mit Präferenzen pro Zuchthündin verwalten"), + ("thermometer", "Läufigkeit & Trächtigkeit", "Zykluskalender, Progesterontests, Deckdaten, automatische Meilensteinberechnung"), + ("graph", "Stammbaum & IK-Rechner", "Stammbaum bis 4 Generationen, Inzuchtkoeffizient nach Wright, Probeverpaarung"), + ("sparkle", "KI-Züchter-Assistent", "Wurfankündigungen schreiben, Genetik-Erklärung, Paarungsanalyse, Jahresbericht"), + ("globe", "Öffentliches Züchter-Profil", "Visitenkarte unter banyaro.app/breeder/{zwingername} mit Hunden, Fotos und Gesundheitsstatistik"), + ("download-simple", "Datenexport", "Vollständiger Export als HTML-Dossier und ODS-Tabelle (LibreOffice/Excel)"), + ] + + features = _features_breeder if req["tier"] == "breeder" else _features_pro + + def _feature_row(icon, title, desc): + return f""" +
Hallo {req['name']},
-dein Account wurde soeben auf {tier_label} freigeschaltet.
-Du kannst alle {tier_label}-Features ab sofort in der App nutzen. - Öffne Ban Yaro und lade die App einmal neu — dann ist dein neuer Tarif aktiv.
-Vielen Dank für dein Vertrauen!
-Viele Grüße
René & das Ban Yaro Team
+ Herzlichen Glückwunsch, {name_esc}! 🎉 +
++ Dein Account wurde soeben auf {tier_label} + freigeschaltet. Vielen Dank für dein Vertrauen in Ban Yaro! +
+ +| - Keine offenen Anfragen - |
| ${h} | ` + ).join('')} +
|---|