diff --git a/backend/database.py b/backend/database.py index 2c37d10..5c5516a 100644 --- a/backend/database.py +++ b/backend/database.py @@ -2341,24 +2341,6 @@ def _migrate(conn_factory): except Exception: pass - # upgrade_requests: Abo-Upgrade-Anfragen von Nutzern - try: - conn.execute(""" - CREATE TABLE IF NOT EXISTS upgrade_requests ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, - tier TEXT NOT NULL, - message TEXT, - created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), - fulfilled_at TEXT, - fulfilled_by INTEGER REFERENCES users(id) - ) - """) - conn.execute("CREATE INDEX IF NOT EXISTS idx_upgrade_req_pending ON upgrade_requests(fulfilled_at, created_at DESC)") - logger.info("Migration: upgrade_requests bereit.") - except Exception as e: - logger.warning(f"Migration upgrade_requests: {e}") - # route_dogs: bestehende Routen allen Hunden des Users zuweisen try: existing = conn.execute("SELECT COUNT(*) FROM route_dogs").fetchone()[0] diff --git a/backend/main.py b/backend/main.py index 9f5a2c4..097edd7 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 = "921" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "918" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): @@ -465,11 +465,10 @@ async def sitemap(): today = date.today().isoformat() urls = [ ("https://banyaro.app/", "weekly", "1.0"), - ("https://banyaro.app/zuechter", "weekly", "0.9"), - ("https://banyaro.app/info", "monthly", "0.8"), - ("https://banyaro.app/presse", "monthly", "0.7"), + ("https://banyaro.app/info", "monthly", "0.9"), + ("https://banyaro.app/presse", "monthly", "0.8"), ("https://banyaro.app/wiki/rassen", "weekly", "0.8"), - ("https://banyaro.app/knigge", "monthly", "0.7"), + ("https://banyaro.app/knigge", "monthly", "0.8"), ("https://banyaro.app/wurfboerse", "daily", "0.8"), ] diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 19e93eb..92a199d 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -124,17 +124,13 @@ 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] return { - "jobs_pending": jobs, - "breeder_pending": breeders, - "reports_open": reports, - "fotos_pending": fotos, - "poi_edits_pending": poi_edits, - "users_today": users_today, - "upgrades_pending": upgrades_pending, + "jobs_pending": jobs, + "breeder_pending": breeders, + "reports_open": reports, + "fotos_pending": fotos, + "poi_edits_pending": poi_edits, + "users_today": users_today, } @@ -1095,66 +1091,3 @@ async def generate_media_previews(user=Depends(require_admin)): errors += 1 return {"generated": generated, "skipped": skipped, "errors": errors} - - -# ------------------------------------------------------------------ -# GET /api/admin/upgrade-requests — offene Upgrade-Anfragen -# POST /api/admin/upgrade-requests/{id}/fulfill — Tier setzen + Mail -# ------------------------------------------------------------------ -@router.get("/upgrade-requests") -async def list_upgrade_requests(user=Depends(require_admin)): - with db() as conn: - rows = conn.execute(""" - SELECT r.id, r.user_id, r.tier, r.message, r.created_at, r.fulfilled_at, - u.name, u.email - FROM upgrade_requests r - JOIN users u ON u.id = r.user_id - ORDER BY r.fulfilled_at IS NOT NULL, r.created_at DESC - LIMIT 100 - """).fetchall() - return [dict(r) for r in rows] - - -@router.post("/upgrade-requests/{req_id}/fulfill") -async def fulfill_upgrade_request(req_id: int, user=Depends(require_admin)): - with db() as conn: - req = conn.execute( - "SELECT r.*, u.name, u.email FROM upgrade_requests r JOIN users u ON u.id=r.user_id WHERE r.id=?", - (req_id,) - ).fetchone() - if not req: - raise HTTPException(404, "Anfrage nicht gefunden.") - if req["fulfilled_at"]: - raise HTTPException(400, "Bereits erledigt.") - if req["tier"] not in _VALID_TIERS: - raise HTTPException(400, "Ungültiger Tier.") - conn.execute( - "UPDATE users SET subscription_tier=? WHERE id=?", - (req["tier"], req["user_id"]) - ) - conn.execute( - "UPDATE upgrade_requests SET fulfilled_at=strftime('%Y-%m-%dT%H:%M:%fZ','now'), fulfilled_by=? WHERE id=?", - (user["id"], req_id) - ) - _audit(conn, user, "fulfill_upgrade", f"user:{req['user_id']}", f"tier={req['tier']}") - - tier_labels = {"pro": "Ban Yaro Pro", "breeder": "Züchter"} - tier_label = tier_labels.get(req["tier"], req["tier"]) - try: - from mailer import send_email, email_html - body_html = 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
| ${h} | ` - ).join('')} -|||||||
|---|---|---|---|---|---|---|---|
| Noch keine Züchter | |||||||
| - Keine offenen Anfragen - |
- Der Account wird auf ${tierLabel} gesetzt und - eine Bestätigungsmail gesendet. -
`, - confirmLabel: 'Freischalten', - danger: false, - }); - if (!ok) return; - btn.disabled = true; - btn.textContent = '…'; - try { - const res = await API.post(`/admin/upgrade-requests/${id}/fulfill`); - UI.toast.success(`${res.user} wurde auf ${tierLabel} freigeschaltet.`); - _renderTab(); - } catch (e) { - UI.toast.error(e.message); - btn.disabled = false; - btn.textContent = 'Freischalten'; - } - }); - }); - } - return { init, refresh, onDogChange }; })(); diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js index 96ee9f7..8767cc6 100644 --- a/backend/static/js/pages/settings.js +++ b/backend/static/js/pages/settings.js @@ -77,137 +77,6 @@ window.Page_settings = (() => { } } - // ---------------------------------------------------------- - // ABO & TARIF - // ---------------------------------------------------------- - function _tierCard(u) { - const tier = u.subscription_tier || 'standard'; - const rolle = u.rolle || 'user'; - const isAdmin = rolle === 'admin' || rolle === 'moderator'; - const isPro = ['pro','pro_test'].includes(tier); - const isBreeder = ['breeder','breeder_test'].includes(tier) || rolle === 'breeder'; - const isStandard = !isAdmin && !isPro && !isBreeder; - - const _badge = (label, color) => - `${label}`; - - const _upgradeBtn = (id, label, price, color) => - ``; - - let statusHtml = ''; - let actionsHtml = ''; - - if (isAdmin) { - statusHtml = _badge('Admin', '#6366f1'); - } else if (isBreeder) { - statusHtml = _badge('Züchter aktiv', '#C4843A'); - } else if (isPro) { - statusHtml = _badge('Pro aktiv', '#16a34a'); - actionsHtml = ` -