mivita/dev/2026-07-22/monatsabschluss-eingefrorene-statistik.md
Kevin 233cd01bb5 Doku: Statistik-Audit 09.09., Bewertung und Umsetzungsstand
Der Ordner dev/2026-07-22 ist ueber Monate gewachsen; ohne Einstieg findet man
darin nichts mehr. Deshalb ein README als Wegweiser, mit dem Hinweis, dass bei
Widerspruechen immer die juengere Entscheidung gilt (Beispiel: F7 wurde am 10.09.
abgeloest).

Die Bewertung traegt oben einen Stand-Block mit erledigten und offenen Befunden
samt Sprungmarken. Ueberholte Aussagen der ersten Fassung sind markiert statt
geloescht, damit der Weg nachvollziehbar bleibt.

Der Monatsabschluss steht als eigenes Dokument, weil es eine dauerhafte
Fachregel ist und keine Audit-Antwort: was eingefroren wird, was die Regel nicht
leisten kann, und die Betriebsbefehle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 11:19:50 +00:00

4.9 KiB
Raw Permalink Blame History

Abgeschlossene Monate sind eingefroren

Entscheidung der Kundin vom 10.09.2026, umgesetzt am selben Tag. Dieses Dokument hält fest, warum die Statistik so arbeitet, was genau eingefroren wird und was das nicht kann.

Es löst die August-Entscheidung F7 („Abo-Bestände tagesaktuell") ab. Der Bezug zu den Audit-Befunden A04 und A12 steht in Abschnitt 13 der Bewertung.

1. Die Regel

Am ersten Tag des Folgemonats läuft die Monatsabrechnung: Provisionen werden berechnet, Gutschriften ausgestellt, der Monat ist kaufmännisch abgeschlossen. Ab diesem Punkt ändert sich an diesem Monat nichts mehr — weder durch Stornos noch durch Änderungen an der Team-Struktur.

Die Regel gilt damit an zwei Stellen, die vorher unabhängig voneinander gedacht waren:

Bereich Regel
Buchungen/Stornos Ein Storno mindert nur den Monat, in dem die Ursprungsbestellung liegt. Ist der Monat abgeschlossen, passiert nichts mehr (Details).
Statistik/Struktur Ein abgeschlossener Monat wird nicht mehr aus heutigen Daten gerechnet, sondern aus dem gespeicherten Monatsstand.

2. Warum die Struktur der eigentliche Grund ist

Die Team-Struktur ist beweglich: Teampartner kommen dazu, wechseln den Sponsor, fallen weg. Wird ein vergangener Monat weiter live gerechnet, verschiebt sich seine Auswertung mit jeder solchen Änderung.

Eine Beraterin sähe dann im Oktober für den August andere Zahlen als in der Abrechnung, die sie für den August bekommen hat — und die Ursache wäre von außen nicht erkennbar. Genau das war der Auslöser für die Entscheidung.

3. Was eingefroren wird

Der Snapshot ist der abgeschlossene Monat. Er enthält:

  • Punkte und Umsätze je Linie und in Summe
  • Abo-Bestände, Neupartner, „+N neu"
  • Führungskräfte-, Recruiter- und Top-10-Listen
  • die Mitglieder je Linie (lines[].user_ids)
  • die Abos je Linie (lines[].abo_ids, getrennt nach Team-/Kundenabos und jeweils „neu")

Die letzten beiden Punkte sind neu (Payload-Version 2). Aus ihnen baut BackofficeDrilldownService die Detaillisten: Klickt man auf eine Zahl eines abgeschlossenen Monats, zeigt die Liste genau die Mitglieder und Abos, aus denen diese Zahl entstanden ist — auch wenn ein Abo inzwischen gekündigt oder gelöscht wurde (withTrashed()).

Bewusst nicht eingefroren: Stammdaten wie Name, E-Mail oder Karrierestufe. Sie werden zur Anzeigezeit gelesen. Eine Umbenennung soll rückwirkend sichtbar sein, eine Strukturänderung nicht.

4. Was das nicht kann

Für Monate, die vor dem 10.09.2026 abgeschlossen wurden, gibt es keine echte historische Struktur. Frühere Sponsor-Zuordnungen werden nirgends historisiert. Der Rebuild dieser Monate friert deshalb die Struktur des Ausführungstags ein, nicht die des damaligen Monatsendes.

Das war die bewusste Abwägung: Einheitlichkeit über alle Monate war wichtiger als die Rekonstruktion einer Struktur, die es nicht mehr gibt. Ab dem Monatsabschluss 01.10.2026 ist der eingefrorene Stand dann der tatsächliche Monatsstand.

Das Home-Dashboard friert für normale Berater nicht ein — Snapshots gibt es nur für die VIP-Konten (admin 1–3). Wer das auch für alle Berater will, braucht Snapshots für alle Konten; das ist eine eigene Entscheidung (Menge, Laufzeit, Speicher).

5. Betrieb

# Laeuft naechtlich; legt fehlende Snapshots fuer abgeschlossene Monate an
php artisan backoffice:store-statistics-snapshots

# Nur bei einem Schemawechsel des Payloads: baut vorhandene Snapshots neu.
# ACHTUNG: friert die Struktur des Ausfuehrungstags ein (siehe Abschnitt 4).
php artisan backoffice:store-statistics-snapshots --force

Beim Wechsel auf Payload-Version 2 wurde --force einmalig ausgeführt. Snapshots mit Payload-Version 1 bleiben lesbar; ihre Detaillisten fallen auf die Live-Auswertung zurück, statt eine Genauigkeit vorzutäuschen, die sie nicht haben.

6. Wo es im Code steht

Datei Rolle
app/Services/Backoffice/BackofficeDashboardService.php Klassenkommentar mit der fachlichen Begründung; PAYLOAD_VERSION; buildLineRow() schreibt user_ids und abo_ids
app/Services/Backoffice/BackofficeDrilldownService.php frozenLines(), frozenUserIds(), frozenAboIds(), aboScope()
app/Console/Commands/BackofficeStoreStatisticsSnapshots.php Warnung zu --force
app/Services/BusinessPlan/SalesPointsVolume.php dieselbe Regel auf der Buchungsseite (isStornoMonthOpen())
tests/Feature/BackofficeSnapshotFreezeTest.php Regressionen zum Einfrieren

Die beiden Tests in BackofficeStatisticsListsTest.php, die vorher die alte Regel („Abo-Bestände tagesaktuell", August-Entscheidung F7) festhielten, beschreiben jetzt die neue. Sie wurden umgeschrieben, nicht entfernt — die Szenarien bleiben abgedeckt.