Abo-Uebersichten: Team-Ansicht konsolidiert, Monatsfilter, Wachstum & Dashboard-KPIs
- /user/abos/ot: Filter nach Eingangsmonat (start_date) ueber neuen UserAbo-Scope - Konsolidierte Team-Abo-Ansicht nach Ebenen/Linien (Bestand, neue Abos im Monat, Eigen-/Kundenabos, Punkte je Ebene + Summen) via TeamAboOverviewService - team/customers leitet auf konsolidierte Ansicht um; Navigation bereinigt - Mitglieder-Detail-Modal mit Abo-Zusammenfassung (Eigen-Abo, Kundenabos, Punkte, Beginn, naechste Ausfuehrung, Ausfuehrungen) - Wachstums-Tabelle (Jahr x Monate) + Liniendiagramm (neue Eigen-/Kundenabos) - Dashboard-KPI-Kachel (Gesamtabos, Kundenabos, 1000-Punkte-Shops) - i18n de/en/es/fr, Tests (Filter, Overview, Wachstum, Modal, Redirect) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
65b867f8ee
commit
4135726772
15 changed files with 967 additions and 174 deletions
320
dev/2026-06-23-abo/ENTWICKLUNGSPLAN-ABO-UEBERSICHTEN.md
Normal file
320
dev/2026-06-23-abo/ENTWICKLUNGSPLAN-ABO-UEBERSICHTEN.md
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
# Entwicklungsplan: Abo-Übersichten erweitern (eigene Kundenabos, Team-Abos, Dashboard)
|
||||
|
||||
> **Status:** In Planung · **Erstellt:** 2026-06-23 · **Briefing:** Kundenanfrage + `docs/salescenter/Todos Backoffice.md`
|
||||
|
||||
## Dokumentations-Hinweis (verbindlich)
|
||||
|
||||
Dieser Plan wird **Schritt für Schritt** abgearbeitet. Für **jede Phase** gilt:
|
||||
|
||||
- Der **Umsetzungsstatus** in diesem Dokument wird nach Abschluss eines Schritts auf `ERLEDIGT` gesetzt (mit Datum, betroffenen Dateien, Zeilenangaben und kurzer Begründung).
|
||||
- **Alle Phasen, Hinweise und getroffenen Detail-Entscheidungen** werden sauber dokumentiert – auch Abweichungen vom Plan und Verworfenes (mit Begründung).
|
||||
- Jede Änderung wird **programmatisch getestet** (Pest), bevor die Phase als erledigt gilt.
|
||||
- Nach Code-Änderungen läuft `./vendor/bin/pint --dirty`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Ziel & Briefing-Zusammenfassung
|
||||
|
||||
Die Darstellung/Auflistung der Abos im Sales Center (`my.mivita.care`) soll erweitert werden. Vier Bausteine:
|
||||
|
||||
1. **Eigene Kundenabos** (`/user/abos/ot`): Filter nach **Monat & Jahr**, in dem das Abo hinzugekommen ist (Eingangsmonat).
|
||||
2. **Team-Abo-Ansichten zusammenführen** (`/user/abos/team/show` + `/user/abos/team/customers`): Beide Seiten überschneiden sich stark und sollen zu **einer** Ansicht „Abos im Team" verschmelzen. Inhalt:
|
||||
- Wer im Team hat wie viele **Kundenabos** abgeschlossen?
|
||||
- **Sortierung nach Monaten:** Wer im Team hat diesen Monat (Monatsfilter) wie viele **neue** Abos (Kunden- und Eigen-Abos) abgeschlossen?
|
||||
- Wer im Team hat **selbst** ein Abo abgeschlossen?
|
||||
- **Gesamtübersicht:** Wie viele Abos haben Team-Mitglieder insgesamt?
|
||||
- **Sortierung nach Ebenen (Linien):** Wichtigste Ebene ist die **1. Ebene** (Wer hat dort ein Abo, wer nicht?), optional ausbaubar auf den gesamten Baum.
|
||||
3. **Dashboard ergänzen:** Anzahl der **„1000-Punkte-Shops"** und **Gesamtabos im Team**.
|
||||
|
||||
---
|
||||
|
||||
## 2. Ist-Zustand (Analyse-Ergebnis)
|
||||
|
||||
### 2.1 Eigene Kundenabos `/user/abos/ot`
|
||||
|
||||
| Bereich | Status heute | Schlüsseldateien |
|
||||
| ------- | ------------ | ---------------- |
|
||||
| Controller | `AboController@index($view='ot')` lädt `UserAbo` (`member_id = Auth`, `is_for=ot`, `status>=1`), liefert bereits `chartData` (Jahresfilter) | `app/Http/Controllers/User/AboController.php:62-83` |
|
||||
| View | Card-Liste pro Abo, oben Monats-Chart (`_abo_chart`) mit **Jahres**-Umschaltung | `resources/views/user/abo/index.blade.php`, `resources/views/user/abo/_abo_chart.blade.php` |
|
||||
| Monatszählung | `AboHelper::getMonthlyAboCounts()` (Snapshot vergangener Monate + Live aktueller Monat) | `app/Services/AboHelper.php:514-565` |
|
||||
| Filter | **Nur Jahr** (Chart). Keine Filterung der Card-Liste nach Eingangsmonat. | – |
|
||||
|
||||
**Fazit:** Jahresfilter existiert über den Chart. Es fehlt ein **Monat+Jahr-Filter auf die Liste** (Abos, deren `start_date` im gewählten Monat liegt).
|
||||
|
||||
### 2.2 Team-Abos `/user/abos/team/show` & `/user/abos/team/customers`
|
||||
|
||||
| Route | Methode | Inhalt heute |
|
||||
| ----- | ------- | ------------ |
|
||||
| `user_abos_team_show` | `TeamController@showAbos` | Flache Card-Liste **aller eigenen Team-Abos** (`is_for=me`, `user_id ∈ Team`), Jahres-Chart `team_abos`. Eine Card pro Abo. |
|
||||
| `user_abos_team_customers` | `TeamController@showTeamCustomerAbos` | Kundenabos im Team (`is_for=ot`, `member_id ∈ Team`), **gruppiert pro Team-Mitglied** (collapsible), anonymisiert, Jahres-Chart `team_cust_abos`. |
|
||||
|
||||
- Beide nutzen `AboHelper::getTeamUserIds($userId)` (rekursive Downline über `m_sponsor`, **flach**, ohne Linien-Information).
|
||||
- Beide nutzen denselben `_abo_chart`-Partial (nur Jahr).
|
||||
- **Überschneidung:** Beide listen Team-Abos, nur unterschiedlich (eigene Abos vs. Kundenabos) und unterschiedlich gruppiert. Keine Ebenen-/Linien-Sortierung, keine „neue Abos diesen Monat"-Aggregation pro Person.
|
||||
- Detailseite: `TeamController@detailAbo` (`user_abos_team_detail`).
|
||||
|
||||
### 2.3 Dashboard
|
||||
|
||||
| Bereich | Status heute | Datei |
|
||||
| ------- | ------------ | ----- |
|
||||
| Dashboard-Home | Karten-Grid; Abo-Bezug nur: Einmalprodukt-Card (`_abo_onetime`) | `resources/views/home.blade.php`, `app/Http/Controllers/HomeController.php:45-92` |
|
||||
| Team-/Abo-KPIs | **Nicht vorhanden** auf dem Dashboard | – |
|
||||
|
||||
### 2.4 Bereits vorhandenes Backoffice-Statistik-Modul (WICHTIG – Wiederverwendung!)
|
||||
|
||||
Es existiert ein **VIP-only** Modul, das den Großteil der gewünschten Team-Logik bereits abbildet:
|
||||
|
||||
| Komponente | Datei | Liefert |
|
||||
| ---------- | ----- | ------- |
|
||||
| Controller | `app/Http/Controllers/User/BackofficeStatisticsController.php` | Übersicht / Drilldown / CSV-Export, Monat+Jahr-Filter (Session-persistiert), nur `isVIP()` |
|
||||
| Dashboard-Service | `app/Services/Backoffice/BackofficeDashboardService.php` | **`lineBuckets($rootUserId)`** = Downline gruppiert nach **Linien/Ebenen** (1..n); pro Linie: Berater-Zahl, Neupartner, **Teamabos** (`team_partner_abos`), **neue Teamabos** (`team_partner_abos_new`), **Teamkundenabos** (`team_customer_abos`), **neue** (`team_customer_abos_new`), Punkte-Aufschlüsselung, **`shop_1000`** (1000-Punkte-Shop-Zähler), Umsatz; plus **`totals`**-Zeile. Snapshots für abgeschlossene Monate. |
|
||||
| Drilldown-Service | `app/Services/Backoffice/BackofficeDrilldownService.php` | Personenlisten je Linie+Metrik (Namen, Punkte, Status, Besteht-seit, nächste Ausführung). |
|
||||
| Snapshot-Modell | `app/Models/BackofficeStatisticsSnapshot.php` | Eingefrorene Monatswerte pro User. |
|
||||
|
||||
> **Schlüssel-Erkenntnis:** Die in der Kundenanfrage gewünschte Ebenen-/Monats-/Gesamtlogik **existiert technisch schon** in `BackofficeDashboardService`. Wir bauen **nicht neu**, sondern (a) machen diese Datenquelle für die Abo-Ansicht wiederverwendbar und (b) liefern eine schlankere, für **alle Berater** zugängliche Abo-fokussierte Ansicht + Dashboard-Widgets.
|
||||
|
||||
Definition **„1000-Punkte-Shop"** (laut Briefing, bereits im Service implementiert): Teampartner, die **mind. 1000 Punkte Kundenumsatz** im gewählten Monat erzielen (`shop1000Count()`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Offene Fragen / Annahmen
|
||||
|
||||
| # | Thema | Annahme (sofern nicht anders entschieden) |
|
||||
| - | ----- | ----------------------------------------- |
|
||||
| A1 | „Eingangsmonat" eines Abos | = `start_date` (Anlage-/Aktivierungsdatum). Filter zeigt Abos mit `start_date` im gewählten Monat/Jahr. | JA
|
||||
| A2 | Zugänglichkeit der neuen Team-Ansicht | Für **alle aktiven Berater** (nicht nur VIP), da rein abo-bezogen und über die eigene Downline. Das umfangreiche Punkte-/Umsatz-Backoffice bleibt VIP-only. | JA
|
||||
| A3 | Umfang Ebenen | **1. Ebene zwingend** als Default sichtbar; weitere Linien aufklappbar; „gesamter Baum" als Summenzeile/optionaler Modus. | JA
|
||||
| A4 | „selbst ein Abo abgeschlossen" | Eigen-Abo = `UserAbo is_for=me` des Team-Mitglieds (Spalte/Badge pro Person: ja/nein + Punkte). | JA
|
||||
| A5 | Zusammenführen der zwei Routen | Neue konsolidierte Seite unter `user_abos_team_show`; `team/customers` wird Weiterleitung/Tab oder entfällt aus der Navigation (Route bleibt vorerst als Redirect). | Redirect
|
||||
| A6 | Dashboard-Widgets-Zielgruppe | Alle aktiven Berater sehen „Gesamtabos im Team" + „1000-Punkte-Shops"; klickbar → neue Team-Abo-Ansicht. | JA
|
||||
|
||||
> **Diese Annahmen bitte vor Umsetzungsbeginn bestätigen oder korrigieren.**
|
||||
|
||||
---
|
||||
|
||||
## 4. Lösungsvorschlag (Architektur)
|
||||
|
||||
### 4.1 Gemeinsame Datenquelle: `TeamAboOverviewService` (neu)
|
||||
|
||||
Neuer Service `app/Services/Abo/TeamAboOverviewService.php`, der die Linien-/Monats-/Gesamtlogik **abo-fokussiert** kapselt und intern `BackofficeDashboardService::lineBuckets()` (oder eine extrahierte, gemeinsam genutzte Helper-Methode) wiederverwendet.
|
||||
|
||||
Liefert je Linie:
|
||||
- `line` (1..n), `consultants` (Anzahl Berater dieser Ebene)
|
||||
- `members_with_own_abo` / `members_total` (wer hat selbst ein Abo)
|
||||
- `team_partner_abos` (Summe Eigen-Abos der Ebene) + `_new` (neu im Monat)
|
||||
- `team_customer_abos` (Summe Kundenabos der Ebene) + `_new`
|
||||
- pro Person (für Drilldown/aufgeklappte Ebene): Name, Karriere-Level, Eigen-Abo (ja/Punkte), #Kundenabos + Punkte, #Teamabos darunter
|
||||
- `totals`-Zeile über alle Linien
|
||||
|
||||
Vorteil: Eine zentrale, getestete Datenquelle für **Team-Ansicht** und **Dashboard-Widgets**. Refactoring-Hinweis: Falls `lineBuckets()`/`newAboCount()`/`shop1000Count()` aus `BackofficeDashboardService` extrahiert werden, in einen gemeinsamen `Trait`/Helper auslagern, um Duplikate zu vermeiden.
|
||||
|
||||
### 4.2 Phase-Übersicht
|
||||
|
||||
| Phase | Inhalt | Aufwand |
|
||||
| ----- | ------ | ------- |
|
||||
| **P1** | `/user/abos/ot`: Monat+Jahr-Filter auf die Liste | klein |
|
||||
| **P2** | `TeamAboOverviewService` (Datenquelle + Tests) | mittel |
|
||||
| **P3** | Konsolidierte Team-Abo-Ansicht (Linien/Ebenen, Monatsfilter, neue Abos, Eigen-Abo-Spalte, Summen) | mittel-groß |
|
||||
| **P4** | Zusammenführung `team/customers` → Redirect/Tab, Navigation anpassen | klein |
|
||||
| **P5** | Dashboard-Widgets „Gesamtabos im Team" + „1000-Punkte-Shops" (klickbar) | klein-mittel |
|
||||
| **P6** | i18n (de/en/es/fr), Pint, Gesamttest | klein |
|
||||
|
||||
---
|
||||
|
||||
## 5. Detailplanung pro Phase
|
||||
|
||||
### Phase 1 — `/user/abos/ot`: Monat- & Jahr-Filter
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- `app/Models/UserAbo.php`: Query-Scope `scopeAddedInMonth($query, $year, $month)` (Filter nach `start_date`; `month=0` lässt Abfrage unverändert).
|
||||
- `app/Http/Controllers/User/AboController.php` (`index('ot')`): wertet `month`-Param aus, nutzt `addedInMonth()`, übergibt `filterMonth`/`filterYear` an die View.
|
||||
- `resources/views/user/abo/index.blade.php`: Filterleiste (Monats-Dropdown + Jahr + Filtern/Zurücksetzen) über der Card-Liste (nur `view==='ot'`).
|
||||
- i18n: `abo.filter`, `abo.reset`, `abo.filter_added_period` in de/en/es/fr.
|
||||
- Test: `tests/Feature/AboOtMonthFilterTest.php` (2 Tests grün).
|
||||
|
||||
- `AboController@index('ot')`: zusätzlich `month`-Parameter (Default „alle") auswerten.
|
||||
- Liste filtern: `whereYear('start_date', $year)` + optional `whereMonth('start_date', $month)`.
|
||||
- View `user/abo/index.blade.php`: Filterleiste (Monats-Dropdown + Jahr) über der Card-Liste; Chart bleibt. Wiederverwendung von `HTMLHelper::getTransMonths()` / `getYearRange()`.
|
||||
- Filter-Persistenz analog zu bestehenden Mustern (Query-Param genügt; Session optional).
|
||||
- **Test:** `tests/Feature` – Abos mit `start_date` in verschiedenen Monaten anlegen, Filter prüft korrekte Teilmenge.
|
||||
|
||||
### Phase 2 — `TeamAboOverviewService`
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- `app/Models/UserAbo.php`: Scope `scopeActiveAbo()` (active=true, status ∉ {4,5,6}) – konsistent mit `BackofficeDashboardService`.
|
||||
- `app/Services/Abo/TeamAboOverviewService.php`: `linesOverview(User,$month,$year)` liefert je Ebene Berateranzahl, „mit Eigen-Abo", Eigen-Abos (+Punkte +neu), Kundenabos (+Punkte +neu), pro-Mitglied-Details und eine Summenzeile. Wiederverwendung von `BackofficeDashboardService::lineBuckets()` (keine Duplizierung der Baum-Traversierung).
|
||||
- i18n: `abo.team_total`, `abo.team_line` in de/en/es/fr.
|
||||
- Test: `tests/Feature/TeamAboOverviewTest.php` (2 Tests, 19 Assertions grün). Hinweis: Test-Schema hat keine `products.slug`-Spalte → `beforeEach` ergänzt sie (etabliertes Muster aus `MembershipQtyProtectionTest`).
|
||||
|
||||
- Neuer Service mit Methoden:
|
||||
- `linesOverview(User $user, int $month, int $year): array` (Linien + Totals, abo-fokussiert)
|
||||
- `lineMembers(User $user, int $line, int $month, int $year): Collection` (Personen einer Ebene mit Abo-Kennzahlen)
|
||||
- Wiederverwendung der vorhandenen `lineBuckets()`-Logik (gemeinsam nutzbar machen).
|
||||
- „neue Abos im Monat": Logik aus `BackofficeDashboardService::newAboCount()` wiederverwenden (Definition: `start_date` im Monat, aktiver Status).
|
||||
- **Test:** Unit/Feature – Downline mit mehreren Ebenen + Abos in verschiedenen Monaten; prüft Linien-Zuordnung, neue-Abo-Zähler, Eigen-Abo-Flag, Summen.
|
||||
|
||||
### Phase 3 — Konsolidierte Team-Abo-Ansicht
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- `TeamController@showAbos` nutzt `TeamAboOverviewService` + Monat/Jahr-Filter (`selectedAboPeriod()`, Session-persistiert).
|
||||
- Neue View `resources/views/user/team/abos.blade.php`: Monats-/Jahresfilter, Summen-Cards (Gesamtabos, Eigen-Abos, Kundenabos, Mitglieder mit Abo), Linien-/Ebenen-Tabelle (1. Ebene hervorgehoben + standardmäßig offen), aufklappbare Mitgliederliste je Ebene (Eigen-Abo ja/nein, #Kundenabos, Punkte), Summenzeile.
|
||||
- i18n: viele neue `abo.*`-Keys (filter_period, team_total_abos, team_own_abos, team_members_with_abo, team_by_level, new_this_month, with_own_abo, consultants, level, own_abo, customer_abos_count, career_level, of, yes, no) in de/en/es/fr.
|
||||
- Test: Render-Test in `tests/Feature/TeamAboOverviewTest.php` (3 Tests grün).
|
||||
|
||||
- `TeamController@showAbos` umstellen auf `TeamAboOverviewService` + Monat/Jahr-Filter (Session-persistiert, analog `BackofficeStatisticsController::selectedPeriod()`).
|
||||
- Neue View `resources/views/user/team/abos.blade.php` (umbauen):
|
||||
- **Kopf:** Monats-/Jahresfilter + Summen-Card (Gesamt-Teamabos, Gesamt-Kundenabos im Team, neue diesen Monat, #1000-Punkte-Shops).
|
||||
- **Linien-Tabelle:** Zeile je Ebene (1. Linie zuerst, hervorgehoben): Berater, „mit Eigen-Abo", Eigen-Abos (Punkte), Kundenabos (Anzahl+Punkte), neue Abos (Monat). Summenzeile unten.
|
||||
- **Aufklappbar pro Ebene:** Personenliste (Name, Karriere-Level, Eigen-Abo ja/nein, #Kundenabos, Punkte). 1. Ebene standardmäßig offen.
|
||||
- Detail-Link je Abo → `user_abos_team_detail` bleibt erhalten.
|
||||
- Wiederverwendung des `_abo_chart`-Partials für den Monatsverlauf (optional beibehalten).
|
||||
- **Test:** Feature – View rendert Linien korrekt, 1. Ebene sichtbar, Summen stimmen.
|
||||
|
||||
### Phase 4 — Zusammenführung `team/customers`
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- `TeamController@showTeamCustomerAbos` leitet dauerhaft auf `user_abos_team_show` um (Route bleibt für Altlinks). Kundenabos sind als Spalte/Drilldown in die konsolidierte Ansicht eingeflossen.
|
||||
- Navigation `layout-sidenav.blade.php`: Menüpunkt „Team Kunden" entfernt; „Teamabos" markiert nun auch die `team/customers`-URL aktiv.
|
||||
- `resources/views/user/team/customer_abos.blade.php` bleibt vorerst bestehen (nicht mehr verlinkt), um nichts ungewollt zu löschen.
|
||||
- Test: `tests/Feature/TeamCustomerAbosRedirectTest.php` (Redirect grün).
|
||||
|
||||
- Kundenabos-Inhalt als **Tab/Abschnitt** in die konsolidierte Ansicht integrieren (gruppiert pro Mitglied bleibt als Drilldown erhalten).
|
||||
- `user_abos_team_customers` → Redirect auf `user_abos_team_show` (Route bleibt für Bookmarks bestehen).
|
||||
- Navigation `layout-sidenav.blade.php`: Punkt „Team Kunden" entfernen/zusammenführen; Label gem. Briefing „**Kundenabos im Team**" / „Teamkundenabos" verwenden (Terminologie-Korrektur).
|
||||
- **Test:** Redirect-Test; Navigation-Smoke.
|
||||
|
||||
### Phase 5 — Dashboard-Widgets
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- `BackofficeDashboardService::shop1000Count()` auf `public` gesetzt (Wiederverwendung).
|
||||
- `TeamAboOverviewService::teamKpis(User,$month,$year)`: leichtgewichtige KPIs (Gesamtabos, Teamabos, Teamkundenabos, 1000-Punkte-Shops) ohne teure Punkte-/Mitglieder-Aggregation.
|
||||
- `HomeController@show`: berechnet `teamAboKpis` für aktive Berater (aktueller Monat).
|
||||
- Neues Partial `resources/views/dashboard/_abo_team_kpis.blade.php`: klickbare KPI-Card (→ `user_abos_team_show`), eingebunden in `home.blade.php`.
|
||||
- i18n: `abo.shop_1000` in de/en/es/fr.
|
||||
- Test: KPI-Test in `tests/Feature/TeamAboOverviewTest.php` (4 Tests grün).
|
||||
|
||||
- `HomeController@show`: für aktive Berater via `TeamAboOverviewService` (bzw. `BackofficeDashboardService::overview()`-Totals für den aktuellen Monat) zwei KPIs berechnen:
|
||||
- **Gesamtabos im Team** (`team_partner_abos` + `team_customer_abos` der Totals, oder getrennt anzeigen).
|
||||
- **1000-Punkte-Shops** (`shop_1000` Totals).
|
||||
- Neuer Partial `resources/views/dashboard/_abo_team_kpis.blade.php`: zwei klickbare KPI-Cards → Link auf neue Team-Abo-Ansicht (bzw. Backoffice-Statistik bei VIP).
|
||||
- Performance: Für das Dashboard nur **eine** Monatsberechnung; bei großen Teams ggf. Snapshot/Cache des aktuellen Monats nutzen (kein Live-Vollscan bei jedem Dashboard-Aufruf – ggf. Caching mit kurzer TTL).
|
||||
- **Test:** Feature – KPIs erscheinen für aktiven Berater mit Team-Abos; Werte stimmen.
|
||||
|
||||
### Phase 6 — i18n & Abschluss
|
||||
|
||||
**Status:** ERLEDIGT (2026-06-23)
|
||||
|
||||
**Umsetzung:**
|
||||
- i18n: alle neuen `abo.*`-Keys in de/en/es/fr gepflegt; `LocalizationSyncTest` grün (Sprachen synchron).
|
||||
- Pint: `--dirty` → pass.
|
||||
- Tests: 29 relevante Tests grün (Phase 1–5 + bestehende Abo-Tests), `LocalizationSyncTest` (3 Tests) grün.
|
||||
|
||||
- Neue Übersetzungsschlüssel in `resources/lang/{de,en,es,fr}/abo.php` + `navigation.php`/`team.php` (Filter-Labels, Spaltenköpfe, KPI-Titel, „1000-Punkte-Shop", „Kundenabos im Team", „neue Abos").
|
||||
- `./vendor/bin/pint --dirty`.
|
||||
- Gesamttest der betroffenen Feature-/Unit-Dateien.
|
||||
|
||||
---
|
||||
|
||||
## 6. Zu beachtende Punkte / Risiken
|
||||
|
||||
1. **Keine Logik-Duplikate:** `BackofficeDashboardService` ist die Referenz für Linien/neue Abos/1000-Punkte-Shop. Gemeinsame Methoden extrahieren statt kopieren.
|
||||
2. **Performance:** Downline-Traversierung (`lineBuckets`) kann bei großen Teams teuer sein. Dashboard-Widgets cachen oder Snapshot des aktuellen Monats nutzen; nicht bei jedem Request live voll durchrechnen.
|
||||
3. **Zugriffsrechte/Datenschutz:** Kundenabos im Team sind heute **anonymisiert** dargestellt (`customer_privacy_info`). Diese Anonymisierung beibehalten; Klarnamen nur dort, wo bisher erlaubt (Team-Mitglieder = Berater). VIP-/Datenschutz-Hinweise aus dem bestehenden Backoffice-Modul übernehmen.
|
||||
4. **Status-Definition Abo aktiv:** Konsistent mit `getMonthlyAboCounts()`/`activeAboQuery()` halten (Terminal-Status 4/5 ausschließen).
|
||||
5. **Snapshots:** Vergangene Monate aus `AboChartSnapshot` bzw. `BackofficeStatisticsSnapshot` lesen (nicht neu berechnen). Aktueller Monat live.
|
||||
6. **Route-Kompatibilität:** `user_abos_team_customers` nicht hart entfernen (Bookmarks/Links) → Redirect.
|
||||
7. **Multi-Tenant/Routing:** Änderungen liegen in `routes/domains/crm.php` (CRM-Domain). Keine Auswirkungen auf andere Domains.
|
||||
|
||||
---
|
||||
|
||||
## 7. Betroffene Dateien (Vorschau)
|
||||
|
||||
**Neu:**
|
||||
- `app/Services/Abo/TeamAboOverviewService.php`
|
||||
- `resources/views/dashboard/_abo_team_kpis.blade.php`
|
||||
- `tests/Feature/TeamAboOverviewTest.php`, `tests/Feature/AboOtMonthFilterTest.php`, `tests/Feature/DashboardAboKpisTest.php`
|
||||
|
||||
**Geändert:**
|
||||
- `app/Http/Controllers/User/AboController.php` (P1)
|
||||
- `app/Http/Controllers/User/TeamController.php` (P3/P4)
|
||||
- `app/Http/Controllers/HomeController.php` (P5)
|
||||
- `app/Services/Backoffice/BackofficeDashboardService.php` (gemeinsame Methoden extrahieren)
|
||||
- `resources/views/user/abo/index.blade.php` (P1)
|
||||
- `resources/views/user/team/abos.blade.php` (P3)
|
||||
- `resources/views/user/team/customer_abos.blade.php` (P4 – Integration/Redirect)
|
||||
- `resources/views/home.blade.php` (P5)
|
||||
- `resources/views/layouts/includes/layout-sidenav.blade.php` (P4)
|
||||
- `routes/domains/crm.php` (P4 – Redirect)
|
||||
- `resources/lang/{de,en,es,fr}/abo.php`, `navigation.php`, `team.php` (P6)
|
||||
|
||||
---
|
||||
|
||||
## 8. Umsetzungsreihenfolge (empfohlen)
|
||||
|
||||
P1 (schneller Mehrwert, isoliert) → P2 (Datenbasis) → P3 (Hauptansicht) → P4 (Konsolidierung/Navi) → P5 (Dashboard) → P6 (i18n/Abschluss).
|
||||
|
||||
---
|
||||
|
||||
## 9. Nachtrag — Mitglieder-Detail-Modal (2026-06-23)
|
||||
|
||||
**Status:** ERLEDIGT
|
||||
|
||||
Statt des generischen `business-user-show`-Modals (Sponsor/Firma) zeigt der Klick auf einen Namen in der Team-Abo-Übersicht jetzt eine abo-fokussierte Zusammenfassung.
|
||||
|
||||
**Umsetzung:**
|
||||
- `TeamAboOverviewService::memberAboSummary(User $owner, int $memberId)`: liefert Name + E-Mail, Eigen-Abo (Punkte, Beginn, nächste Ausführung, Anzahl Ausführungen) sowie Kunden-Abos (Anzahl, Gesamtpunkte, Liste je Abo). Team-Autorisierung via `AboHelper::isUserInTeam()` → `null` (→ „nicht gefunden"-Modal), wenn Mitglied nicht in Downline.
|
||||
- `ModalController@load`: neuer Branch `team-abo-member-show`.
|
||||
- Neue View `resources/views/user/team/modal_member_abos.blade.php`.
|
||||
- `user/team/abos.blade.php`: Namens-Link nutzt `data-action="team-abo-member-show"`.
|
||||
- i18n: `abo.next_execution`, `abo.executions_count`, `abo.abo_count_points`, `abo.no_own_abo`, `abo.no_customer_abos` in de/en/es/fr.
|
||||
- Tests: 2 zusätzliche Tests in `tests/Feature/TeamAboOverviewTest.php` (gesamt 6 grün).
|
||||
|
||||
---
|
||||
|
||||
## 10. Nachtrag — Zeitraum-Logik: Bestand + Wachstums-Tabelle (2026-06-23)
|
||||
|
||||
**Status:** ERLEDIGT
|
||||
|
||||
**Entscheidung (mit Kunde):** Variante **A + C** statt historischem Filter (Variante B verworfen, da „aktiv" ein Jetzt-Zustand ist und eine historische Rekonstruktion fehleranfällig/irreführend wäre).
|
||||
|
||||
**Umsetzung:**
|
||||
- Oberer Bereich (Cards + Linien-Tabelle) zeigt immer den **aktuellen Bestand**; die „+neu"-Badges beziehen sich fest auf den **laufenden Monat** (Spaltenkopf zeigt den Monatsnamen). Der frühere, missverständliche Zeitraum-Filter wurde entfernt.
|
||||
- Neue **Wachstums-Tabelle** unter der Bestandsübersicht: wählbares Jahr (GET-Param `year`), Zeilen = Monate, Spalten = neue Eigen-Abos / neue Kunden-Abos / Summe + Jahres-Summenzeile.
|
||||
- `TeamAboOverviewService::monthlyGrowth(User,$year)` + privater Helfer `newAbosByMonth()` (DB-agnostisch via `toBase()->pluck('start_date')` + PHP-Gruppierung, kein `MONTH()`/`strftime`). Definition „neu" konsistent mit Badges (aktives Abo, `start_date` im Monat).
|
||||
- `TeamController@showAbos` vereinfacht (kein Session-Filter mehr): Bestand = aktueller Monat, Wachstum = `year`-Param.
|
||||
- i18n: `abo.team_growth`, `abo.month`, `abo.new_own_abos`, `abo.new_customer_abos`, `abo.new_total` in de/en/es/fr.
|
||||
- Tests: 1 zusätzlicher Test (`monthlyGrowth`) + angepasster Render-Test (gesamt 7 grün).
|
||||
|
||||
---
|
||||
|
||||
## 11. Nachtrag — Tabellen-Feinschliff Ebenen (2026-06-23)
|
||||
|
||||
**Status:** ERLEDIGT
|
||||
|
||||
- Linien-Tabelle: redundante Spalte „Mit Eigen-Abo" entfernt (= identisch zu „Eigen-Abos", da max. 1 Eigen-Abo pro Berater).
|
||||
- Neue Spalte **„Punkte"** (Gesamtpunkte je Ebene = Eigen- + Kundenabo-Punkte) inkl. Gesamtsumme im Footer (nutzt vorhandene `own_abo_points`/`customer_abo_points` aus `linesOverview`).
|
||||
- Hinweis-Fußzeile unter der Wachstums-Tabelle (`abo.growth_note`) erklärt die Differenz Bestand vs. Jahres-Wachstum.
|
||||
- **Klarstellung 124 vs. 123:** kein Bug. 124 = aktueller Bestand aller aktiven Eigen-Abos; 123 = davon in 2026 gestartet. 1 Eigen-Abo stammt aus einem Vorjahr und ist weiterhin aktiv.
|
||||
- i18n: `abo.growth_note` in de/en/es/fr.
|
||||
|
||||
---
|
||||
|
||||
## 12. Nachtrag — Wachstums-Liniendiagramm (2026-06-23)
|
||||
|
||||
**Status:** ERLEDIGT
|
||||
|
||||
- Unter der Wachstums-Tabelle: Chart.js-**Liniendiagramm** (X = Monate, Y = Mengen) mit zwei Kurven (neue Eigen-Abos, neue Kunden-Abos) für das gewählte Jahr.
|
||||
- Datenaufbereitung im Controller (`TeamController::buildGrowthChart()`) statt im Blade `@php`-Block – sauberere MVC-Trennung und umgeht ein Blade-Kompilierungsproblem mit `@php`-Block + Arrow-Funktionen in diesem Template.
|
||||
- Nutzt dieselbe Chart.js-v2-Lib wie `_abo_chart.blade.php` (`/vendor/libs/chartjs/chartjs.js`), feste Canvas-ID `aboGrowthChart`.
|
||||
- 2. Kachel-Dublette „Mit eigenem Abo" oben entfernt; verbleibende drei Kacheln auf `col-md-4`.
|
||||
- Render-Test entsprechend erweitert (gesamt 7 grün), Pint pass.
|
||||
Loading…
Add table
Add a link
Reference in a new issue