417 lines
16 KiB
Markdown
417 lines
16 KiB
Markdown
# Entwicklungskonzept: Backoffice Dashboard & Interaktivität
|
|
|
|
Datum: 13.05.2026
|
|
|
|
Quelle: `docs/salescenter/Todos Backoffice.md`
|
|
|
|
## Zielbild
|
|
|
|
Das Partner-Backoffice soll von einer statischen Monats-Kachelansicht zu einer klickbaren, linienbasierten Statistik ausgebaut werden. Führungskräfte sollen von der Gesamtübersicht über Linien und Generationen bis zu einzelnen Kunden, Partnern und Abos navigieren können.
|
|
|
|
Kernziel ist eine einheitliche Datenbasis für:
|
|
|
|
- Dashboard-Kennzahlen pro Linie 1 bis 8 inklusive Summenzeile
|
|
- Detailansichten je Linie, Firstline und Kennzahl
|
|
- Kundenabos, Teamabos, Kundenabos im Team, Umsatz und Punkte
|
|
- neue Spezial-Kennzahl "1000 Punkte Shop"
|
|
- saubere Begrifflichkeit und rechtssichere Sichtbarkeit in Incentive-Ranglisten
|
|
|
|
## Bestandsaufnahme im System
|
|
|
|
### Dashboard
|
|
|
|
Aktueller Einstieg:
|
|
|
|
- Route: `GET /home`
|
|
- Controller: `App\Http\Controllers\HomeController@show`
|
|
- View: `resources/views/home.blade.php`
|
|
- Statistik-Partial: `resources/views/dashboard/_statistics.blade.php`
|
|
|
|
Die aktuelle Statistik wird direkt im Blade-Partial berechnet. Sie nutzt unter anderem:
|
|
|
|
- `App\Models\UserBusiness` für gespeicherte Monatswerte und Payline-Punkte
|
|
- `App\Models\UserSalesVolume` für Kunden-/Shop-Punkte
|
|
- `App\Models\UserAbo` für eigene Abos, Kundenabos und Teamabos
|
|
- rekursive Sponsor-Abfragen über `users.m_sponsor`
|
|
|
|
Bewertung:
|
|
|
|
- Die vorhandene Ansicht ist ein guter Einstieg, aber fachlich zu grob.
|
|
- Es gibt noch keine Linien 1 bis 8, keine Summenzeile und keine Drill-down-Routen.
|
|
- Die Kennzahl "Kundenabos" vermischt aktuell eigene Abos und Kundenabos.
|
|
- "Team-Abos" zählt aktuell Beraterabos im Team, aber nicht die separat geforderten Kundenabos im Team.
|
|
|
|
### Team- und Abo-Bereich
|
|
|
|
Relevante Routen und Controller:
|
|
|
|
- `User\TeamController@structure` für Strukturansicht
|
|
- `User\TeamController@show` und `datatableOptimized` für Teamliste
|
|
- `User\TeamController@showAbos` für Team-Beraterabos
|
|
- `User\TeamController@showTeamCustomerAbos` für Kundenabos im Team
|
|
- `User\TeamController@detailAbo` für Abo-Details
|
|
|
|
Relevante Daten:
|
|
|
|
- `UserAbo::is_for = 'me'` bedeutet Berater-/Eigenabo
|
|
- `UserAbo::is_for = 'ot'` bedeutet Kundenabo
|
|
- `UserAbo::user_id` ist der Bestell-/Abo-User
|
|
- `UserAbo::member_id` ist der zugeordnete Berater
|
|
- `UserAbo::next_date` liefert die nächste Abo-Ausführung
|
|
- `UserAbo::getTotalPoints()` berechnet Punkte aus Abo-Items und Produkten
|
|
- `AboHelper::getTeamUserIds()` liefert Downline-User-IDs
|
|
- `AboHelper::getMonthlyAboCounts()` kennt bereits die Scopes `team_abos` und `team_cust_abos`
|
|
|
|
Bewertung:
|
|
|
|
- Viele Datenquellen für die geforderten Listen existieren bereits.
|
|
- Die Logik ist aber auf mehrere Controller, Blades und Helper verteilt.
|
|
- Für das neue Dashboard sollte die Logik zentralisiert werden, statt weitere Berechnungen in Blade-Dateien zu ergänzen.
|
|
|
|
### Business- und Punkteberechnung
|
|
|
|
Relevante Bausteine:
|
|
|
|
- `App\Services\BusinessPlan\TreeCalcBotOptimized`
|
|
- `App\Models\UserBusiness`
|
|
- `App\Models\UserSalesVolume`
|
|
- `App\Services\BusinessPlan\SalesPointsVolume`
|
|
|
|
Bewertung:
|
|
|
|
- Für Monats- und Teamwerte sollte bevorzugt auf gespeicherte Businessdaten zurückgegriffen werden.
|
|
- Live-Berechnung über TreeCalcBot ist als Fallback sinnvoll, darf aber nicht bei jedem Seitenaufruf ungefiltert große Strukturen neu berechnen.
|
|
- Die neue Drill-down-Logik benötigt klare Regeln, ob sie Live-Daten oder gespeicherte Monats-Snapshots zeigt.
|
|
|
|
### Incentives
|
|
|
|
Relevante Dateien:
|
|
|
|
- `App\Http\Controllers\User\IncentiveController`
|
|
- `resources/views/user/incentive/show.blade.php`
|
|
- `App\Models\IncentiveParticipant`
|
|
- `App\Services\Incentive\IncentiveTracker`
|
|
|
|
Status:
|
|
|
|
- Teilnahme-Opt-in existiert über `accepted_terms_at`.
|
|
- Ranking wird aktuell mit `paginate(100)` angezeigt.
|
|
- Nicht zustimmende Teilnehmer werden für normale User anonymisiert.
|
|
- VIP-Ansicht sieht zusätzliche Hinweise zur Zustimmung.
|
|
|
|
Lücke zum Briefing:
|
|
|
|
- Es gibt noch keine separate Zustimmung "Name/Fotos/Land in Rangliste sichtbar".
|
|
- Foto und Land sind in der aktuellen Rangliste nicht als sichtbare Standardspalten umgesetzt.
|
|
- Rechtliche Freigabe muss fachlich vor der technischen Umsetzung geklärt werden.
|
|
|
|
### Checkout-Herkunft
|
|
|
|
Relevante Dateien:
|
|
|
|
- `App\Http\Controllers\Web\CheckoutController`
|
|
- `App\Repositories\CheckoutRepository`
|
|
- `App\Models\ShoppingUser`
|
|
|
|
Status:
|
|
|
|
- `CheckoutController::validateCheckoutData()` validiert Basisdaten, aber keine Pflichtfrage "Von wem hast du von Mivita erfahren?"
|
|
- `ShoppingUser` nutzt `is_from` für den technischen Ursprung wie `shopping`, `homeparty` oder `collection`.
|
|
- Ein fachliches Herkunfts-/Empfehlungsfeld existiert nicht als sauber getrennte Datenquelle.
|
|
|
|
### Storno und Punkterückführung
|
|
|
|
Relevante Dateien:
|
|
|
|
- `App\Repositories\InvoiceRepository`
|
|
- `App\Services\BusinessPlan\SalesPointsVolume`
|
|
- `App\Services\Incentive\IncentiveTracker`
|
|
|
|
Status:
|
|
|
|
- Beim Erstellen einer Stornorechnung ruft `InvoiceRepository::createCancellation()` die Punktekorrektur auf.
|
|
- `SalesPointsVolume::cancelSalesPointsVolume()` erstellt einen negativen `UserSalesVolume`-Eintrag mit Status `6`.
|
|
- Danach wird der Monat neu berechnet und `IncentiveTracker::trackStorno()` informiert.
|
|
|
|
Risiken:
|
|
|
|
- Wenn zur Originalrechnung kein `UserSalesVolume` existiert, wird nur geloggt und keine Punktekorrektur erstellt.
|
|
- Der negative Storno-Eintrag wird aktuell dem aktuellen Monat zugeordnet, nicht zwingend dem ursprünglichen Umsatzmonat.
|
|
- Fachlich muss entschieden werden, ob Stornos im Stornomonat oder im Ursprungsmonat wirken sollen.
|
|
|
|
## Fachliche Prüfung der To-dos
|
|
|
|
### 1. Überarbeitetes Dashboard & KPI-Übersicht
|
|
|
|
Umsetzung sinnvoll, aber nicht als Erweiterung des bestehenden Blade-Partials. Benötigt wird ein dedizierter Service, der die Kennzahlen pro Linie liefert.
|
|
|
|
Vorgeschlagene Tabelle Stufe 1:
|
|
|
|
- Linie
|
|
- Anzahl Berater
|
|
- Umsatz gesamt
|
|
- Eigen-/Beraterabos im Team
|
|
- eigene Kundenabos
|
|
- Kundenabos im Team
|
|
- Neupartner
|
|
- 1000 Punkte Shop
|
|
- Summe
|
|
|
|
Wichtig:
|
|
|
|
- "Teamkundenabos" sollte als Begriff für Kundenabos der Downline verwendet werden.
|
|
- "Teamabos" sollte nur für Berater-/Eigenabos im Team verwendet werden.
|
|
- Eigene Abos dürfen nicht in Kundenabos eingerechnet werden.
|
|
|
|
### 2. Interaktivität & Deep Dive
|
|
|
|
Umsetzung über eigene Backoffice-Statistik-Routen statt über große Modals im Dashboard.
|
|
|
|
Vorgeschlagene Stufen:
|
|
|
|
- Stufe 1: Linienübersicht `/user/backoffice/statistics`
|
|
- Stufe 2: Linien-/Firstline-Detail `/user/backoffice/statistics/line/{line}`
|
|
- Stufe 3: Kennzahlenliste `/user/backoffice/statistics/details?line=...&metric=...&user=...`
|
|
|
|
Jede Zahl erhält einen Link auf eine gefilterte Detailansicht. Die Detailansicht sollte die Query-Parameter sichtbar halten, damit Support und Fachbereich Ergebnisse reproduzieren können.
|
|
|
|
### 3. Spezial-Kennzahl "1000 Punkte Shop"
|
|
|
|
Definition muss vor Umsetzung final geklärt werden.
|
|
|
|
Vorschlag für Version 1:
|
|
|
|
- Zeitraum: gewählter Monat/Jahr des Dashboards
|
|
- Personenkreis: Downline des eingeloggten Users
|
|
- Schwelle: `UserSalesVolume` Shop-/KP-Summe pro Partner >= 1000 Punkte
|
|
- Sortierung: Volumen absteigend
|
|
- Detailspalten: Name, Account, Linie/Generation, Shop-Punkte, Gesamt-KP, Umsatz netto
|
|
|
|
Offene Fachfrage:
|
|
|
|
- Meint "Kundenumsatz" nur Shop-Umsatz (`month_shop_points`) oder alle Kundenpunkte inklusive Abo-/Beraterkontext?
|
|
|
|
### 4. Bestellformular: "Von wem hast du von Mivita erfahren?"
|
|
|
|
Technisch sollte ein neues fachliches Feld eingeführt werden, nicht `is_from` zweckentfremdet werden.
|
|
|
|
Vorschlag:
|
|
|
|
- Migration für `shopping_users.referral_source_name` oder ähnliches Feld
|
|
- optional zusätzlich auf `shopping_orders`, wenn die Information revisionssicher pro Bestellung eingefroren werden soll
|
|
- Pflichtvalidierung in `CheckoutController::validateCheckoutData()`
|
|
- Anzeige im Checkout-Formular und optional im Admin-/Bestelldetail
|
|
- später exportierbar für Marketingauswertung
|
|
|
|
Zu klären:
|
|
|
|
- Freitext oder Auswahl plus Freitext?
|
|
- Pflicht nur im Webshop/Bestelllink oder auch bei Salescenter-, Homeparty- und Collection-Flows?
|
|
- Soll eine konkrete Beraterzuordnung daraus entstehen oder nur Tracking?
|
|
|
|
### 5. Stornoprozess
|
|
|
|
Die Grundlogik existiert. Vor einer fachlichen Freigabe braucht es Tests und eine Periodenentscheidung.
|
|
|
|
Prüfpunkte:
|
|
|
|
- Storno einer Beraterbestellung erzeugt negative Punkte beim richtigen Berater.
|
|
- Storno einer Kunden-/Shopbestellung erzeugt negative Punkte im richtigen Umsatztyp.
|
|
- Storno einer Abo-Bestellung wirkt korrekt auf Incentive-Logs.
|
|
- Storno ohne vorhandenen `UserSalesVolume` ist sichtbar und lösbar, nicht nur ein Log-Eintrag.
|
|
- Businessdaten nach Storno werden für betroffenen Monat/Jahr aktualisiert oder als neu zu berechnen markiert.
|
|
|
|
### 6. Rechtliches & Sichtbarkeit in Incentives
|
|
|
|
Die bestehende Teilnahmezustimmung sollte nicht automatisch als Freigabe für öffentliche Namens-/Fotoanzeige interpretiert werden.
|
|
|
|
Vorschlag:
|
|
|
|
- eigenes Feld auf `incentive_participants`, z. B. `ranking_visibility_accepted_at`
|
|
- Button/Checkbox in der Incentive-Seite: "Ich stimme zu, dass mein Name, Foto und Land in der Rangliste sichtbar sind"
|
|
- Anzeige von Name, Foto und Land nur, wenn die Zustimmung vorliegt oder ein Admin/VIP die Ansicht nutzt
|
|
- nach juristischer Klärung kann die Regel angepasst werden
|
|
|
|
Technische Ergänzungen:
|
|
|
|
- Ranking um Foto und Land erweitern
|
|
- Pagination/Limit bewusst definieren: alle Teilnehmer anzeigen, aber paginiert
|
|
- Übersetzungen in `resources/lang/*/incentive.php` ergänzen
|
|
|
|
### 7. Multimedia-Bereich / Event-Archiv
|
|
|
|
Es gibt bereits Dashboard-News und ein News-Archiv. Für Events sind zwei Varianten möglich:
|
|
|
|
Variante A: `DashboardNews` um Typ "event" erweitern
|
|
|
|
- weniger Aufwand
|
|
- bestehendes Admin-Modul kann wiederverwendet werden
|
|
- geeignet, wenn Events im gleichen Format wie News funktionieren
|
|
|
|
Variante B: eigenes Event-Modul
|
|
|
|
- sauberere Trennung
|
|
- eigene Felder für Galerie, Eventdatum, Call-/Foto-Typ
|
|
- sinnvoll, wenn Uploads, mehrere Bilder pro Event oder Kategorien benötigt werden
|
|
|
|
Empfehlung: Variante A als MVP, falls keine komplexe Galerieverwaltung benötigt wird.
|
|
|
|
## Technisches Zielkonzept
|
|
|
|
### Neue zentrale Services
|
|
|
|
Empfohlen:
|
|
|
|
- `App\Services\Backoffice\BackofficeDashboardService`
|
|
- `App\Services\Backoffice\BackofficeDrilldownService`
|
|
|
|
Aufgaben `BackofficeDashboardService`:
|
|
|
|
- Zeitraum normalisieren
|
|
- Downline pro Linie aufbauen
|
|
- Summen pro Linie berechnen
|
|
- Daten für Stufe 1 und Stufe 2 liefern
|
|
- Caching-/Snapshot-Strategie kapseln
|
|
|
|
Aufgaben `BackofficeDrilldownService`:
|
|
|
|
- Kennzahlenfilter aus Request validieren
|
|
- Personen-/Abo-/Umsatzlisten erzeugen
|
|
- Berechtigungen gegen Downline prüfen
|
|
- einheitliche Summary für Listen liefern
|
|
|
|
### Controller und Views
|
|
|
|
Empfohlen:
|
|
|
|
- `App\Http\Controllers\User\BackofficeStatisticsController`
|
|
- Views unter `resources/views/user/backoffice/statistics/`
|
|
|
|
Geplante Actions:
|
|
|
|
- `index()` für Stufe 1
|
|
- `line(int $line)` für Stufe 2
|
|
- `details()` für Stufe 3
|
|
- optional `export()` für CSV/Excel später
|
|
|
|
Die vorhandenen Team-Views bleiben bestehen. Das neue Dashboard verweist für Detailseiten aber auf eigene, schlankere Statistik-Views.
|
|
|
|
### Datenmodell und Definitionen
|
|
|
|
Einheitliche Metriken:
|
|
|
|
- `consultants`: aktive Berater in Linie
|
|
- `own_abos`: eigene Beraterabos des eingeloggten Users
|
|
- `team_partner_abos`: Beraterabos im Team (`is_for = 'me'`)
|
|
- `direct_customer_abos`: Kundenabos des betrachteten Beraters (`member_id = user_id`, `is_for = 'ot'`)
|
|
- `team_customer_abos`: Kundenabos der Downline-Berater (`member_id in teamUserIds`, `is_for = 'ot'`)
|
|
- `new_partners`: neue aktive Partner im Zeitraum
|
|
- `turnover_points`: Punkte aus `UserSalesVolume`/`UserBusiness`
|
|
- `turnover_net`: Netto-Umsatz aus `UserSalesVolume`/`UserBusiness`
|
|
- `shop_1000`: Partner mit Kunden-/Shop-Punkten >= 1000
|
|
|
|
### Berechtigungen
|
|
|
|
Jede Detailansicht muss sicherstellen:
|
|
|
|
- Der eingeloggte User sieht nur eigene Downline-Daten.
|
|
- Ein direkt angefragter `user_id` muss per Sponsor-Hierarchie im Team liegen.
|
|
- Kundenabos werden nur in dem Umfang angezeigt, der fachlich für Berater vorgesehen ist.
|
|
- Datenschutzrelevante Kundendaten sollten auf das notwendige Minimum reduziert werden.
|
|
|
|
## Umsetzungsphasen
|
|
|
|
### Phase 1: Begriffe, Datenbasis und MVP Dashboard
|
|
|
|
- Fachliche Definitionen finalisieren
|
|
- `BackofficeDashboardService` erstellen
|
|
- Stufe-1-Linienübersicht mit Linien 1 bis 8 und Summenzeile bauen
|
|
- bestehende Dashboard-Kachel durch Link auf neue Statistikseite ergänzen oder neue Seite im Menü aufnehmen
|
|
- Kennzahlen noch ohne vollständigen Deep Dive, aber bereits sauber berechnet
|
|
|
|
### Phase 2: Drill-down Stufe 2 und Stufe 3
|
|
|
|
- Linien-Detailansicht pro Firstline bauen
|
|
- Detailansichten je Kennzahl bauen
|
|
- Abo-Listen mit Name, Punktewert, nächster Ausführung und Anzahl Lieferungen anzeigen
|
|
- Links aus jeder Kennzahl setzen
|
|
- leere Zustände und Summenzeilen ergänzen
|
|
|
|
### Phase 3: 1000 Punkte Shop
|
|
|
|
- fachliche Definition final bestätigen
|
|
- Query und Summary implementieren
|
|
- Widget in Übersicht ergänzen
|
|
- Detailansicht mit Sortierung nach Volumen absteigend bauen
|
|
|
|
### Phase 4: Herkunftsabfrage im Checkout
|
|
|
|
- Migration und Model-Fillable ergänzen
|
|
- Checkout-Formular erweitern
|
|
- Validierung und Speicherung ergänzen
|
|
- Admin-/Bestelldetail oder Export um Feld erweitern
|
|
|
|
### Phase 5: Storno-Qualitätssicherung
|
|
|
|
- Tests für vorhandene Storno-Punktepfade ergänzen
|
|
- Fachentscheidung zur Periodenlogik dokumentieren
|
|
- Fehlerfall ohne Original-`UserSalesVolume` sichtbar machen
|
|
- ggf. Businessdaten-Neuberechnung nach Storno anstoßen
|
|
|
|
### Phase 6: Incentive-Sichtbarkeit und Event-Archiv
|
|
|
|
- rechtliche Entscheidung einarbeiten
|
|
- separates Ranking-Sichtbarkeits-Opt-in ergänzen
|
|
- Foto/Land im Ranking anzeigen
|
|
- Event-Archiv als `DashboardNews`-Typ oder eigenes Modul umsetzen
|
|
|
|
## Teststrategie
|
|
|
|
Feature-Tests:
|
|
|
|
- Dashboard zeigt nur Daten der eigenen Downline.
|
|
- Linien 1 bis 8 werden korrekt gruppiert.
|
|
- Summenzeile entspricht Summe der Linien.
|
|
- Klick auf Teamabos zeigt nur `is_for = 'me'` in der Downline.
|
|
- Klick auf Kundenabos im Team zeigt nur `is_for = 'ot'` mit `member_id` in der Downline.
|
|
- 1000-Punkte-Shop listet nur Partner über Schwelle und sortiert absteigend.
|
|
- Checkout verlangt die Herkunftsabfrage und speichert sie.
|
|
- Storno erzeugt negativen `UserSalesVolume`-Eintrag und aktualisiert Monatswerte.
|
|
- Incentive-Ranking zeigt Name/Foto/Land nur nach passender Zustimmung.
|
|
|
|
Unit-Tests:
|
|
|
|
- Service aggregiert Linien korrekt.
|
|
- Service verhindert Zugriff auf fremde Team-User.
|
|
- Metrikdefinitionen liefern stabile Counts bei aktiven, gekündigten und zukünftigen Abos.
|
|
|
|
Regressionsprüfung:
|
|
|
|
- bestehende Teamseiten `user.team.*`
|
|
- bestehende Abo-Seiten
|
|
- bestehendes Incentive-Ranking
|
|
- Checkout für Webshop, Bestelllink und Salescenter-Flows
|
|
|
|
## Offene Fachfragen
|
|
|
|
1. Soll die neue Statistik die aktuelle Monatslogik nutzen oder standardmäßig den letzten abgeschlossenen Monat zeigen?
|
|
2. Sollen Stornos im Stornomonat oder im ursprünglichen Umsatzmonat gegengerechnet werden?
|
|
3. Wie genau wird "1000 Punkte Shop" definiert: nur Shop-Punkte, alle Kundenpunkte oder Kundenabos plus Einzelbestellungen?
|
|
4. Welche Kundendaten dürfen Berater in Deep-Dive-Listen sehen?
|
|
5. Ist die Herkunftsabfrage Freitext, Auswahlfeld oder Kombination?
|
|
6. Gilt die Herkunftsabfrage für alle Checkout-Flows oder nur für externe Kundenbestellungen?
|
|
7. Darf eine Incentive-Teilnahme bereits Name/Foto/Land freigeben oder braucht es ein separates Opt-in?
|
|
8. Soll das Event-Archiv nur Bilder und Texte enthalten oder eine echte Galerie mit Mehrfachuploads?
|
|
|
|
## Empfehlung
|
|
|
|
Die Backoffice-Statistik sollte als eigenes kleines Modul im User-Bereich umgesetzt werden, nicht als weitere Logik in `dashboard/_statistics.blade.php`. Die vorhandenen Datenquellen sind ausreichend für ein MVP, aber sie müssen zentral aggregiert, fachlich sauber benannt und über berechtigte Drill-down-Routen zugänglich gemacht werden.
|
|
|
|
Priorität für die erste Umsetzung:
|
|
|
|
1. Daten- und Begriffsdefinitionen finalisieren
|
|
2. zentrale Services und Stufe-1-Linienübersicht
|
|
3. Drill-down für Abos und Neupartner
|
|
4. 1000-Punkte-Shop
|
|
5. Checkout-Herkunft und Storno-Tests
|
|
6. Incentive-Sichtbarkeit und Event-Archiv
|