diff --git a/backend/main.py b/backend/main.py index d1430df..c7316a4 100644 --- a/backend/main.py +++ b/backend/main.py @@ -408,7 +408,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "979" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "980" # 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 86abd4b..0ff5241 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -1275,12 +1275,13 @@ async def fulfill_upgrade_request(req_id: int, user=Depends(require_admin)): logging.getLogger(__name__).warning(f"Bestätigungsmail fehlgeschlagen: {e}") # Offene Rechnungen (sent/draft) des alten Tiers stornieren + neuen Entwurf anlegen + inv_number = None try: - await _handle_upgrade_invoices(req, tier_label) + inv_number = await _handle_upgrade_invoices(req, tier_label) except Exception as e: logger.warning(f"Upgrade-Rechnungslogik fehlgeschlagen für {req['name']}: {e}") - return {"ok": True, "tier": req["tier"], "user": req["name"]} + return {"ok": True, "tier": req["tier"], "user": req["name"], "invoice_number": inv_number} def _get_discount_info(conn, user_id: int) -> dict: @@ -1379,6 +1380,7 @@ async def _handle_upgrade_invoices(req: dict, new_tier_label: str): ) logger.info(f"Neuer Rechnungsentwurf {inv_number} für {req['email']} nach Upgrade auf {new_tier_label}") + return inv_number # ------------------------------------------------------------------ diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 91f4a6d..8c8ee55 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 = '979'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '980'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← 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/js/pages/admin.js b/backend/static/js/pages/admin.js index a3b2b91..a02e1e1 100644 --- a/backend/static/js/pages/admin.js +++ b/backend/static/js/pages/admin.js @@ -3610,7 +3610,7 @@ window.Page_admin = (() => { const tierLabel = { pro: 'Pro', breeder: 'Züchter' }[tier] || tier; const ok = await UI.modal.confirm({ title: `${name} auf ${tierLabel} freischalten?`, - message: `Der Account wird auf ${tierLabel} gesetzt und eine Bestätigungsmail gesendet.`, + message: `Der Account wird auf ${tierLabel} gesetzt und eine Bestätigungsmail gesendet.\n\nFalls noch keine Rechnung gesendet wurde, wird ein Entwurf automatisch angelegt.`, confirmText: 'Freischalten', danger: false, }); @@ -3619,7 +3619,14 @@ window.Page_admin = (() => { btn.textContent = '…'; try { const res = await API.post(`/admin/upgrade-requests/${id}/fulfill`); - UI.toast.success(`${res.user} wurde auf ${tierLabel} freigeschaltet.`); + if (res.invoice_number) { + UI.toast.success( + `${res.user} freigeschaltet · Entwurf ${res.invoice_number} unter Rechnungen versenden`, + 6000 + ); + } else { + UI.toast.success(`${res.user} wurde auf ${tierLabel} freigeschaltet.`); + } _renderTab(); _renderActionItems(); } catch (e) { diff --git a/backend/static/sw.js b/backend/static/sw.js index da47cbd..76366b9 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-v979'; +const CACHE_VERSION = 'by-v980'; 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