mivita/dev/2026-06-23-abo/ENTWICKLUNGSPLAN-ABO-UEBERSICHTEN.md
Kevin 4135726772 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>
2026-06-23 14:07:29 +00:00

320 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.