Files
kaffeekasse-saas/docs/saas-umstrukturierungsplan.md
T
2026-07-11 22:24:22 +02:00

19 KiB

SaaS-Umstrukturierungsplan Kaffeeliste

Stand: 2026-07-11

Dieses Dokument beschreibt den geplanten Umbau der bestehenden Kaffeelisten-App zu einer mehrkundenfaehigen SaaS-Anwendung mit oeffentlicher Landingpage, Kundenregistrierung und geschuetzter App. Die bestehende Bedienlogik und das visuelle Grunddesign sollen bewusst erhalten bleiben.

Zielbild

  • Mehrere Kunden koennen eigene Kaffeelisten betreiben.
  • Jeder Kunde hat isolierte Daten, Einstellungen, Mitglieder und Buchungen.
  • Neue Kunden koennen sich ueber eine oeffentliche Landingpage registrieren.
  • Die operative App bleibt optisch nah am aktuellen Bestand: Sidebar, Tabellen, schlichte Formulare, HTML5-UP-Anmutung.
  • Authentifizierung, Rollen, Mandantenkontext und Sicherheitspruefungen werden zentralisiert.
  • Finanznahe Vorgaenge werden nachvollziehbar und revisionsfreundlich gespeichert.

Nicht-Ziele fuer den ersten Umbau

  • Kein kompletter Design-Relaunch.
  • Keine verspielte Marketing-App statt der bestehenden Arbeitsoberflaeche.
  • Kein gleichzeitiger Neubau aller Randmodule, wenn diese fuer den MVP nicht benoetigt werden.
  • Kein Dual-Write zwischen Legacy und neuer App als Standardbetrieb.
  • Keine Mandanten-ID aus Formularfeldern oder URL-Parametern als alleinige Sicherheitsbasis.

Ist-Zustand

Die aktuelle App ist eine flache PHP/sqlsrv-Legacy-App im Webroot.

Wichtige Bereiche:

  • index.php: persoenliches Dashboard.
  • stricheintragen.php: Sammelerfassung von Kaffee-Strichen.
  • einzahlung.php: Sammelerfassung von Einzahlungen.
  • kaffeeliste.php: Gesamtuebersicht.
  • mitarbeiterverwalten.php: Mitglieder- und Adminpflege.
  • letzteneintraege.php: Korrektur beziehungsweise Loeschung letzter Buchungen.
  • csvupload.php: Zahlungsimport.
  • exportKaffeeliste.php: PDF-/Listenexport.
  • mailversenden.php: Massenmail.
  • hinweise.php: Hinweise.
  • faq.php: FAQ.

Zentrale technische Beobachtungen:

  • Authentifizierung haengt an Windows/IIS AUTH_USER und LDAP.
  • Die Mailadresse des Nutzers wird in functionsLDAP.php ermittelt.
  • Rollen liegen als Boolean admin direkt auf kl_Mitarbeiter.
  • Datenzugriff findet direkt in den einzelnen PHP-Seiten per sqlsrv_query statt.
  • Es gibt kein sichtbares Migrationssystem und kein DB-Schema im Repository.
  • Fachliche Tabellen haben aktuell keinen Mandantenbezug.
  • Das Design kommt vor allem aus assets/css/main.css und dem HTML5-UP-Layout.
  • Die App-Navigation sitzt faktisch in footer.php; nav.php ist leer.

Grundsatzentscheidung

Der Umbau sollte nicht mit einer rein kosmetischen Landingpage starten, sondern mit einem stabilen SaaS-Fundament:

  1. Bestand dokumentieren und fachliche Ergebnisse einfrieren.
  2. Mandantenmodell, Auth und Rollen sauber aufbauen.
  3. Bestehende Fachlogik schrittweise tenant-sicher uebernehmen.
  4. Landingpage und App-Shell trennen, ohne das App-Design neu zu erfinden.

So bleibt die vertraute Kaffeelisten-Oberflaeche erhalten, waehrend die Datenbasis und Sicherheit SaaS-faehig werden.

Zielarchitektur

Public-Bereich

Der Public-Bereich ist ohne Login erreichbar und laedt keine Mandantendaten.

Empfohlene Routen:

  • /: Landingpage.
  • /preise oder spaeter /pricing: optional, falls Tarife eingefuehrt werden.
  • /faq: oeffentliche FAQ oder FAQ-Auszug.
  • /registrieren: Kundenregistrierung.
  • /login: Login.
  • /passwort-vergessen: Passwort-Reset.

Landingpage-Inhalte:

  • Hero mit Name Kaffeeliste und kurzer Nutzenbeschreibung.
  • Drei Kernablaeufe: Kaffee nehmen, Strich setzen, bei Bedarf bezahlen.
  • Kurzer Blick auf Funktionen: Mitglieder, Guthaben, Einzahlungen, Export, Hinweise.
  • App-Screenshot oder Demo-Ansicht im bestehenden Stil.
  • FAQ-Auszug.
  • Call-to-Action zu Registrierung und Login.

Geschuetzte App

Die geschuetzte App bleibt die operative Arbeitsoberflaeche.

Empfohlene Routen:

  • /app: Dashboard oder Weiterleitung auf /app/dashboard.
  • /app/dashboard: Meine Kaffeeliste.
  • /app/striche: Eigene Striche erfassen, falls erlaubt.
  • /app/einzahlungen: Zahlungen und PayPal-Optionen.
  • /app/mitglieder: Mitgliederverwaltung.
  • /app/liste: Gesamtuebersicht.
  • /app/buchungen: Letzte Eintraege und Korrekturen.
  • /app/importe: CSV-Importe.
  • /app/export/pdf: PDF-/Listenexport.
  • /app/hinweise: Hinweise.
  • /app/einstellungen: Tenant-Einstellungen.

Die App sollte eine Sidebar behalten, aber besser gruppiert werden:

  • Persoenlich: Meine Kaffeeliste, Namensanpassung, FAQ.
  • Erfassung: Striche, Einzahlungen.
  • Auswertung: Kaffeeliste, Buchungen, Export.
  • Administration: Mitglieder, Hinweise, Einstellungen, Importe.

Datenmodell

Empfohlen wird ein Shared-Database/Shared-Schema-Modell mit verpflichtendem tenant_id auf allen fachlichen Tabellen.

Kernschema:

tenants(
  id, slug, name, status, timezone, locale, currency_code,
  created_at, updated_at
)

tenant_settings(
  tenant_id, mark_price_cents, self_entry_enabled, paypal_enabled,
  paypal_url_template, sheet_window_days, negative_warning_cents,
  positive_highlight_cents, branding_json, updated_by_user_id
)

users(
  id, email_norm, password_hash, name, email_verified_at,
  mfa_enabled, disabled_at, last_login_at, created_at, updated_at
)

tenant_memberships(
  id, tenant_id, user_id, role, status, invited_at, joined_at,
  created_at, updated_at,
  UNIQUE(tenant_id, user_id)
)

participants(
  id, tenant_id, user_id NULL, display_name, email_norm NULL,
  paypal_name NULL, active, legacy_mitarbeiter_id,
  created_at, updated_at,
  UNIQUE(tenant_id, email_norm)
)

ledger_entries(
  id, tenant_id, participant_id, type, amount_cents, marks_count,
  unit_price_cents, booked_at, source, note, created_by_user_id,
  import_batch_id NULL, legacy_table, legacy_id,
  voided_at NULL, reversal_of_entry_id NULL,
  created_at
)

notices(
  id, tenant_id, message, valid_from, valid_until,
  created_by_user_id, deleted_at, created_at, updated_at
)

payment_import_batches(
  id, tenant_id, original_filename, checksum, status,
  created_by_user_id, created_at
)

payment_import_rows(
  id, batch_id, row_number, participant_id NULL, raw_name,
  amount_cents, booked_at, status, raw_json
)

audit_log(
  id, tenant_id, actor_user_id, action, subject_type, subject_id,
  metadata_json, ip, created_at
)

outbound_emails(
  id, tenant_id, participant_id, template, subject, status,
  sent_at, error, created_at
)

Wichtige Modellierungsregeln:

  • users sind Login-Konten.
  • participants sind Kaffee-Teilnehmer.
  • Ein Teilnehmer kann, muss aber nicht, ein Login-Konto haben.
  • Rollen gehoeren in tenant_memberships, nicht direkt auf Teilnehmer.
  • Buchungen sollten nicht hart geloescht werden.
  • Korrekturen laufen ueber Storno- oder Reversal-Eintraege.
  • Legacy-IDs werden bei Migration gespeichert, damit Ergebnisse vergleichbar bleiben.
  • Geldwerte sollten als Cent-Integer gespeichert werden, nicht als Float.

Rollenmodell

Empfohlene Rollen:

  • owner: Kunde verwalten, Billing, Admins, Loeschung, Grundeinstellungen.
  • admin: Mitglieder, Hinweise, fachliche Einstellungen, Auswertungen.
  • treasurer: Zahlungen, CSV-Import, Korrekturen, Exporte, Mails.
  • member: eigenes Dashboard, eigene Striche, eigener Anzeigename.
  • viewer: lesende Auswertungen.

Alle Rollen sind tenant-scoped. Ein User kann also bei Kunde A Admin und bei Kunde B nur Mitglied sein.

Authentifizierung und Sicherheit

SaaS-Basis:

  • E-Mail/Passwort-Login mit password_hash.
  • E-Mail-Verifikation.
  • Passwort-Reset.
  • Sichere Session-Cookies.
  • CSRF-Schutz fuer alle schreibenden Aktionen.
  • Rate-Limits fuer Login, Registrierung und Passwort-Reset.
  • Zentrale Funktionen oder Middleware: requireLogin, requireTenant, requireRole, csrfToken.

Tenant-Aufloesung:

  • Primaer serverseitig aus Subdomain, Custom Domain oder tenantgebundener Auswahl nach Login.
  • Nicht allein aus Hidden Inputs oder frei manipulierbaren IDs.
  • Jede fachliche Query braucht einen Tenant-Scope.

Spaeter moeglich:

  • LDAP/AD oder SSO pro Kunde als optionaler Identity Provider.
  • MFA fuer Owner/Admins.
  • Row-Level-Security in der Datenbank.

Design-Leitplanken

Das bestehende Design soll erhalten bleiben.

Beibehalten:

  • Gruener Akzent #38761d.
  • Weiss/Grau als ruhige Grundflaeche.
  • Roboto Slab fuer Ueberschriften.
  • Open Sans fuer Fliesstext.
  • Sidebar fuer die geschuetzte App.
  • Tabellen als primaere Darstellung fuer operative Daten.
  • Schlichte Formularfelder und Buttons.

Verbessern ohne Relaunch:

  • Hinweise als wiederverwendbare Komponente statt Inline-Style.
  • Einheitliche Erfolgs-, Fehler- und Warnmeldungen.
  • Dashboardwerte als kompakte Statusbereiche.
  • Aktionsleisten ueber Tabellen.
  • Sidebar-Gruppierung und aktive Navigation.
  • FAQ strukturieren, aber Inhalte nicht stark veraendern.

Nicht tun:

  • Kein komplett neues Farbsystem.
  • Keine dekorative Marketingoptik in der App.
  • Keine App-Tabellen in Kartenlandschaften aufloesen.
  • Keine Navigationsstruktur, die die heutigen Kernablaeufe versteckt.

Meilensteinplan

Uebersicht:

Meilenstein Schwerpunkt Hauptergebnis
M0 Baseline Bestand, Sicherheit und Designreferenz sind dokumentiert
M1 Golden Master Legacy-Ergebnisse sind als Vergleichsbasis eingefroren
M2 Technisches Fundament Public-/App-Struktur, Bootstrap, Session und CSRF stehen
M3 SaaS-Basis Tenants, User, Registrierung, Login und Rollen funktionieren
M4 Datenmigration Legacy-Daten sind tenant-sicher im Zielmodell abgebildet
M5 App-Kern Dashboard, Striche, Einzahlungen, Mitglieder und Liste laufen
M6 Betriebsflows Import, Export, Mail und Jahresprozesse sind auditierbar
M7 Landingpage Werbliche Seite und Registrierung sind oeffentlich nutzbar
M8 Haertung Betrieb, Datenschutz, Monitoring und Isolation sind geprueft
M9 Cutover Produktivumstellung ist vorbereitet und Legacy ist read-only

M0: Planungs- und Sicherheitsbaseline

Ziel: Den aktuellen Zustand verlaesslich dokumentieren, bevor umgebaut wird.

Arbeitsartefakte:

  • docs/m0/README.md
  • docs/m0/code-inventory.md
  • docs/m0/security-baseline.md
  • docs/m0/schema-export.sql
  • docs/m0/golden-master-queries.sql
  • docs/m0/screenshot-checklist.md

Schritte:

  • Live-DB-Schema exportieren.
  • Tabellen, Spalten, Indizes und Constraints dokumentieren.
  • Bekannte Jobs/Skripte erfassen, zum Beispiel Mailversand und Jahresauswertung.
  • Secrets inventarisieren und rotieren, insbesondere hart codierte Zugangsdaten.
  • Bestehende Seiten und UI-Zustaende per Screenshots festhalten.
  • Fachliche Kernregeln dokumentieren: Saldo, Jahreswerte, Preis pro Strich, 100-Tage-Listen, CSV-Deduplizierung, PDF-Ausgabe.

Ergebnis:

  • Datenkatalog.
  • Prozesslandkarte.
  • Designreferenz.
  • Liste kritischer Sicherheitsrisiken.

Abhaengigkeiten:

  • Zugriff auf echte oder anonymisierte Datenbank.
  • Kenntnis der Produktivumgebung.

M1: Golden-Master-Validierung

Ziel: Sicherstellen, dass spaetere neue Berechnungen dieselben Ergebnisse wie der Bestand liefern.

Schritte:

  • Referenzdatensatz aus Legacy erzeugen.
  • Pro Mitglied berechnen: Gesamteinzahlungen, Gesamtausgaben, Gesamtstriche, aktueller Stand, Jahreswerte.
  • PDF-/Export-Summen als Referenz sichern.
  • CSV-Importfaelle sammeln: Treffer, Dubletten, unbekannte Namen.
  • Testfaelle fuer Guthaben, Schulden, Nullsaldo und inaktive Teilnehmer anlegen.

Ergebnis:

  • Golden-Master-Daten.
  • Vergleichsqueries oder Vergleichsskript.
  • Akzeptanzkriterien fuer Migration und neue App.

Abhaengigkeiten:

  • M0 abgeschlossen.

M2: Technisches Fundament

Ziel: Eine saubere Basis fuer App, Public-Seiten, Auth und Mandanten schaffen.

Schritte:

  • Projektstruktur festlegen: Public-Routes, App-Routes, Views/Templates, Services/Repositories.
  • Zentrales Bootstrap fuer Config, DB-Verbindung, Session und Fehlerbehandlung.
  • Layouts trennen: Public-Layout und App-Layout.
  • Bestehende Assets weiterverwenden.
  • CSRF- und Session-Basis einziehen.
  • Konfigurationswerte aus Code in Umgebung oder Settings verschieben.

Ergebnis:

  • Grundgeruest fuer neue SaaS-App.
  • Kein fachlicher Rewrite, aber klare Struktur fuer die Migration.

Abhaengigkeiten:

  • Entscheidung, ob PHP nativ weitergefuehrt oder ein Framework genutzt wird.

M3: Mandanten, Registrierung und Login

Ziel: Mehrkundenfaehigkeit und Kunden-Onboarding technisch aktivieren.

Schritte:

  • Tabellen fuer tenants, users, tenant_memberships und tenant_settings anlegen.
  • Registrierung: Tenant + Owner-User + Default-Settings erzeugen.
  • Login, Logout, Passwort-Reset und E-Mail-Verifikation bauen.
  • Tenant-Aufloesung definieren.
  • Rollenpruefung zentralisieren.
  • Erste Admin-/Owner-Seite fuer Grundeinstellungen.

Ergebnis:

  • Ein neuer Kunde kann sich registrieren und in seine eigene App gelangen.
  • Rollen und Tenant-Kontext sind serverseitig verfuegbar.

Abhaengigkeiten:

  • M2 abgeschlossen.

M4: Migration des fachlichen Kerns

Ziel: Bestehende Kaffeelisten-Daten tenant-sicher uebernehmen.

Schritte:

  • Initialen Tenant fuer den bisherigen Bestand anlegen.
  • kl_Mitarbeiter nach participants migrieren.
  • admin-Informationen in tenant_memberships oder Admin-Rollen ueberfuehren.
  • kl_config nach tenant_settings migrieren.
  • kl_Einzahlungen und kl_Kaffeeverbrauch nach ledger_entries migrieren.
  • Legacy-IDs speichern.
  • Salden gegen Golden-Master vergleichen.

Ergebnis:

  • Bestehender Datenbestand ist im neuen Modell abgebildet.
  • Saldenparitaet ist nachweisbar.

Abhaengigkeiten:

  • M1 und M3 abgeschlossen.

M5: Geschuetzte App-Funktionen

Ziel: Die operativen Kernseiten im neuen Modell bereitstellen.

Schritte:

  • Dashboard Meine Kaffeeliste umsetzen.
  • Eigene Stricherfassung umsetzen.
  • Zahlungs-/PayPal-Bereich umsetzen.
  • Mitgliederverwaltung tenant- und rollenbasiert umsetzen.
  • Gesamtuebersicht umsetzen.
  • Letzte Eintraege und Korrekturen als Storno statt Delete umsetzen.
  • Hinweise als tenant-spezifische Notices umsetzen.

Ergebnis:

  • Ein Kunde kann seine Kaffeeliste operativ nutzen.
  • App sieht weiterhin nach bestehender Kaffeeliste aus.

Abhaengigkeiten:

  • M4 abgeschlossen.

M6: Import, Export und Mail

Ziel: Admin- und Treasurer-Flows produktionsreif machen.

Schritte:

  • CSV-Import mit Vorschau, Dublettenpruefung und Audit bauen.
  • Uploads ausserhalb des Webroots speichern.
  • PDF-/Listenexport aus neuem Datenmodell bauen.
  • Mailversand als nachvollziehbaren Versandjob mit Dry-Run und Versandlog gestalten.
  • Jahresauswertung beziehungsweise Jahresbuchungen tenant-sicher abbilden.

Ergebnis:

  • Kassenverwaltung ist fuer reale Betriebsablaeufe vollstaendig.
  • Import/Export/Mail sind auditierbar.

Abhaengigkeiten:

  • M5 fuer die Kernansichten.

M7: Oeffentliche Landingpage

Ziel: Werbliche Einstiegseite und Registrierung verfuegbar machen, ohne die App-Optik zu verwischen.

Schritte:

  • Public-Layout mit bestehender Typografie und gruenem Akzent bauen.
  • Landingpage-Inhalte erstellen.
  • Demo-Screenshot oder Demo-Ansicht einbinden.
  • CTA zu Registrierung und Login.
  • FAQ-Auszug strukturieren.
  • Keine App-Sidebar im Public-Bereich.

Ergebnis:

  • Interessenten verstehen das Produkt und koennen sich registrieren.
  • Bestehende App bleibt optisch eigenstaendig und arbeitsorientiert.

Abhaengigkeiten:

  • M3 fuer Registrierung.
  • M5 fuer echte App-Screens oder Demo.

M8: Haertung, Datenschutz und Betrieb

Ziel: Die SaaS-App fuer mehrere Kunden sicher betreiben.

Schritte:

  • Backups und Restore-Prozess definieren.
  • Monitoring und Fehlerlogging einrichten.
  • Audit-Log fuer Admin-Aktionen pruefen.
  • Datenexport pro Tenant.
  • Loesch-/Anonymisierungsprozess fuer Teilnehmer und Kunden.
  • Rate-Limits und Security Headers.
  • Mandanten-Isolation testen.
  • Rollenmatrix testen.

Ergebnis:

  • SaaS ist betrieblich und datenschutzseitig belastbarer.

Abhaengigkeiten:

  • M3 bis M6.

M9: Cutover und Legacy-Archiv

Ziel: Produktive Umstellung ohne Datenverlust.

Schritte:

  • Legacy fuer Schreibzugriffe sperren.
  • Finalen Delta-Export ziehen.
  • Migration ausfuehren.
  • Rowcounts, Salden, PDF-Stichproben und Importhistorie pruefen.
  • DNS oder Reverse Proxy umschalten.
  • Legacy 30 bis 90 Tage read-only als Archiv behalten.
  • Rollback-Fenster und Vorgehen dokumentieren.

Ergebnis:

  • Neuer SaaS-Betrieb ist live.
  • Alter Bestand bleibt fuer Rueckfragen lesbar.

Abhaengigkeiten:

  • M8 abgeschlossen.

Empfohlene MVP-Reihenfolge

Fuer den ersten produktnahen MVP sollten nicht alle Randmodule gleichzeitig umgebaut werden.

MVP-Paket:

  1. Tenant, User, Login, Registrierung.
  2. Teilnehmer, Settings, Ledger.
  3. Dashboard, Striche, Einzahlungen, Gesamtuebersicht.
  4. Mitgliederverwaltung.
  5. Hinweise.
  6. CSV-Import, Export.
  7. Landingpage.

Spaeter:

  • Umfrage-Modul.
  • SSO/LDAP pro Kunde.
  • Billing/Tarife.
  • MFA.
  • Custom Domains.
  • Erweiterte Mandanten-Branding-Optionen.

Validierung

Fachliche Pruefungen:

  • Saldo je Teilnehmer alt gegen neu.
  • Jahreswerte alt gegen neu.
  • Gesamtstriche alt gegen neu.
  • Einzahlungen alt gegen neu.
  • Export-Summen alt gegen neu.
  • CSV-Import: identische Treffer- und Dublettenlogik.

Sicherheitspruefungen:

  • Fremde Tenant-IDs liefern keine Daten.
  • Fremde Teilnehmer-IDs liefern keine Daten.
  • Admin-Funktionen sind ohne Rolle blockiert.
  • Alle POST-Aktionen brauchen CSRF.
  • Uploads sind nicht direkt ausfuehrbar.
  • Ausgabe von Namen, Mails und Hinweisen ist escaped.

UX-Pruefungen:

  • Kernseiten bleiben optisch wiedererkennbar.
  • Sidebar bleibt fuer App-Nutzer vertraut.
  • Landingpage zeigt keine App-Adminnavigation.
  • Mobile Darstellung bleibt bedienbar.
  • Tabellen bleiben lesbar.

Risiken und Gegenmassnahmen

Risiko Gegenmassnahme
Tenant-Leak durch vergessene Query-Filter Zentrale Repository-/Query-Schicht, Tests mit zwei Tenants
Falsche Salden nach Migration Golden-Master-Vergleich vor Cutover
Harte Deletes verlieren Audit-Historie Storno-/Reversal-Modell fuer Buchungen
Login und Teilnehmer werden vermischt users und participants strikt trennen
Bestehendes Design driftet weg Designreferenz und App-Komponenten definieren
CSV-Upload unsicher Upload ausserhalb Webroot, Dateityppruefung, Importvorschau
Mailversand nicht nachvollziehbar Versandlog, Dry-Run, Job-Status
AD/LDAP blockiert SaaS-Onboarding E-Mail/Passwort als Basis, SSO spaeter optional
Kein DB-Schema im Repo Schema exportieren und Migrationen einfuehren

Offene Entscheidungen

  • Soll die neue App weiterhin nativ in PHP entstehen oder mit einem Framework?
  • Soll SQL Server bleiben oder mittelfristig eine andere Datenbank genutzt werden?
  • Wie sollen Kunden-Tenants adressiert werden: Subdomain, Pfad oder Auswahl nach Login?
  • Welche Rolle soll treasurer haben: eigene Rolle oder Teil von admin?
  • Wird das Umfrage-Modul Teil des SaaS-Produkts oder nur archiviert?
  • Braucht der MVP schon Tarife/Billing oder erstmal nur Registrierung?
  • Sollen bestehende Kunden per Einladung oder per Self-Service onboarden?

Naechster konkreter Arbeitsschritt

Als naechstes sollte M0 gestartet werden:

  1. Produktiv-/Testdatenbankschema exportieren.
  2. Screenshot-Referenz der wichtigsten Seiten erstellen.
  3. Golden-Master-Auswertungen definieren.
  4. Entscheidung treffen, ob der neue SaaS-Kern im bestehenden PHP-Stil oder mit einem Framework aufgebaut wird.