# M4 Datenmigration Fachlicher Kern Stand: 2026-07-14 M4 uebernimmt die finanznahen Legacy-Buchungen additiv in das neue tenant-sichere Ledger-Modell. Die bestehenden Legacy-Seiten lesen und schreiben weiterhin die bisherigen `kl_*`-Tabellen; das Ledger dient zunaechst als vergleichbare, pruefbare Zielstruktur. Erste App-Abfragen koennen nun ueber einen zentralen Ledger-Service gegen `ledger_entries` laufen. ## Ziel - `kl_Einzahlungen` nach `ledger_entries` spiegeln. - `kl_Kaffeeverbrauch` nach `ledger_entries` spiegeln. - Legacy-IDs erhalten, damit Paritaet und spaetere Delta-Migration moeglich bleiben. - Summen gegen den Golden Master pruefen. - Keine bestehenden Legacy-Buchungen loeschen oder veraendern. ## Nicht-Ziele - Keine Umstellung der operativen Seiten auf das Ledger in diesem Schritt. - Keine Storno-/Korrektur-UI. - Kein CSV-Import auf neues Import-Batch-Modell. - Kein PDF-/Mail-/Jahresprozess-Rewrite. ## Umgesetzter erster Schritt Umgesetzte Migration: ```text database/migrations/0006_saas_ledger_entries.sql ``` Neue Tabelle: - `ledger_entries` Ergaenzende Skripte: ```text scripts/backfill-ledger-entries.php scripts/check-m4-ledger-migration.php scripts/check-m4-ledger-service.php ``` Ergaenzende App-Dateien: ```text app/ledger.php ledger-preview.php ``` Ausgefuehrter Dev-Stand: - Migration `0006_saas_ledger_entries.sql` wurde angewendet. - 9 Legacy-Einzahlungen wurden als `payment` gespiegelt. - 12 Legacy-Kaffeeverbrauch-Zeilen wurden als `consumption` gespiegelt. - Ein zweiter Backfill-Lauf blieb idempotent und erzeugte keine Dubletten. - `app/ledger.php` stellt zentrale Abfragen fuer Tenant-Summen, Teilnehmer-Summen, einzelne Teilnehmer und letzte Buchungen bereit. - `ledger-preview.php` zeigt eine read-only App-Vorschau auf Tenant-Summen, aktive Teilnehmer und die letzten Ledger-Buchungen. ## Abbildungsregeln ### Einzahlungen Quelle: ```text kl_Einzahlungen ``` Ziel: ```text ledger_entries.type = payment ledger_entries.amount_cents = Betrag * 100 ledger_entries.booked_at = Datum ledger_entries.source = legacy_payment ledger_entries.legacy_table = kl_Einzahlungen ledger_entries.legacy_id = EinzahlungsID ``` Einzahlungen werden positiv gespeichert. ### Kaffeeverbrauch Quelle: ```text kl_Kaffeeverbrauch ``` Ziel: ```text ledger_entries.type = consumption ledger_entries.amount_cents = -Kosten * 100 ledger_entries.marks_count = AnzahlStriche ledger_entries.unit_price_cents = KostenproStrich * 100 ledger_entries.booked_at = Datum ledger_entries.source = legacy_web bei Eintragsart = 2, sonst legacy_manual ledger_entries.legacy_table = kl_Kaffeeverbrauch ledger_entries.legacy_id = VerbrauchID ``` Verbrauch wird negativ gespeichert. Damit ergibt `SUM(amount_cents)` direkt den aktuellen Saldo eines Teilnehmers. ## Idempotenz und Aufraeumen Das Backfill-Skript nutzt `tenant_id`, `legacy_table` und `legacy_id` als eindeutige Quelle. Wiederholte Laeufe aktualisieren vorhandene Ledger-Zeilen. Fuer den Default-Tenant werden nur solche Legacy-Spiegelungen entfernt, deren urspruengliche Legacy-Zeile nicht mehr existiert. Fachliche Daten werden dabei nicht aus den `kl_*`-Tabellen geloescht. ## Ausfuehrung ```bash php scripts/backfill-default-tenant.php php scripts/backfill-ledger-entries.php php scripts/check-m4-ledger-migration.php php scripts/check-m4-ledger-service.php php scripts/check-golden-master.php ``` In der lokalen VS-Code-Server-Umgebung muss wie bei M2/M3 die lokale PHP-8.3- Installation aus `.local/` verwendet werden. ## Akzeptanzkriterien - Migration `0006_saas_ledger_entries.sql` laeuft erfolgreich: erfuellt. - Jede Legacy-Einzahlung hat genau eine Ledger-Zeile: erfuellt. - Jeder Legacy-Kaffeeverbrauch hat genau eine Ledger-Zeile: erfuellt. - Legacy-IDs sind je Tenant eindeutig: erfuellt. - Einzahlungen sind positiv, Verbrauch ist negativ: erfuellt. - Verbrauch behaelt Strichanzahl und Preis pro Strich: erfuellt. - Web-Striche aus `Eintragsart = 2` bleiben als `source = legacy_web` erkennbar: erfuellt. - Ledger-Summen entsprechen dem Golden Master: erfuellt. - Zentrale Ledger-Abfragen liefern dieselben Teilnehmer-Summen wie der Golden Master: erfuellt. - Tenant-Summen, aktive Teilnehmer, Einzelteilnehmer und letzte Buchungen sind ueber `app/ledger.php` abrufbar: erfuellt. - Read-only Ledger-Preview ist im Browser erreichbar: erfuellt. ## Aktueller Pruefstatus - M4 Ledger-Migration: gruen mit 73 Assertions. - M4 Ledger-Service: gruen mit 102 Assertions. - M3 SaaS-Basis: weiterhin gruen. - M3 Tenant-Aufloesung: weiterhin gruen. - M3 Passwort/E-Mail: weiterhin gruen. - M3 Auth-Flow: weiterhin gruen. - M3 Settings-Flow: weiterhin gruen. - M3 Mail-Flow: weiterhin gruen. - Golden Master: weiterhin gruen mit 104 Assertions. - HTTP-Smoke: weiterhin gruen mit 23 geprueften Seiten inklusive `ledger-preview.php`. ## Noch offen in M4 - Tenant-sichere Dashboard-, Strich-, Einzahlungs- und Listenqueries schrittweise von Legacy-Tabellen auf das Ledger umstellen. - Storno-/Reversal-Modell in der UI statt harter Deletes. - Delta-Strategie fuer den finalen Cutover.