23-01-2026

This commit is contained in:
Kevin Adametz 2026-01-23 17:35:23 +01:00
parent a939cd51ef
commit a8b395e20d
248 changed files with 29342 additions and 4805 deletions

View file

@ -79,9 +79,11 @@ class TreeCalcBotOptimized
if ($storedStructure) {
$this->logger->info("Loading stored business structure for {$this->date->month}/{$this->date->year}");
$this->loadStoredStructure($storedStructure);
return;
} else {
$this->logger->info("Building fresh business structure for {$this->date->month}/{$this->date->year}");
$this->buildFreshStructure();
return;
}
} catch (\Exception $e) {
$this->logger->error("Error initializing admin structure: " . $e->getMessage());
@ -171,9 +173,8 @@ class TreeCalcBotOptimized
{
try {
$this->logger->info("Initializing business user details for: {$user->id}");
$this->businessUser = new BusinessUserItemOptimized($this->date, $this);
$this->businessUser->makeUserFromModel($user, $forceLiveCalculation); // ✅ Nutzt bereits User-Objekt
$this->businessUser->makeUserFromModel($user, $forceLiveCalculation);
$this->businessUser->checkSponsor($user);
// Führe vollständige Berechnung durch, wenn:
@ -184,14 +185,22 @@ class TreeCalcBotOptimized
$this->logger->info("Forcing live calculation for user {$user->id}");
}
// Aufbau der Struktur für den User in die unendliche Tiefe
// Phase 1: Aufbau der Struktur für den User in die unendliche Tiefe
$this->businessUser->readParentsBusinessUsers($forceLiveCalculation);
// Calculate Points in Lines (optimiert für Memory-Effizienz)
// Phase 2: Calculate Points in Lines (optimiert für Memory-Effizienz)
if (count($this->businessUser->businessUserItems) > 0) {
$this->calculateUserPointsOptimized($this->businessUser->businessUserItems, 1, $this->businessUser);
}
// Qualifikation nach qual_kp (KundenPoints) und qual_pp (PaylinePoints)
// Phase 3: Qualifikation für ALLE User in der Struktur berechnen (Bottom-Up)
// WICHTIG: Muss VOR der Root-Qualifikation erfolgen, damit die Kinder
// ihr qual_user_level haben (für Growth Bonus Differenz-Berechnung)
if (count($this->businessUser->businessUserItems) > 0) {
$this->calculateQualificationsForStructure($this->businessUser->businessUserItems);
}
// Phase 4: Qualifikation für ROOT-User nach qual_kp und qual_pp
$this->businessUser->calcQualPP();
}
} catch (\Exception $e) {
@ -200,6 +209,96 @@ class TreeCalcBotOptimized
}
}
/**
* Berechnet Qualifikationen für alle User in der Struktur rekursiv (Bottom-Up)
*
* WICHTIG: Diese Methode muss NACH der Punkte-Aggregation aufgerufen werden!
* Sie stellt sicher, dass alle User in der Struktur ihr qual_user_level haben,
* was für die Growth Bonus Differenz-Berechnung benötigt wird.
*
* Der Ablauf ist:
* 1. Rekursiv zuerst die Kinder berechnen (Bottom-Up)
* 2. business_lines für diesen User berechnen (basierend auf seinen Kindern)
* 3. Qualifikation berechnen (verwendet business_lines für Payline-Punkte)
*
* @param array $businessUserItems Array von BusinessUserItemOptimized
*/
private function calculateQualificationsForStructure(array $businessUserItems): void
{
foreach ($businessUserItems as $item) {
// Rekursiv zuerst die Kinder berechnen (Bottom-Up)
// So haben tiefere Ebenen ihr qual_user_level bevor die höheren Ebenen berechnet werden
if (!empty($item->businessUserItems)) {
$this->calculateQualificationsForStructure($item->businessUserItems);
}
// Business Lines für diesen User berechnen (basierend auf seinen Kindern)
// WICHTIG: Dies ist nötig, damit getPointsforPayline() korrekt funktioniert
if (!empty($item->businessUserItems)) {
$this->calculateBusinessLinesForUser($item);
}
// Dann Qualifikation für diesen User berechnen
// Nur wenn noch nicht berechnet (Performance-Optimierung)
if (!$item->isQualificationCalculated()) {
$item->calcQualPP(false);
}
}
}
/**
* Berechnet die business_lines für einen einzelnen User basierend auf seinen Kindern
*
* Diese Methode aggregiert die Team-Punkte der Kinder in die business_lines,
* ähnlich wie calculateUserPointsOptimized, aber nur für einen einzelnen User.
*
* @param BusinessUserItemOptimized $user Der User, für den die business_lines berechnet werden
*/
private function calculateBusinessLinesForUser(BusinessUserItemOptimized $user): void
{
// Bereits berechnet? (business_lines existieren und haben Daten)
$existingLines = $user->business_lines;
if (!empty($existingLines) && count($existingLines) > 0) {
return;
}
// Initialisiere business_lines über die Methode
$user->initBusinessLines();
// Sammle alle Kinder rekursiv mit ihrer Tiefe
$this->collectChildrenPointsForUser($user->businessUserItems, 1, $user);
}
/**
* Rekursive Hilfsfunktion zum Sammeln der Punkte für business_lines
*
* @param array $children Die Kinder des Users
* @param int $line Die aktuelle Linie (Tiefe)
* @param BusinessUserItemOptimized $targetUser Der User, für den wir die business_lines bauen
*/
private function collectChildrenPointsForUser(array $children, int $line, BusinessUserItemOptimized $targetUser): void
{
foreach ($children as $child) {
// Initialisiere die Linie falls nötig
if (!$targetUser->hasBusinessLine($line)) {
$obj = new stdClass();
$obj->points = 0;
$targetUser->addBusinessLineToUser($line, $obj);
}
// Füge die Team-Punkte des Kindes hinzu
$points = (float) ($child->sales_volume_points_TP_sum ?? 0);
if ($points > 0) {
$targetUser->addBusinessLinePoints($line, $points);
}
// Rekursiv für die Kinder des Kindes (nächste Linie)
if (!empty($child->businessUserItems)) {
$this->collectChildrenPointsForUser($child->businessUserItems, $line + 1, $targetUser);
}
}
}
/**
* Gibt Growth Bonus zurück (ab Linie 6)
* Erweitert um Array/Object-Kompatibilität für business_lines
@ -276,6 +375,15 @@ class TreeCalcBotOptimized
return $this->businessUsers;
}
/**
* Getter-Methoden (Rückwärtskompatibilität)
*/
public function getItem(): object
{
return $this->businessUser;
}
/**
* Zählt die Gesamtanzahl aller User in der Struktur (rekursiv)
*/