- /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>
23 KiB
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
ERLEDIGTgesetzt (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:
- Eigene Kundenabos (
/user/abos/ot): Filter nach Monat & Jahr, in dem das Abo hinzugekommen ist (Eingangsmonat). - 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.
- 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 überm_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. |
| 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. |
| A3 | Umfang Ebenen | 1. Ebene zwingend als Default sichtbar; weitere Linien aufklappbar; „gesamter Baum" als Summenzeile/optionaler Modus. |
| A4 | „selbst ein Abo abgeschlossen" | Eigen-Abo = UserAbo is_for=me des Team-Mitglieds (Spalte/Badge pro Person: ja/nein + Punkte). |
| 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). |
| A6 | Dashboard-Widgets-Zielgruppe | Alle aktiven Berater sehen „Gesamtabos im Team" + „1000-Punkte-Shops"; klickbar → neue Team-Abo-Ansicht. |
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-ScopescopeAddedInMonth($query, $year, $month)(Filter nachstart_date;month=0lässt Abfrage unverändert). -
app/Http/Controllers/User/AboController.php(index('ot')): wertetmonth-Param aus, nutztaddedInMonth(), übergibtfilterMonth/filterYearan die View. -
resources/views/user/abo/index.blade.php: Filterleiste (Monats-Dropdown + Jahr + Filtern/Zurücksetzen) über der Card-Liste (nurview==='ot'). -
i18n:
abo.filter,abo.reset,abo.filter_added_periodin de/en/es/fr. -
Test:
tests/Feature/AboOtMonthFilterTest.php(2 Tests grün). -
AboController@index('ot'): zusätzlichmonth-Parameter (Default „alle") auswerten. -
Liste filtern:
whereYear('start_date', $year)+ optionalwhereMonth('start_date', $month). -
View
user/abo/index.blade.php: Filterleiste (Monats-Dropdown + Jahr) über der Card-Liste; Chart bleibt. Wiederverwendung vonHTMLHelper::getTransMonths()/getYearRange(). -
Filter-Persistenz analog zu bestehenden Mustern (Query-Param genügt; Session optional).
-
Test:
tests/Feature– Abos mitstart_datein verschiedenen Monaten anlegen, Filter prüft korrekte Teilmenge.
Phase 2 — TeamAboOverviewService
Status: ERLEDIGT (2026-06-23)
Umsetzung:
-
app/Models/UserAbo.php: ScopescopeActiveAbo()(active=true, status ∉ {4,5,6}) – konsistent mitBackofficeDashboardService. -
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 vonBackofficeDashboardService::lineBuckets()(keine Duplizierung der Baum-Traversierung). -
i18n:
abo.team_total,abo.team_linein de/en/es/fr. -
Test:
tests/Feature/TeamAboOverviewTest.php(2 Tests, 19 Assertions grün). Hinweis: Test-Schema hat keineproducts.slug-Spalte →beforeEachergänzt sie (etabliertes Muster ausMembershipQtyProtectionTest). -
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_dateim 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@showAbosnutztTeamAboOverviewService+ 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@showAbosumstellen aufTeamAboOverviewService+ Monat/Jahr-Filter (Session-persistiert, analogBackofficeStatisticsController::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_detailbleibt 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@showTeamCustomerAbosleitet dauerhaft aufuser_abos_team_showum (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 dieteam/customers-URL aktiv. -
resources/views/user/team/customer_abos.blade.phpbleibt 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 aufuser_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()aufpublicgesetzt (Wiederverwendung). -
TeamAboOverviewService::teamKpis(User,$month,$year): leichtgewichtige KPIs (Gesamtabos, Teamabos, Teamkundenabos, 1000-Punkte-Shops) ohne teure Punkte-/Mitglieder-Aggregation. -
HomeController@show: berechnetteamAboKpisfür aktive Berater (aktueller Monat). -
Neues Partial
resources/views/dashboard/_abo_team_kpis.blade.php: klickbare KPI-Card (→user_abos_team_show), eingebunden inhome.blade.php. -
i18n:
abo.shop_1000in de/en/es/fr. -
Test: KPI-Test in
tests/Feature/TeamAboOverviewTest.php(4 Tests grün). -
HomeController@show: für aktive Berater viaTeamAboOverviewService(bzw.BackofficeDashboardService::overview()-Totals für den aktuellen Monat) zwei KPIs berechnen:- Gesamtabos im Team (
team_partner_abos+team_customer_abosder Totals, oder getrennt anzeigen). - 1000-Punkte-Shops (
shop_1000Totals).
- Gesamtabos im Team (
-
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;LocalizationSyncTestgrü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
- Keine Logik-Duplikate:
BackofficeDashboardServiceist die Referenz für Linien/neue Abos/1000-Punkte-Shop. Gemeinsame Methoden extrahieren statt kopieren. - 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. - 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. - Status-Definition Abo aktiv: Konsistent mit
getMonthlyAboCounts()/activeAboQuery()halten (Terminal-Status 4/5 ausschließen). - Snapshots: Vergangene Monate aus
AboChartSnapshotbzw.BackofficeStatisticsSnapshotlesen (nicht neu berechnen). Aktueller Monat live. - Route-Kompatibilität:
user_abos_team_customersnicht hart entfernen (Bookmarks/Links) → Redirect. - 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.phpresources/views/dashboard/_abo_team_kpis.blade.phptests/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 viaAboHelper::isUserInTeam()→null(→ „nicht gefunden"-Modal), wenn Mitglied nicht in Downline.ModalController@load: neuer Branchteam-abo-member-show.- Neue View
resources/views/user/team/modal_member_abos.blade.php. user/team/abos.blade.php: Namens-Link nutztdata-action="team-abo-member-show".- i18n:
abo.next_execution,abo.executions_count,abo.abo_count_points,abo.no_own_abo,abo.no_customer_abosin 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 HelfernewAbosByMonth()(DB-agnostisch viatoBase()->pluck('start_date')+ PHP-Gruppierung, keinMONTH()/strftime). Definition „neu" konsistent mit Badges (aktives Abo,start_dateim Monat).TeamController@showAbosvereinfacht (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_totalin 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_pointsauslinesOverview). - 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_notein 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-IDaboGrowthChart. -
- Kachel-Dublette „Mit eigenem Abo" oben entfernt; verbleibende drei Kacheln auf
col-md-4.
- Kachel-Dublette „Mit eigenem Abo" oben entfernt; verbleibende drei Kacheln auf
- Render-Test entsprechend erweitert (gesamt 7 grün), Pint pass.