wiki/c-work/4-done/2026-05-enterprise-subscription.md
2026-06-02 09:42:12 +02:00

6.5 KiB

Enterprise Subscription

Beschreibung und Kontext

Enterprise-Kunden wollen mit Pauschalen arbeiten statt mit nutzungsbasierter Stripe-Abrechnung. Der Sysadmin (Platform Admin) erstellt ein individuelles Abo mit fixen Limiten (Users, Features, Storage, AI-Budget) und einem Pauschalpreis. Die Abrechnung erfolgt per E-Mail-Rechnung, nicht über Stripe. Alle Limiten sind hart — Überschreitung wird blockiert, nicht nachverrechnet.

Business-Treiber: Grosse Kunden verlangen Planbarkeit und interne Verrechnung statt Kreditkarten-Abrechnung.

Fokus und kritische Details

  • assertCapacity muss bei Enterprise die Custom-Felder statt den Plan-Katalog lesen
  • creditSubscriptionBudget, adjustAiBudgetForUserChange, reconcileMandateStorageBilling brauchen Enterprise-Guards
  • AI-Budget Top-Up via Stripe bleibt für Enterprise-Mandanten weiterhin möglich (separater Flow)
  • syncQuantityToStripe ist bereits sicher (Guard auf stripeSubscriptionId=None)
  • SubscriptionCapacityException.userAction darf bei Enterprise nicht UPGRADE_SUBSCRIPTION sein

Ziel und Nicht-Ziele

  • Ziel: Sysadmin kann Enterprise-Abo erstellen, erneuern, anpassen; fixe Limiten mit Hard-Block; Rechnung per E-Mail an Mandate Admins
  • Ziel: Auto-Renewal via Cron-Job (eventManager) für Enterprise-Abos mit autoRenew=True
  • Ziel: Mandate Admin sieht Enterprise-Abo readonly im Dashboard
  • Explizit NICHT: PDF-Invoice-System, Frontend Enterprise-Formular (Phase 2)
  • Explizit NICHT: Enterprise als Self-Service für Mandate Admin

Betroffene Module

  • Gateway: datamodelSubscription, interfaceDbSubscription, interfaceDbBilling, interfaceDbApp, mainServiceSubscription, routeSubscription, routeBilling, enterpriseRenewalScheduler (neu), app.py
  • Frontend: Subscription-Status-Anzeige (readonly für Enterprise), Sysadmin-Panel Enterprise-Badge
  • DB-Migration: nein (neue Felder auf MandateSubscription, auto-schema)
  • Andere Komponenten: E-Mail-Versand (notifyMandateAdmins, bestehende Logik)

Entscheidungen

Datum Entscheidung Begründung
2026-05-09 Custom-Werte auf MandateSubscription statt eigene Plan-Tabelle Einfacher, kein neues DB-Schema nötig, Plan-Katalog bleibt statisch
2026-05-09 Rechnung als strukturierte E-Mail, kein PDF Vertrag wird extern geregelt, E-Mail reicht als Bestätigung
2026-05-09 Renew = altes Abo EXPIRED + neues ACTIVE (Duplikat) Saubere Audit-History, Budget-Gutschrift wie bei Erstaktivierung
2026-05-09 Auto-Renewal via eventManager.registerCron (täglich 06:00 UTC) Bestehende APScheduler-Infrastruktur nutzen, analog Audit-Log-Cleanup
2026-05-09 Rechnungs-E-Mail nur an Mandate Admins Gleiche Logik wie bestehende Pläne, kein Sysadmin als Empfänger
2026-05-09 Storage-Overage bei Enterprise: Hard-Block statt Pool-Abzug Konsistent mit dem Pauschalen-Konzept

Umsetzungs-Checkliste

  • Datenmodell: ENTERPRISE in BUILTIN_PLANS + enterprise*-Felder auf MandateSubscription (isEnterprise, enterpriseFlatPriceCHF, enterpriseMaxUsers, enterpriseMaxFeatureInstances, enterpriseMaxDataVolumeMB, enterpriseBudgetAiCHF, enterpriseNote)
  • Helper: getEffectiveLimits(sub, plan) in datamodelSubscription.py — liest bei isEnterprise die Custom-Felder
  • Guard: assertCapacity → über getEffectiveLimits abgedeckt (Enterprise-Felder automatisch)
  • Guard: creditSubscriptionBudget → Enterprise-Budget-Gutschrift
  • Guard: adjustAiBudgetForUserChange → bei Enterprise übersprungen
  • Guard: reconcileMandateStorageBilling → bei Enterprise übersprungen
  • Guard: getDataVolumeWarning → Enterprise-Felder
  • Guard: SubscriptionCapacityExceptionuserAction=CONTACT_ADMIN bei Enterprise
  • Service: createEnterprise, renewEnterprise, updateEnterprise in mainServiceSubscription.py
  • E-Mail: _buildEnterpriseInvoiceHtml + _sendEnterpriseInvoiceEmail via notifyMandateAdmins
  • Auto-Renewal: enterpriseRenewalScheduler.py via eventManager.registerCron (täglich 06:00 UTC)
  • Routes: POST enterprise/create, POST enterprise/renew, PUT enterprise/update in routeSubscription.py
  • Admin-View: _buildEnrichedSubscriptions + _computeUsage für Enterprise
  • RBAC / Permissions: alle 3 Endpoints isPlatformAdmin-only
  • Neutralisierung betroffen? Nein
  • Billing-Impact? Ja — neue Abrechnungsform

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given Sysadmin, When POST enterprise/create mit validen Parametern, Then Enterprise-Abo ACTIVE mit Custom-Limiten + AI-Budget gutgeschrieben + Rechnung per E-Mail an Mandate Admins + Sysadmin must
2 Given Enterprise-Abo aktiv, When Mandate Admin User 21 hinzufügen will (Limit=20), Then Hard-Block mit Meldung "Enterprise-Limit erreicht, kontaktieren Sie den Administrator" must
3 Given Enterprise-Abo aktiv, When User hinzugefügt wird (unter Limit), Then KEIN pro-rata AI-Budget-Adjustment must
4 Given Enterprise-Abo aktiv, When Storage-Nutzung steigt über Limit, Then Hard-Block, KEIN Pool-Abzug must
5 Given Enterprise-Abo aktiv, When Mandate Admin AI-Budget Top-Up via Stripe macht, Then funktioniert wie bei normalem Abo must
6 Given Enterprise-Abo aktiv, When Sysadmin PUT enterprise/update mit neuen Limiten, Then Limiten sofort wirksam must
7 Given Enterprise-Abo aktiv, When Sysadmin POST enterprise/renew, Then altes Abo EXPIRED + neues ACTIVE + Budget + Rechnung must
8 Given Enterprise-Abo aktiv, When Mandate Admin GET /status, Then sieht Enterprise-Abo mit Limiten und Nutzung (readonly) must
9 Given Enterprise-Abo aktiv, When Mandate Admin versucht Plan zu wechseln, Then nicht möglich (kein Self-Service) must

Testplan

ID AC Art Automatisiert Repo-Pfad Status
T1 1 api manuell done
T2 2 api manuell done
T3 3 api manuell done
T4 4 api manuell done
T5 5 api manuell done
T6 6 api manuell done
T7 7 api manuell done
T8 8,9 api manuell done
  • Cursor Plan: enterprise_subscription_aca22e32.plan.md

Abschluss

  • Dieses Dokument Status → done (2026-05-15)
  • Eintrag in c-work/_CHANGELOG.md