Files
kaffeekasse-saas/docs/billing.md
T
clemensandClaude Sonnet 5 ade1fd0ed9 Billing Phase 1: Tarifstatus-Datenmodell und Tariflogik je Mandant
Vorbereitung fuer Stripe Billing (Zahlungseinzug) + bestehendes Dolibarr
des Kunden (Rechnungsstellung/Buchhaltung) statt eines eigenen Rechnungs-
systems oder eines zusaetzlichen ERP nur fuer Kaffeeliste - Begruendung
in docs/billing.md.

- Neue Tabelle tenant_billing (plan_code, subscription_status, sowie
  bereits vorbereitete, noch ungenutzte Felder fuer Stripe/Dolibarr-IDs).
- app/billing.php: billing_plans() als einzige Quelle der Tarifstufen
  (synchron mit preise.php), billing_required_plan_code() anhand aktiver
  Teilnehmerzahl, billing_check_tenant() vergleicht gebuchten mit
  benoetigtem Tarif - rein informativ, kein Enforcement, solange Stripe
  nicht angebunden ist.
- Neue Mandanten starten automatisch auf plan_code='free' bei der
  Registrierung.
- mandant-einstellungen.php zeigt Owner/Admin ihren aktuellen Tarif und
  Teilnehmerstand, mit Hinweis bei Bedarf einer hoeheren Stufe.
- Back-Office zeigt zusaetzlich zur Mandantenliste den gebuchten und
  (falls abweichend) den tatsaechlich benoetigten Tarif.

Live getestet: Tarifgrenzen (10/25/50/150) mit einem Mandanten unter und
einem ueber dem Freikontingent geprueft, UI in Mandant-Einstellungen und
Back-Office verifiziert. Alle M8-Isolations-/Rollenmatrix-Tests weiterhin
gruen.

Phase 2 (Stripe) und Phase 3 (Dolibarr-Sync) folgen, sobald Test-Keys
beziehungsweise Sandbox-Zugang vorliegen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 23:38:28 +02:00

4.4 KiB
Raw Blame History

Preis- und Abrechnungslogik

Stand: 2026-07-16

Geplante Architektur (mit dem Kunden abgestimmt): Stripe Billing für den Zahlungseinzug, bestehendes Dolibarr für Rechnungsstellung/Buchhaltung. Kein eigenes Rechnungssystem, kein zusätzliches ERP nur für Kaffeeliste siehe Begründung unten.

Warum diese Aufteilung

Drei getrennte Probleme:

  1. Rechnung erzeugen löst Dolibarr (bereits im Einsatz für ein anderes Business des Kunden), fortlaufend nummeriert, GoBD-konform.
  2. Geld tatsächlich einziehen der eigentlich schwierige Teil (wiederkehrende Belastung, Fehlschlag-Wiederholung, Zahlungsmittel- Verwaltung). Weder ein selbstgebautes System noch Dolibarr allein lösen das; ein Zahlungsanbieter mit Abo-Logik schon.
  3. Tarif-/Nutzungsstand verwalten das übernimmt Kaffeeliste selbst, da die Teilnehmerzahl je Mandant ohnehin schon vorhanden ist.

Empfehlung: Stripe Billing statt Mollie, weil eine echte Abo-Logik mit automatischem Stufenwechsel gebraucht wird (Stripes Billing-Produkt ist dafür ausgereifter als Mollies Subscriptions-API); Mollie ist bei SEPA-Lastschrift günstiger, aber weniger auf SaaS-Abos zugeschnitten.

Phase 1: Datenmodell und Tariflogik (umgesetzt, keine externen Zugänge nötig)

Umgesetzte Dateien:

database/migrations/0014_saas_tenant_billing.sql
app/billing.php
app/saas-auth.php (Init bei Registrierung)
mandant-einstellungen.php (Anzeige "Abo & Tarif")
app/platform-admin.php, backoffice.php (Tarif-Spalte im Back-Office)
  • Neue Tabelle tenant_billing: plan_code, subscription_status, stripe_customer_id, stripe_subscription_id, current_period_end, dolibarr_thirdparty_id (letztere beide vorbereitet für Phase 2/3, noch ungenutzt).
  • billing_plans() ist die einzige Quelle für die Tarifstufen (free/basic/plus/pro/enterprise), synchron mit den Preisen auf preise.php.
  • billing_required_plan_code() errechnet anhand der aktiven Teilnehmerzahl die günstigste ausreichende Stufe.
  • billing_check_tenant() vergleicht gebuchten mit benötigtem Tarif; rein informativ kein Enforcement, kein Sperren bei Überschreitung. Solange Stripe nicht angebunden ist, wird bei Bedarf manuell umgestellt (Hinweistext verweist auf Kontakt per E-Mail).
  • Neue Mandanten starten automatisch mit plan_code = 'free'.
  • Owner/Admin sehen ihren aktuellen Tarif und die aktive Teilnehmerzahl unter „Abo & Tarif" auf mandant-einstellungen.php; bei Bedarf einer höheren Stufe erscheint ein Hinweis.
  • Das Back-Office (backoffice.php) zeigt zusätzlich zur Mandantenliste den gebuchten Tarif und, falls abweichend, den tatsächlich benötigten Tarif der Betreiber sieht auf einen Blick, wer manuell hochgestuft werden müsste.

Live getestet: Tarifgrenzen-Berechnung (10/25/50/150) mit einem Mandanten knapp unter und einem mit 12 Teilnehmern (über dem Freikontingent, korrekt als „basic" erkannt) geprüft; UI-Anzeige in Mandant-Einstellungen und Back-Office live verifiziert. Alle bestehenden M8-Isolationstests und der Rollen-Matrix-Test bleiben unverändert grün.

Phase 2: Stripe-Anbindung (noch offen)

Wartet auf Stripe-Test-API-Keys vom Kunden. Geplanter Umfang:

  • Stripe Checkout zum Abschließen/Wechseln eines bezahlten Tarifs.
  • Webhook-Endpunkt für checkout.session.completed, customer.subscription.updated/.deleted, invoice.paid/.payment_failed, der tenant_billing aktuell hält.
  • Stripe Customer Portal für Zahlungsmittel-Verwaltung/Kündigung durch den Kunden selbst.
  • Automatischer Stufenwechsel: Sobald billing_check_tenant() einen höheren Bedarf erkennt, Wechsel der Stripe-Subscription auslösen (mit Proration) statt nur anzuzeigen.

Phase 3: Dolibarr-Anbindung (noch offen)

Wartet auf Zugang zu einer Dolibarr-Sandbox/Testinstanz (bewusst nicht direkt gegen die produktive Instanz des Kunden, um deren bestehende Buchhaltungsdaten nicht zu gefährden). Geplanter Umfang:

  • Bei jedem erfolgreichen Stripe-Zahlungsereignis (invoice.paid) über die Dolibarr-REST-API eine Rechnung im bestehenden Dolibarr des Kunden anlegen (dolibarr_thirdparty_id verknüpft den Mandanten mit dem Dolibarr-Kunden).
  • Stripe bleibt alleiniger Zahlungsweg; Dolibarr wird nur als Buchhaltungs- Spiegel befüllt, nicht selbst zum Auslösen von Zahlungen verwendet.
  • Erst nach erfolgreichem Test gegen die Sandbox gegen die produktive Dolibarr-Instanz freigeben.