diff --git a/backend/main.py b/backend/main.py index 3ce196a..482806f 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 = "941" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "940" # 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 09ab0b8..b8cfb40 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -1150,87 +1150,19 @@ 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""" - - -
- - -
{title}
-
{desc}
- - """ - - feature_rows = "".join(_feature_row(i, t, d) for i, t, d in features) - try: from mailer import send_email, email_html - import html as _html - name_esc = _html.escape(req["name"]) body_html = f""" -

- Herzlichen Glückwunsch, {name_esc}! 🎉 -

-

- Dein Account wurde soeben auf {tier_label} - freigeschaltet. Vielen Dank für dein Vertrauen in Ban Yaro! -

- -
-
Dein Tarif
-
{tier_label} - {tier_price} -
-
- -
Deine neuen Features
- - {feature_rows} -
- -
- So aktivierst du deine Features:
- Öffne Ban Yaro und lade die App einmal neu (Startseite antippen → herunterziehen - oder App schließen und neu öffnen). Alle Features sind dann sofort verfügbar. -
""" - - html = email_html(body_html, cta_url="https://banyaro.app", cta_label="Ban Yaro jetzt öffnen") - plain = (f"Herzlichen Glückwunsch, {req['name']}!\n\n" - f"Dein Account wurde auf {tier_label} ({tier_price}) freigeschaltet.\n\n" - f"Öffne Ban Yaro und lade die App neu — alle Features sind dann aktiv.\n\n" - f"Viele Grüße\nRené & das Ban Yaro Team") - await send_email(req["email"], f"🎉 Dein {tier_label}-Zugang ist aktiv!", html, plain) +

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

""" + html = email_html(body_html, cta_url="https://banyaro.app", cta_label="Ban Yaro öffnen") + plain = (f"Hallo {req['name']},\n\ndein Account wurde auf {tier_label} freigeschaltet.\n" + f"Öffne Ban Yaro und lade die App neu.\n\nViele Grüße\nRené") + await send_email(req["email"], f"Dein {tier_label}-Zugang ist aktiv", html, plain) except Exception as e: import logging logging.getLogger(__name__).warning(f"Bestätigungsmail fehlgeschlagen: {e}") diff --git a/backend/static/js/app.js b/backend/static/js/app.js index d585465..12d4361 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '941'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '940'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 6803ce0..8241dc5 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v941'; +const CACHE_VERSION = 'by-v940'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache