8.1 KiB
Konzept: Erweiterte Detailansicht für Growth Bonus (Matrix-View)
Die Anforderung ist, eine Matrix-Ansicht zu erstellen, bei der die Ebenen (Level 1, 2, 3...) als Spalten und die einzelnen Linien (Legs/Beine) als Zeilen dargestellt werden. Dies soll auch dann geschehen, wenn der Bonus gekappt ist, um volle Transparenz zu gewährleisten.
1. Datenstruktur-Erweiterung (GrowthBonusCalculator)
Die bisherige Aggregation (getVolumeByProtectionLevel) gruppiert Volumen nach "Schutz-Level". Das ist gut für die Berechnung, aber für die Visualisierung "Ebene für Ebene" brauchen wir die Rohdaten pro Ebene.
Wir benötigen eine neue Methode getMatrixDetails, die rekursiv die Struktur traversiert und für jedes Bein eine flache Liste von Ebenen-Volumen zurückgibt, angereichert mit Status-Informationen.
Struktur des Ergebnis-Arrays:
[
// Ein Eintrag pro Firstline (Bein)
[
'user' => [ 'id' => 123, 'name' => 'Max Mustermann', 'level' => 'Gold' ],
'levels' => [
1 => [ // Ebene 1 (relativ zu mir, also der Firstline-User selbst)
'volume' => 500,
'user_level' => 'Gold',
'protection_percent' => 2.0, // Was der User für sich beansprucht
'my_percent' => 2.5, // Mein Anspruch
'diff_percent' => 0.5, // Resultierende Provision
'commission' => 2.50,
'is_blocked' => false
],
2 => [ // Ebene 2 (User unter Max)
'volume' => 1000,
'user_level' => 'Silver',
'protection_percent' => 1.5,
'my_percent' => 2.5,
'diff_percent' => 1.0,
'commission' => 10.00,
'is_blocked' => false
],
// ... weitere Ebenen bis max Tiefe oder Abbruchbedingung
],
'totals' => [ 'volume' => 1500, 'commission' => 12.50 ]
],
// ... weitere Beine
]
2. Implementierungsschritte
-
GrowthBonusCalculator.php: MethodegetMatrixDetailshinzufügen.- Muss rekursiv durch die
businessUserItemslaufen. - Muss tracken, welcher "Schutz-Level" von oben kommt (rekursiv weitergegeben).
- Muss aber
protection_percentlokal pro User neu bewerten (max(incoming, own)).
- Muss rekursiv durch die
-
BusinessUserItemOptimized.php: Aufruf ingetGrowthBonusBreakdownanpassen oder neue MethodegetGrowthBonusMatrixhinzufügen. -
View
_user_detail_in.blade.php: Umbau der Tabelle zu einer Matrix.
Herausforderung: Tiefe und Breite
Eine komplette Matrix kann sehr breit und lang werden.
- Begrenzung: Wir sollten die Tiefe standardmäßig begrenzen (z.B. 10-20 Ebenen) oder nur relevante Ebenen (wo Volumen > 0) anzeigen.
- Breite: In der Tabelle werden die Spalten "Ebene 1", "Ebene 2", ... sein.
3. Code-Anpassung GrowthBonusCalculator.php
/**
* Liefert eine Matrix-Sicht für die detaillierte Darstellung
* Zeilen = Beine (Legs), Spalten = Ebenen (Levels)
*/
public function getMatrixDetails(BusinessUserItemOptimized $userItem, $qualUserLevel): array
{
$details = [];
if (empty($qualUserLevel->growth_bonus) || $qualUserLevel->growth_bonus <= 0) {
return $details;
}
$myGrowthPercent = (float) $qualUserLevel->growth_bonus;
foreach ($userItem->businessUserItems as $childItem) {
$legData = [
'user' => [
'id' => $childItem->user_id,
'name' => $childItem->first_name . ' ' . $childItem->last_name,
'level' => $childItem->user_level_name
],
'levels' => [],
'total_commission' => 0.0,
'total_volume' => 0.0
];
// Rekursiv die Ebenen dieses Beins einsammeln
// Start bei Ebene 1 (das ist das Kind selbst)
// Initial Protection ist 0 (vom Upline/Mir kommt kein Schutz, der relevant wäre, da ICH ja der Empfänger bin)
$this->collectLegLevels($childItem, 1, 0.0, $myGrowthPercent, $legData);
if (!empty($legData['levels'])) {
// Sortieren nach Ebenen-Index
ksort($legData['levels']);
$details[] = $legData;
}
}
// Sortieren nach Gesamt-Provision
usort($details, function($a, $b) {
return $b['total_commission'] <=> $a['total_commission'];
});
return $details;
}
private function collectLegLevels(BusinessUserItemOptimized $item, int $level, float $incomingProtection, float $myPercent, array &$legData)
{
// 1. Eigenen Status ermitteln (Schutz für Downline)
$myProtection = 0.0;
if ($item->isQualLevel()) {
$qual = $item->qual_user_level;
$growth = is_array($qual) ? ($qual['growth_bonus'] ?? 0) : ($qual->growth_bonus ?? 0);
if ($growth > 0) {
$myProtection = (float) $growth;
}
}
// Der effektive Schutz, der AUF diesen User wirkt (von oben kommend + sein eigener Anspruch)
// WICHTIG: Für die Provision auf DIESEN User zählt der $incomingProtection (Schutz von oben).
// Für die Weitergabe nach unten zählt max($incoming, $myProtection).
// Berechnung für diesen User (Ebene)
$volume = (float) ($item->sales_volume_points_TP_sum ?? 0);
if ($volume > 0) {
// Differenz: Mein Anspruch - Schutz von oben
$diffPercent = max(0, $myPercent - $incomingProtection);
$commission = round($volume / 100 * $diffPercent, 2);
// Speichern in Matrix
// Wir summieren Volumen pro Ebene (falls durch parallele Zweige im Bein mehrere User auf gleicher Ebene sind - hier aber linearer Abstieg)
// Moment, businessUserItems ist ein Baum. Ein Bein kann breit werden.
// Wir müssen pro Ebene summieren.
if (!isset($legData['levels'][$level])) {
$legData['levels'][$level] = [
'volume' => 0.0,
'commission' => 0.0,
'details' => [] // Optional für Hover
];
}
$legData['levels'][$level]['volume'] += $volume;
$legData['levels'][$level]['commission'] += $commission;
// Metadaten für Anzeige (nur beim ersten Eintrag pro Ebene oder aggregiert?)
// Bei Matrix-View (Spalten=Ebenen) summieren wir alles auf Ebene X in diesem Bein.
// Das "Problem": In Ebene X können User mit unterschiedlichem Schutz-Status sein.
// Daher ist eine einfache Summe evtl. irreführend bei der %-Anzeige.
// Alternative: Wir zeigen pro Ebene den "dominanten" Status oder listen auf.
// Für die Tabelle ist eine Zelle pro Ebene vorgesehen.
// Wir speichern Detail-Infos für Tooltip.
$legData['levels'][$level]['details'][] = [
'u' => $item->user_id,
'v' => $volume,
'p' => $incomingProtection, // Protected by
'd' => $diffPercent
];
$legData['total_volume'] += $volume;
$legData['total_commission'] += $commission;
}
// Protection für nächste Ebene: Maximum aus was von oben kam und was dieser User beansprucht
$nextProtection = max($incomingProtection, $myProtection);
// Rekursion
// Max Tiefe z.B. 20
if ($level < 20 && !empty($item->businessUserItems)) {
foreach ($item->businessUserItems as $child) {
$this->collectLegLevels($child, $level + 1, $nextProtection, $myPercent, $legData);
}
}
}
4. Design der Tabelle (Blade)
Spalten: Leg (Partner) | Ebene 1 | Ebene 2 | Ebene 3 | ... | Ebene 10 | Total Zeilen: Partner A | ... | ... | ...
Zellen-Inhalt:
- Oben: Provision (€)
- Unten: Volumen (Pkt)
- Farbe: Grün (Volle %), Gelb (Teil %), Rot (0% / Block)
Da die Ebenen dynamisch sind, ermitteln wir max_level über alle Legs.