K11 aus dem September-Protokoll (Tickets C1 und C2 im Entwicklungsplan), live seit 14.09.2026. C1 – Statistik rechnet wie die Provision - Standard-Baum ist der Provisionsbaum (Mitglieder wie TreeCalcBot: Mitgliedsebene, Abrechnungskonto, active_date; ausgefilterte Knoten kappen ihren Unterbaum, max. 21 Linien). Gesamte Downline bleibt per Umschalter erreichbar, Wahl in der Session. - Punkte-Definition: Provisionspunkte (TP + Shop), reine Karrierepunkte ausgewiesen statt eingerechnet, negative Monatssalden je User wie in der Provision auf 0 gekappt. - Abgeschlossene Monate nehmen die Mitglieder je Linie aus dem gespeicherten Provisionslauf (user_businesses), Snapshots je Baum-Definition (Payload-Version 3, Migration). - Struktur-Modal: Gesamt aus den Linien-Punkten mit Dezimalen statt der int-Spalte total_pp. - Messlauf statistics:compare-trees (Downline / Provisionsbaum / Struktur je VIP, Laufstand-Drift). C2 – Laufstand-Race (Provision zu niedrig bei zeitgleichen Buchungen) - Neuberechnung liest die Zeilen des Beraters sperrend (FOR UPDATE), Index (user_id, year, month). - Paid-Pfad der Payone- und Stripe-Webhooks als DB::transaction mit 3 Anlaeufen; Deadlock und Lock-Timeout aus der Rechnungserstellung werden nicht mehr geschluckt. - Sicherheitsnetz sales:repair-running-totals taeglich 02:45 vor dem Provisionslauf; abgeschlossene Monate werden nicht angefasst (Entscheid 14.09.: keine Nachzahlung fuer 06/08). Doku: Entwicklungsplan zum Protokoll, Deploy-Notiz 14.09. (inkl. Migrations-Stolperstein: Migrationen tragen Werte als Literale, nicht als Konstanten aus dem Anwendungscode). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
6.3 KiB
Deploy 14.09.2026 — Team-Statistik = Team-Struktur, Laufstand-Fix
Das Paket zu K11 aus dem Entwicklungsplan zum September-Protokoll (Tickets C1 und C2) ist auf Produktion. Upload per SFTP, anschließend Migration, Snapshot-Neuaufbau, Laufstand-Reparatur und Cache-Leerung im Terminal. Die Zahlen von Team-Statistik und Team-Struktur stimmen seitdem überein (Rückmeldung Kevin, 14.09.).
Was live gegangen ist
| Ticket | Inhalt |
|---|---|
| C1 | Die Team-Statistik rechnet standardmäßig mit dem Provisionsbaum und den Provisionspunkten — denselben Mitgliedern und Punkten wie die Team-Struktur. Die bisherige Sicht (gesamte Downline) bleibt per Umschalter erreichbar. Für abgeschlossene Monate kommen die Mitglieder je Linie aus dem gespeicherten Provisionslauf. |
| C2 | Laufstand-Race in user_sales_volumes behoben: sperrendes Lesen bei der Neuberechnung, Deadlock-Wiederholung in beiden Zahlungs-Webhooks, tägliches Sicherheitsnetz um 02:45 vor dem Provisionslauf. |
php artisan migrate
php artisan backoffice:store-statistics-snapshots --force
php artisan sales:repair-running-totals
php artisan config:clear && php artisan view:clear && php artisan cache:clear
Stolperstein beim Migrieren. Der erste migrate-Lauf brach mit „Undefined constant
BackofficeDashboardService::TREE_COMMISSION" ab: die Migration hatte die Baum-Namen aus der
Service-Klasse gelesen, und der PHP-Prozess auf dem Server hielt noch die alte Klasse (Opcache). Es
wurde nichts halb angewendet — der Fehler fiel beim Aufbau des Blueprints, vor jedem SQL. Die
Migration trägt die Werte jetzt als Literale; Regel für die Zukunft: Migrationen dürfen nicht vom
Anwendungscode abhängen. Nach Pull, optimize:clear und PHP-FPM-Reload lief sie sauber durch.
Was sich in den Daten geändert hat
Migrationen.
backoffice_statistics_snapshotsbekommt die Spaltetree(commission/downline); bestehende Snapshots werden alsdownlinegekennzeichnet, der Unique-Index läuft jetzt über (user_id,year,month,tree).user_sales_volumesbekommt den Index (user_id,year,month), damit die sperrende Lesart nur den Monatsbereich des Beraters sperrt. Keine vorhandene Zeile wurde verändert.
Snapshot-Neuaufbau. backoffice_statistics_snapshots wurde für alle abgeschlossenen Monate und
beide Baum-Definitionen neu geschrieben (Payload-Version 3). Die Provisionsbaum-Variante nimmt die
Mitglieder je Linie aus user_businesses des jeweiligen Provisionslaufs.
Laufstand-Reparatur September. sales:repair-running-totals hat die Laufstände von 2 Usern
(848 und 1543, zusammen 216 Punkte) neu gerechnet. Nur die kumulativen Spalten der letzten Zeile
wurden korrigiert; die Einzelbuchungen waren vollständig. Der laufende Monat rechnet in der Struktur
live, die Provision für September wird damit richtig.
Nicht angefasst: Juni und August. Beide Monate hatten je einen User mit Laufstand-Drift (66 bzw.
82 Punkte) und sind so abgerechnet worden. Entscheid 14.09.: keine Nachzahlung, keine
Nachberechnung. Die Laufstände bleiben, wie sie in die Provision eingegangen sind; der Nachtlauf
fasst abgeschlossene Monate nicht an (manuell nur mit --force).
Nicht angefasst: Provisionen (user_businesses), Gutschriften, Rechnungen, Marketingplan.
Was das für die Zahlen bedeutet
Die Kachel „Umsatz (Punkte)" der Team-Statistik zeigt jetzt die Provisionspunkte. Gegenüber vorher ist sie kleiner, aus drei Gründen, die alle bewusst sind:
- Nur Provisionsbaum. Berater ohne Mitgliedsebene oder ohne Abrechnungskonto zählen nicht, und ihr Unterbaum ebenfalls nicht — genau wie in der Provisionsberechnung. Die Ansicht zeigt, wie viele Berater der Downline deshalb außen vor sind.
- Reine Karrierepunkte (KP) zählen nicht (Neupartner-Einschreibung, manuelle KP-Gutschriften). Sie stehen als eigene Zahl unter der Tabelle: „Nicht enthalten: X Punkte ohne Payline-Wirkung".
- Negative Monatssalden werden auf 0 gekappt, wie in der Provision. Auch das steht als eigene Zahl: „Nicht abgezogen: Y Punkte aus negativen Monatssalden".
Wer die bisherige Sicht braucht, wählt oben „Gesamte Downline". Die Wahl bleibt in der Sitzung erhalten und steckt auch im CSV-Dateinamen.
Beim Messlauf vor dem Deploy lagen die VIP-Konten im Provisionsbaum bis auf die Laufstand-Drift exakt auf der Struktur. Für August ergab sich nach Umstellung auf die gespeicherte Struktur nur noch eine Differenz von 82 Punkten — genau der Drift-User dieses Monats.
Woran man merken würde, dass etwas nicht stimmt
- Team-Statistik, Provisionsbaum, laufender Monat: Summe der Linien muss mit dem Modal „Linie /
Punkte / Provision" auf der Struktur-Seite auf den Cent übereinstimmen. Prüfung:
php artisan statistics:compare-trees 9 2026(Spalte „Diff PB-Struktur" muss 0,00 sein). - Abgeschlossener Monat: Abzeichen „Monat abgeschlossen · Stand eingefroren" plus Hinweis, dass die Mitglieder je Linie aus dem gespeicherten Provisionslauf stammen.
- Nachtlauf 02:45:
sales:repair-running-totalsschreibt bei Drift eine Warnung inscron-Log. Über mehrere Nächte sollte dort „keine Abweichung" stehen — das ist der Nachweis, dass die Sperre auf MySQL wirkt (die Test-Suite läuft auf SQLite und kann den Race nicht nachstellen). - Zahlungs-Webhooks: Ein Deadlock würde die ganze Paid-Transaktion bis zu dreimal wiederholen.
Erkennbar im
payone- bzw.stripe-Log nur, wenn alle drei Anläufe scheitern; dann stellt der Anbieter erneut zu.
Offen
- C2, Stufe 3 (Provision aus der Zeilensumme statt aus dem Laufstand der letzten Zeile) gehört
zum Ledger-Plan
dev/2026-09-10-business-plan/. - Rückfrage R4 (negative Monatssalden in der Provision) ist eine fachliche Entscheidung und wurde nicht angefasst.
- Unverändert: die vorbestehenden Testfehler auf dem Branch (92 Fehlschläge in Unit-Tests ohne
Datenbank-Setup, z. B.
TreeCalcBotOptimizedTest,ConcurrentPaymentTest; alle mit „no such table" oderBadMethodCallExceptionbereits im Setup). Gehören in ein eigenes Aufräumpaket.
Nicht in diesem Commit und weiterhin nicht committet: die Arbeit aus anderen Themen im selben
Arbeitsbaum (DHL, DATEV, Newsletter-Listen, Berater-Übertragung, DSGVO-Löschung, shipped_at,
Kundenabo-Legenden).