193 lines
8.1 KiB
Markdown
193 lines
8.1 KiB
Markdown
# 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:
|
|
|
|
```php
|
|
[
|
|
// 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
|
|
|
|
1. **`GrowthBonusCalculator.php`**: Methode `getMatrixDetails` hinzufügen.
|
|
* Muss rekursiv durch die `businessUserItems` laufen.
|
|
* Muss tracken, welcher "Schutz-Level" von oben kommt (rekursiv weitergegeben).
|
|
* Muss aber `protection_percent` lokal pro User neu bewerten (max(incoming, own)).
|
|
|
|
2. **`BusinessUserItemOptimized.php`**: Aufruf in `getGrowthBonusBreakdown` anpassen oder neue Methode `getGrowthBonusMatrix` hinzufügen.
|
|
|
|
3. **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`
|
|
|
|
```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.
|
|
|