Die Closure fuer den Link des gruenen "+N"-Badges band die neue Variable nicht per use ein; sobald eine Linie neue Abos zaehlte, brach die Uebersicht mit "Undefined variable $selectedTree" ab. Regressionstest rendert die Uebersicht mit einem neuen Teamabo und prueft den Badge-Link. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
117 lines
7.2 KiB
Markdown
117 lines
7.2 KiB
Markdown
# Deploy 14.09.2026 — Team-Statistik = Team-Struktur, Laufstand-Fix
|
|
|
|
Das Paket zu K11 aus dem [Entwicklungsplan zum September-Protokoll](../_tickets/entwicklungsplan-protokoll-september-2026.md)
|
|
(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. |
|
|
|
|
```bash
|
|
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_snapshots` bekommt die Spalte `tree` (`commission` / `downline`); bestehende
|
|
Snapshots werden als `downline` gekennzeichnet, der Unique-Index läuft jetzt über
|
|
(`user_id`, `year`, `month`, `tree`).
|
|
- `user_sales_volumes` bekommt 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:
|
|
|
|
1. **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.
|
|
2. **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".
|
|
3. **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-totals` schreibt bei Drift eine Warnung ins
|
|
`cron`-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" oder `BadMethodCallException` bereits 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).
|
|
|
|
---
|
|
|
|
## Nachtrag 14.09.2026 — Übersicht brach mit „Undefined variable $selectedTree" ab
|
|
|
|
Kurz nach dem Deploy meldete Produktion auf `/user/backoffice/statistics` eine ViewException. Die
|
|
Link-Closure für das grüne „+N"-Badge (neue Abos im Monat) in `index.blade.php` band die neue
|
|
Variable `$selectedTree` nicht per `use` ein. Der Fehler trat nur auf, wenn in einer Linie neue Abos
|
|
gezählt wurden — die Tests hatten die Übersicht bis dahin nie mit gefüllten Zeilen gerendert.
|
|
|
|
**Behebung:** `use (..., $selectedTree)` an der Closure, dazu ein Regressionstest, der die Übersicht
|
|
mit einem neuen Teamabo rendert und den Badge-Link samt `tree=`-Parameter prüft
|
|
(`BackofficeStatisticsDrilldownTest`). Ohne den Fix schlägt er mit genau dieser Meldung fehl.
|
|
|
|
**Deployment:** nur `resources/views/user/backoffice/statistics/index.blade.php`, danach
|
|
`php artisan view:clear`. Keine Migration, keine Daten.
|