update 20.10.2025
This commit is contained in:
parent
8c11130b5d
commit
a939cd51ef
616 changed files with 84821 additions and 4121 deletions
475
app/Http/Controllers/User/TeamController.php
Executable file → Normal file
475
app/Http/Controllers/User/TeamController.php
Executable file → Normal file
|
|
@ -45,7 +45,7 @@ class TeamController extends Controller
|
|||
$this->middleware('active.account');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Zeigt die Team-Übersicht mit optimierter TreeCalcBotOptimized-Datenverarbeitung
|
||||
|
|
@ -55,60 +55,58 @@ class TeamController extends Controller
|
|||
{
|
||||
$startTime = microtime(true);
|
||||
$startMemory = memory_get_usage();
|
||||
|
||||
|
||||
try {
|
||||
$this->setFilterVars();
|
||||
$user = User::find(\Auth::user()->id);
|
||||
$this->month = session('team_user_filter_month');
|
||||
$this->year = session('team_user_filter_year');
|
||||
|
||||
|
||||
// Prüfe ob Live-Berechnung erzwungen werden soll
|
||||
$forceLiveCalculation = Request::get('force_live_calculation', false) || Request::get('live', false);
|
||||
|
||||
\Log::info("TeamController: Building optimized team overview for user {$user->id} ({$this->month}/{$this->year})" .
|
||||
($forceLiveCalculation ? " with forced live calculation" : ""));
|
||||
|
||||
$forceLiveCalculation = false;
|
||||
|
||||
\Log::info("TeamController: Building optimized team overview for user {$user->id} ({$this->month}/{$this->year})" .
|
||||
($forceLiveCalculation === true ? " with forced live calculation" : "not live calculation"));
|
||||
|
||||
// Verwende TreeCalcBotOptimized für bessere Performance
|
||||
$TreeCalcBot = new TreeCalcBotOptimized($this->month, $this->year, 'member', $forceLiveCalculation);
|
||||
$TreeCalcBot->initStructureUser($user->id);
|
||||
|
||||
//$TreeCalcBot = new TreeCalcBotOptimized($this->month, $this->year, 'member', $forceLiveCalculation);
|
||||
//$TreeCalcBot->initStructureUser($user->id);
|
||||
$endTime = microtime(true);
|
||||
$endMemory = memory_get_usage();
|
||||
|
||||
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
$memoryUsed = $this->formatBytes($endMemory - $startMemory);
|
||||
|
||||
|
||||
$calculationType = $forceLiveCalculation ? " (LIVE)" : " (CACHE)";
|
||||
\Log::info("TeamController: Optimized team overview built in {$executionTime}ms, Memory: {$memoryUsed}{$calculationType}");
|
||||
|
||||
|
||||
$data = [
|
||||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(2022),
|
||||
'filter_active' => $this->getFilterActive(),
|
||||
'filter_levels' => $this->getFilterLevels(),
|
||||
'filter_next_level' => $this->getFilterNextLevel(),
|
||||
'TreeCalcBot' => $TreeCalcBot,
|
||||
//'TreeCalcBot' => $TreeCalcBot,
|
||||
'performance' => [
|
||||
'execution_time' => $executionTime,
|
||||
'memory_used' => $memoryUsed,
|
||||
'user_id' => $user->id,
|
||||
'user_count' => $TreeCalcBot->getTotalUserCount(),
|
||||
'user_count' => 0, //$TreeCalcBot->getTotalUserCount(),
|
||||
'version' => 'Optimized',
|
||||
'calculation_type' => $forceLiveCalculation ? 'Live' : 'Cache'
|
||||
],
|
||||
'optimized' => true,
|
||||
'forceLiveCalculation' => $forceLiveCalculation,
|
||||
];
|
||||
|
||||
return view('user.team.show', $data);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error in optimized show for user {$user->id}: " . $e->getMessage());
|
||||
|
||||
|
||||
// Fallback mit minimalen Daten
|
||||
$endTime = microtime(true);
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
|
||||
|
||||
$data = [
|
||||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(2022),
|
||||
|
|
@ -124,7 +122,7 @@ class TeamController extends Controller
|
|||
],
|
||||
'optimized' => false,
|
||||
];
|
||||
|
||||
|
||||
return view('user.team.show', $data);
|
||||
}
|
||||
}
|
||||
|
|
@ -133,55 +131,54 @@ class TeamController extends Controller
|
|||
{
|
||||
$startTime = microtime(true);
|
||||
$startMemory = memory_get_usage();
|
||||
|
||||
|
||||
$user = User::find(\Auth::user()->id);
|
||||
if(config('app.debug')){
|
||||
if (config('app.debug')) {
|
||||
$user = User::find(454);
|
||||
}
|
||||
$this->setFilterVars();
|
||||
|
||||
|
||||
// Prüfe ob optimierte Version explizit angefordert wird
|
||||
$useOptimized = Request::get('use_optimized', true);
|
||||
|
||||
|
||||
// Prüfe ob Live-Berechnung erzwungen werden soll
|
||||
$forceLiveCalculation = Request::get('force_live_calculation', false) || Request::get('live', false);
|
||||
|
||||
|
||||
try {
|
||||
if ($useOptimized) {
|
||||
// Verwende User-spezifische optimierte Version
|
||||
$TreeCalcBot = new TreeCalcBotOptimized(
|
||||
session('team_user_filter_month'),
|
||||
session('team_user_filter_year'),
|
||||
session('team_user_filter_month'),
|
||||
session('team_user_filter_year'),
|
||||
'member',
|
||||
$forceLiveCalculation
|
||||
);
|
||||
$TreeCalcBot->initStructureUser($user->id, $forceLiveCalculation);
|
||||
$optimizedUsed = true;
|
||||
|
||||
} else {
|
||||
// Standard TreeCalcBot mit Performance-Monitoring
|
||||
$TreeCalcBot = new TreeCalcBot(
|
||||
session('team_user_filter_month'),
|
||||
session('team_user_filter_year'),
|
||||
session('team_user_filter_month'),
|
||||
session('team_user_filter_year'),
|
||||
'member'
|
||||
);
|
||||
|
||||
|
||||
// Standard TreeCalcBot unterstützt forceLiveCalculation nicht
|
||||
$TreeCalcBot->initStructureUser($user->id);
|
||||
$optimizedUsed = false;
|
||||
}
|
||||
|
||||
|
||||
$endTime = microtime(true);
|
||||
$endMemory = memory_get_usage();
|
||||
|
||||
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
$memoryUsed = $this->formatBytes($endMemory - $startMemory);
|
||||
|
||||
$versionInfo = ($optimizedUsed ? "OPTIMIZED" : "STANDARD") .
|
||||
($forceLiveCalculation ? " + LIVE" : " + CACHE");
|
||||
|
||||
|
||||
$versionInfo = ($optimizedUsed ? "OPTIMIZED" : "STANDARD") .
|
||||
($forceLiveCalculation ? " + LIVE" : " + CACHE");
|
||||
|
||||
\Log::info("TeamController: Structure built for user {$user->id} in {$executionTime}ms, Memory: {$memoryUsed} ({$versionInfo})");
|
||||
|
||||
|
||||
$data = [
|
||||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(2022),
|
||||
|
|
@ -189,28 +186,27 @@ class TeamController extends Controller
|
|||
'performance' => [
|
||||
'execution_time' => $executionTime,
|
||||
'memory_used' => $memoryUsed,
|
||||
'user_count' => $optimizedUsed && method_exists($TreeCalcBot, 'getTotalUserCount')
|
||||
? $TreeCalcBot->getTotalUserCount()
|
||||
: '-',
|
||||
'user_count' => $optimizedUsed && method_exists($TreeCalcBot, 'getTotalUserCount')
|
||||
? $TreeCalcBot->getTotalUserCount()
|
||||
: '-',
|
||||
'version' => $optimizedUsed ? 'Optimized' : 'Standard',
|
||||
'calculation_type' => $forceLiveCalculation ? 'Live' : 'Cache'
|
||||
],
|
||||
'optimized' => $optimizedUsed,
|
||||
'forceLiveCalculation' => $forceLiveCalculation,
|
||||
];
|
||||
|
||||
|
||||
return view('user.team.structure', $data);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error in structure for user {$user->id}: " . $e->getMessage());
|
||||
|
||||
|
||||
// Fallback zur Standard-Implementierung
|
||||
$TreeCalcBot = new TreeCalcBot(session('team_user_filter_month'), session('team_user_filter_year'), 'member');
|
||||
$TreeCalcBot->initStructureUser($user->id);
|
||||
|
||||
|
||||
$endTime = microtime(true);
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
|
||||
|
||||
$data = [
|
||||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(2022),
|
||||
|
|
@ -226,14 +222,15 @@ class TeamController extends Controller
|
|||
'optimized' => false,
|
||||
'forceLiveCalculation' => $forceLiveCalculation,
|
||||
];
|
||||
|
||||
|
||||
return view('user.team.structure', $data);
|
||||
}
|
||||
}
|
||||
public function structureOld()
|
||||
{
|
||||
abort(403, 'This page is removed');
|
||||
$user = User::find(\Auth::user()->id);
|
||||
if(config('app.debug')){
|
||||
if (config('app.debug')) {
|
||||
$user = User::find(454);
|
||||
}
|
||||
$this->setFilterVars();
|
||||
|
|
@ -263,27 +260,29 @@ class TeamController extends Controller
|
|||
$user = User::find(\Auth::user()->id);
|
||||
$this->month = Request::get('team_user_filter_month') ?: session('team_user_filter_month');
|
||||
$this->year = Request::get('team_user_filter_year') ?: session('team_user_filter_year');
|
||||
|
||||
|
||||
// Prüfe ob Live-Berechnung erzwungen werden soll
|
||||
$forceLiveCalculation = Request::get('force_live_calculation', false) || Request::get('live', false);
|
||||
|
||||
\Log::info("TeamController: Building optimized datatable for user {$user->id} ({$this->month}/{$this->year})" .
|
||||
($forceLiveCalculation == true ? " with forced live calculation" : ""));
|
||||
|
||||
$forceLiveCalculation = false;
|
||||
\Log::info("TeamController: Building optimized datatable for user {$user->id} ({$this->month}/{$this->year})" .
|
||||
($forceLiveCalculation == true ? " with forced live calculation" : ""));
|
||||
|
||||
// Lade TreeCalcBotOptimized-Daten
|
||||
$TreeCalcBot = new TreeCalcBotOptimized($this->month, $this->year, 'member', $forceLiveCalculation);
|
||||
$TreeCalcBot->initStructureUser($user->id, $forceLiveCalculation);
|
||||
|
||||
// Extrahiere alle User aus der Struktur
|
||||
$teamUsers = collect($this->getTeamUsersFromStructure($TreeCalcBot));
|
||||
// \Log::info("TeamController: TeamUsers: " . $teamUsers->count());
|
||||
|
||||
$teamUsersRaw = $this->getTeamUsersFromStructure($TreeCalcBot);
|
||||
|
||||
// KRITISCH: Bereinige die Objekte für DataTables (entferne zirkuläre Referenzen)
|
||||
$teamUsers = collect($this->cleanBusinessUserItemsForDataTable($teamUsersRaw));
|
||||
|
||||
\Log::info("TeamController: TeamUsers cleaned for DataTable: " . $teamUsers->count());
|
||||
$endTime = microtime(true);
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
$this->forceLiveCalculation = $forceLiveCalculation;
|
||||
|
||||
|
||||
\Log::info("TeamController: Optimized datatable data prepared in {$executionTime}ms for " . $teamUsers->count() . " users");
|
||||
|
||||
|
||||
return \DataTables::of($teamUsers)
|
||||
->addColumn('id', function ($teamUser) {
|
||||
return '<button type="button" class="btn icon-btn btn-xs btn-secondary" data-toggle="modal" data-target="#modals-load-content"
|
||||
|
|
@ -310,7 +309,6 @@ class TeamController extends Controller
|
|||
})
|
||||
->addColumn('user_level', function ($teamUser) {
|
||||
return $teamUser->user_level_name ? TranslationHelper::transUserLevelName($teamUser->user_level_name) : '';
|
||||
|
||||
})
|
||||
->addColumn('is_qual_kp', function ($teamUser) {
|
||||
$user = User::find($teamUser->user_id);
|
||||
|
|
@ -320,12 +318,11 @@ class TeamController extends Controller
|
|||
return formatNumber($teamUser->sales_volume_points_KP_sum, 0);
|
||||
})
|
||||
->addColumn('sales_volume_total', function ($teamUser) {
|
||||
|
||||
return formatNumber($teamUser->payline_points_qual_kp, 0);
|
||||
|
||||
return formatNumber($teamUser->payline_points_qual_kp, 0);
|
||||
})
|
||||
->addColumn('next_level_qualified', function ($teamUser) {
|
||||
|
||||
|
||||
$userBusiness = UserBusiness::where('user_id', $teamUser->user_id)
|
||||
->where('month', $this->month)
|
||||
->where('year', $this->year)
|
||||
|
|
@ -334,7 +331,6 @@ class TeamController extends Controller
|
|||
return NextLevelBadgeHelper::generateBadgeFromUserBusiness($userBusiness);
|
||||
}
|
||||
return NextLevelBadgeHelper::renderNoDataBadge();
|
||||
|
||||
})
|
||||
->addColumn('active_account', function ($teamUser) {
|
||||
return get_active_badge($teamUser->active_account);
|
||||
|
|
@ -344,10 +340,9 @@ class TeamController extends Controller
|
|||
})
|
||||
->rawColumns(['id', 'next_level_qualified', 'active_account', 'is_qual_kp', 'sales_volume_KP_points', 'sales_volume_total'])
|
||||
->make(true);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error in optimized datatable: " . $e->getMessage());
|
||||
|
||||
|
||||
// Fallback zur Standard-DataTable
|
||||
return $this->datatable();
|
||||
}
|
||||
|
|
@ -361,7 +356,7 @@ class TeamController extends Controller
|
|||
try {
|
||||
$user = User::find(\Auth::user()->id);
|
||||
$query = $this->initTeamSearch($user);
|
||||
|
||||
|
||||
return \DataTables::eloquent($query)
|
||||
->addColumn('id', function (User $teamUser) {
|
||||
return '<button type="button" class="btn icon-btn btn-xs btn-secondary" data-toggle="modal" data-target="#modals-load-content"
|
||||
|
|
@ -397,7 +392,7 @@ class TeamController extends Controller
|
|||
$individual = (int) $teamUser->getUserSalesVolumeBy($month, $year, 'sales_volume_KP_points');
|
||||
$shop = (int) $teamUser->getUserSalesVolumeBy($month, $year, 'sales_volume_points_shop');
|
||||
return '<div class="no-line-break">' . $total . '</div>' .
|
||||
'<span class="small no-line-break">E: ' . $individual . ' | S: ' . $shop . '</span>';
|
||||
'<span class="small no-line-break">E: ' . $individual . ' | S: ' . $shop . '</span>';
|
||||
})
|
||||
->addColumn('sales_volume_total', function (User $teamUser) {
|
||||
$month = Request::get('team_user_filter_month') ?: session('team_user_filter_month');
|
||||
|
|
@ -406,7 +401,7 @@ class TeamController extends Controller
|
|||
$individual = (float) $teamUser->getUserSalesVolumeBy($month, $year, 'sales_volume_total');
|
||||
$shop = (float) $teamUser->getUserSalesVolumeBy($month, $year, 'sales_volume_total_shop');
|
||||
return '<div class="no-line-break">' . formatNumber($total) . ' €</div>' .
|
||||
'<span class="small no-line-break">E: ' . formatNumber($individual) . ' | S: ' . formatNumber($shop) . ' €</span>';
|
||||
'<span class="small no-line-break">E: ' . formatNumber($individual) . ' | S: ' . formatNumber($shop) . ' €</span>';
|
||||
})
|
||||
->addColumn('email', function (User $teamUser) {
|
||||
return e($teamUser->email);
|
||||
|
|
@ -441,35 +436,35 @@ class TeamController extends Controller
|
|||
// Verwende bereits berechnete UserBusiness-Daten für bessere Performance
|
||||
$month = Request::get('team_user_filter_month') ?: session('team_user_filter_month');
|
||||
$year = Request::get('team_user_filter_year') ?: session('team_user_filter_year');
|
||||
|
||||
|
||||
$userBusiness = UserBusiness::where('user_id', $teamUser->id)
|
||||
->where('month', $month)
|
||||
->where('year', $year)
|
||||
->first();
|
||||
|
||||
|
||||
if ($userBusiness) {
|
||||
return NextLevelBadgeHelper::generateBadgeFromUserBusiness($userBusiness);
|
||||
}
|
||||
|
||||
|
||||
return NextLevelBadgeHelper::renderNoDataBadge();
|
||||
})
|
||||
->filterColumn('m_account', function ($query, $keyword) {
|
||||
if ($keyword != "") {
|
||||
$query->whereHas('account', function($q) use ($keyword) {
|
||||
$query->whereHas('account', function ($q) use ($keyword) {
|
||||
$q->where('m_account', 'LIKE', '%' . $keyword . '%');
|
||||
});
|
||||
}
|
||||
})
|
||||
->filterColumn('first_name', function ($query, $keyword) {
|
||||
if ($keyword != "") {
|
||||
$query->whereHas('account', function($q) use ($keyword) {
|
||||
$query->whereHas('account', function ($q) use ($keyword) {
|
||||
$q->where('first_name', 'LIKE', '%' . $keyword . '%');
|
||||
});
|
||||
}
|
||||
})
|
||||
->filterColumn('last_name', function ($query, $keyword) {
|
||||
if ($keyword != "") {
|
||||
$query->whereHas('account', function($q) use ($keyword) {
|
||||
$query->whereHas('account', function ($q) use ($keyword) {
|
||||
$q->where('last_name', 'LIKE', '%' . $keyword . '%');
|
||||
});
|
||||
}
|
||||
|
|
@ -487,10 +482,9 @@ class TeamController extends Controller
|
|||
->orderColumn('active_account', 'users.payment_account $1')
|
||||
->rawColumns(['id', 'is_qual_kp', 'sales_volume_KP_points', 'sales_volume_total', 'sponsor', 'active_account', 'next_level_qualified'])
|
||||
->make(true);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error in userDatatable: " . $e->getMessage());
|
||||
|
||||
|
||||
return response()->json([
|
||||
'error' => 'Team-Datatable konnte nicht geladen werden: ' . $e->getMessage()
|
||||
], 500);
|
||||
|
|
@ -504,21 +498,21 @@ class TeamController extends Controller
|
|||
public function marketingplan()
|
||||
{
|
||||
$startTime = microtime(true);
|
||||
|
||||
|
||||
try {
|
||||
$user = User::find(\Auth::user()->id);
|
||||
$currentLevel = $user->user_level;
|
||||
|
||||
|
||||
// Lade alle aktiven User Level, sortiert nach Position
|
||||
$userLevels = \App\Models\UserLevel::where('active', true)
|
||||
->orderBy('pos', 'asc')
|
||||
->get();
|
||||
|
||||
|
||||
$endTime = microtime(true);
|
||||
$executionTime = round(($endTime - $startTime) * 1000, 2);
|
||||
|
||||
|
||||
\Log::info("TeamController: Marketingplan loaded for user {$user->id} in {$executionTime}ms");
|
||||
|
||||
|
||||
$data = [
|
||||
'userLevels' => $userLevels,
|
||||
'currentUser' => $user,
|
||||
|
|
@ -527,12 +521,11 @@ class TeamController extends Controller
|
|||
'execution_time' => $executionTime
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
return view('user.team.marketingplan', $data);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error loading marketingplan: " . $e->getMessage());
|
||||
|
||||
|
||||
return view('user.team.marketingplan', [
|
||||
'error' => __('marketingplan.loading_error') . ' ' . $e->getMessage(),
|
||||
'userLevels' => collect(),
|
||||
|
|
@ -580,7 +573,7 @@ class TeamController extends Controller
|
|||
// Filtere Team-Mitglieder basierend auf Sponsor-Hierarchie
|
||||
// TODO: Hier müsste die Logik implementiert werden, um nur Team-Mitglieder des aktuellen Users zu finden
|
||||
// Für jetzt zeigen wir alle aktiven User (kann später spezifiziert werden)
|
||||
|
||||
|
||||
$activeFilter = Request::get('team_user_filter_active') ?: session('team_user_filter_active', 1);
|
||||
if ($activeFilter == 1) {
|
||||
$query->where('users.payment_account', '>=', now());
|
||||
|
|
@ -591,7 +584,7 @@ class TeamController extends Controller
|
|||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
public function points()
|
||||
{
|
||||
$this->setFilterVars();
|
||||
|
|
@ -718,12 +711,12 @@ class TeamController extends Controller
|
|||
}
|
||||
if (Request::get('team_user_filter_level')) {
|
||||
session(['team_user_filter_level' => Request::get('team_user_filter_level')]);
|
||||
}else{
|
||||
} else {
|
||||
session(['team_user_filter_level' => 0]);
|
||||
}
|
||||
if (Request::get('team_user_filter_next_level')) {
|
||||
session(['team_user_filter_next_level' => Request::get('team_user_filter_next_level')]);
|
||||
}else{
|
||||
} else {
|
||||
session(['team_user_filter_next_level' => 0]);
|
||||
}
|
||||
}
|
||||
|
|
@ -812,96 +805,120 @@ class TeamController extends Controller
|
|||
return round($bytes, $precision) . ' ' . $units[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt verfügbare User Level für Filter
|
||||
*/
|
||||
private function getFilterLevels(): array
|
||||
{
|
||||
$levels = [0 => 'Alle Level'];
|
||||
|
||||
$userLevels = \App\Models\UserLevel::orderBy('pos')->get(['id', 'name']);
|
||||
foreach ($userLevels as $level) {
|
||||
$levels[$level->id] = $level->name;
|
||||
}
|
||||
|
||||
return $levels;
|
||||
/**
|
||||
* Holt verfügbare User Level für Filter
|
||||
*/
|
||||
private function getFilterLevels(): array
|
||||
{
|
||||
$levels = [0 => 'Alle Level'];
|
||||
|
||||
$userLevels = \App\Models\UserLevel::orderBy('pos')->get(['id', 'name']);
|
||||
foreach ($userLevels as $level) {
|
||||
$levels[$level->id] = $level->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt übersetzte Filter für Aktiv-Status
|
||||
*/
|
||||
private function getFilterActive(): array
|
||||
{
|
||||
return [
|
||||
1 => __('team.filter_active'),
|
||||
2 => __('team.filter_not_active'),
|
||||
3 => __('team.filter_all')
|
||||
];
|
||||
}
|
||||
return $levels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt übersetzte Filter für Next Level Status
|
||||
*/
|
||||
private function getFilterNextLevel(): array
|
||||
{
|
||||
return [
|
||||
0 => __('team.all_status'),
|
||||
1 => __('team.qualified_green'),
|
||||
2 => __('team.in_progress_yellow'),
|
||||
3 => __('team.no_level_red')
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Holt übersetzte Filter für Aktiv-Status
|
||||
*/
|
||||
private function getFilterActive(): array
|
||||
{
|
||||
return [
|
||||
1 => __('team.filter_active'),
|
||||
2 => __('team.filter_not_active'),
|
||||
3 => __('team.filter_all')
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt übersetzte Filter für Next Level Status
|
||||
*/
|
||||
private function getFilterNextLevel(): array
|
||||
{
|
||||
return [
|
||||
0 => __('team.all_status'),
|
||||
1 => __('team.qualified_green'),
|
||||
2 => __('team.in_progress_yellow'),
|
||||
3 => __('team.no_level_red')
|
||||
];
|
||||
}
|
||||
|
||||
// Performance-optimierte Badge-Generierung wurde in NextLevelBadgeHelper ausgelagert
|
||||
// Alte performance-lastige Methoden wurden entfernt um die Datatable-Performance zu verbessern
|
||||
|
||||
/**
|
||||
* Extrahiert alle User aus TreeCalcBotOptimized-Struktur für DataTable-Anzeige
|
||||
* Sammelt rekursiv alle User aus der Struktur und macht sie als flache Liste verfügbar
|
||||
* Sammelt rekursiv alle User aus der Struktur und macht sie als FLACHE Liste verfügbar
|
||||
*/
|
||||
public function getTeamUsersFromStructure(TreeCalcBotOptimized $treeCalcBot): array
|
||||
{
|
||||
$allUsers = [];
|
||||
$deep = 0;
|
||||
$processedIds = [];
|
||||
|
||||
// Debug: Prüfe TreeCalcBot-Inhalt
|
||||
$businessUsers = $treeCalcBot->getItems();
|
||||
\Log::info("TeamController: TreeCalcBot items count: " . count($businessUsers));
|
||||
|
||||
// Sammle alle Root-User
|
||||
\Log::info("TeamController: TreeCalcBot root items count: " . count($businessUsers));
|
||||
|
||||
// Sammle alle Root-User UND deren verschachtelte businessUserItems
|
||||
foreach ($businessUsers as $businessUser) {
|
||||
\Log::debug("TeamController: Processing businessUser", [
|
||||
'user_id' => ($businessUser->user_id),
|
||||
// WICHTIG: user_id korrekt über b_user abrufen (Magic Method Problem mit isset())
|
||||
$userId = $businessUser->user_id; // Über __get() Method
|
||||
|
||||
\Log::debug("TeamController: Processing root businessUser", [
|
||||
'user_id' => $userId,
|
||||
'businessUserItems_count' => count($businessUser->businessUserItems ?? []),
|
||||
]);
|
||||
$businessUser->deep = $deep;
|
||||
$allUsers[] = $businessUser;
|
||||
$this->collectUserIdsFromBusinessUser($businessUser, $allUsers, $deep+1, false);
|
||||
// WICHTIG: Root-User selbst hinzufügen (korrigierte user_id Prüfung)
|
||||
//nur User können auch children haben - businessUserItems
|
||||
if ($userId && !isset($processedIds[$userId])) {
|
||||
$processedIds[$userId] = true;
|
||||
$businessUser->deep = 0;
|
||||
$allUsers[] = $businessUser;
|
||||
$this->collectAllBusinessUserItemsFlat($businessUser->businessUserItems ?? [], $allUsers, $processedIds, 1);
|
||||
\Log::debug("TeamController: Root-User hinzugefügt: {$userId}");
|
||||
}
|
||||
}
|
||||
// Sammle parentless User
|
||||
// Sammle parentless User, kann bei usern eigenlich nicht vorkommen, da sie immer teil des baums sind
|
||||
if ($treeCalcBot->isParentless()) {
|
||||
$parentless = $treeCalcBot->__get('parentless');
|
||||
//\Log::info("TeamController: Found " . count($parentless) . " parentless users");
|
||||
|
||||
if (is_array($parentless)) {
|
||||
foreach ($parentless as $businessUser) {
|
||||
if ($businessUser) {
|
||||
$businessUser->deep = 0;
|
||||
$allUsers[] = $businessUser;
|
||||
|
||||
// Sammle rekursiv alle Unter-User
|
||||
$this->collectUserIdsFromBusinessUser($businessUser, $allUsers, 0, true);
|
||||
// WICHTIG: user_id korrekt über b_user abrufen (Magic Method Problem mit isset())
|
||||
$userId = $businessUser->user_id; // Über __get() Method
|
||||
|
||||
if ($userId) {
|
||||
// Prüfe ob dieser parentless User bereits gesammelt wurde
|
||||
if (!isset($processedIds[$userId])) {
|
||||
$processedIds[$userId] = true;
|
||||
$businessUser->deep = 0;
|
||||
$allUsers[] = $businessUser;
|
||||
|
||||
\Log::debug("TeamController: Parentless-User hinzugefügt: {$userId}");
|
||||
|
||||
// Sammle ALLE verschachtelten businessUserItems rekursiv
|
||||
$this->collectAllBusinessUserItemsFlat($businessUser->businessUserItems ?? [], $allUsers, $processedIds, 1);
|
||||
} else {
|
||||
\Log::debug("TeamController: Parentless-User übersprungen: {$userId} (bereits verarbeitet)");
|
||||
}
|
||||
} else {
|
||||
\Log::warning("TeamController: Parentless BusinessUser ohne user_id übersprungen");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\Log::info("TeamController: AllUsers before filtering: " . count($allUsers));
|
||||
|
||||
// Filter anwenden
|
||||
$filteredUsers = $this->applyTeamFiltersToBusinessUsers($allUsers);
|
||||
\Log::info("TeamController: AllUsers after filtering: " . count($filteredUsers));
|
||||
|
||||
|
||||
return $filteredUsers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wendet Team-Filter auf BusinessUser-Objekte an
|
||||
*/
|
||||
|
|
@ -910,9 +927,9 @@ class TeamController extends Controller
|
|||
$activeFilter = Request::get('team_user_filter_active') ?: session('team_user_filter_active', 1);
|
||||
$levelFilter = Request::get('team_user_filter_level') ?: session('team_user_filter_level', 0);
|
||||
$nextLevelFilter = Request::get('team_user_filter_next_level') ?: session('team_user_filter_next_level', 0);
|
||||
|
||||
|
||||
\Log::info("TeamController: Applying filters - Active: {$activeFilter}, Level: {$levelFilter}, NextLevel: {$nextLevelFilter}");
|
||||
|
||||
|
||||
// Debug: Zeige verfügbare Eigenschaften des ersten BusinessUsers
|
||||
if (!empty($businessUsers)) {
|
||||
$firstUser = $businessUsers[0];
|
||||
|
|
@ -924,8 +941,8 @@ class TeamController extends Controller
|
|||
'next_can_user_level' => isset($firstUser->next_can_user_level) ? 'set' : 'not set',
|
||||
]);
|
||||
}
|
||||
|
||||
$filtered = array_filter($businessUsers, function($businessUser) use ($activeFilter, $levelFilter, $nextLevelFilter) {
|
||||
|
||||
$filtered = array_filter($businessUsers, function ($businessUser) use ($activeFilter, $levelFilter, $nextLevelFilter) {
|
||||
// Active Filter anwenden
|
||||
if ($activeFilter == 1) { // Nur aktive
|
||||
if (!$businessUser->active_account) {
|
||||
|
|
@ -937,19 +954,19 @@ class TeamController extends Controller
|
|||
}
|
||||
}
|
||||
// activeFilter == 3 bedeutet alle (keine Einschränkung)
|
||||
|
||||
|
||||
// Level Filter anwenden
|
||||
if ($levelFilter && $levelFilter != 0) {
|
||||
if ($businessUser->m_level_id != $levelFilter) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Next Level Filter anwenden
|
||||
if ($nextLevelFilter && $nextLevelFilter != 0) {
|
||||
$hasNextQual = ($businessUser->next_qual_user_level) && $businessUser->next_qual_user_level !== '[]';
|
||||
$hasNextCan = ($businessUser->next_can_user_level) && $businessUser->next_can_user_level !== '[]';
|
||||
|
||||
|
||||
switch ($nextLevelFilter) {
|
||||
case 1: // Qualifiziert (grün) - hat next_qual_user_level
|
||||
if (!$hasNextQual) {
|
||||
|
|
@ -968,35 +985,153 @@ class TeamController extends Controller
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true; // Alle Filter bestanden
|
||||
});
|
||||
|
||||
|
||||
// Array-Indizes neu setzen für korrekte DataTable-Verarbeitung
|
||||
return array_values($filtered);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hilfsmethode zum rekursiven Sammeln von User-IDs aus BusinessUser-Struktur
|
||||
* NEUE OPTIMIERTE Methode: Sammelt ALLE BusinessUserItems in einer flachen Liste
|
||||
* Perfekt für DataTable-Verarbeitung - keine verschachtelte Struktur
|
||||
*/
|
||||
private function collectUserIdsFromBusinessUser($businessUser, &$allUsers, $deep, $parentless): void
|
||||
private function collectAllBusinessUserItemsFlat(array $businessUserItems, &$allUsers, &$processedIds, $depth = 1): void
|
||||
{
|
||||
if (isset($businessUser->businessUserItems) && is_array($businessUser->businessUserItems)) {
|
||||
\Log::debug("TeamController: Collecting from businessUser with " . count($businessUser->businessUserItems) . " sub-items");
|
||||
|
||||
foreach ($businessUser->businessUserItems as $subBusinessUser) {
|
||||
if ($subBusinessUser) {
|
||||
$subBusinessUser->deep = $deep;
|
||||
$allUsers[] = $subBusinessUser;
|
||||
if($subBusinessUser->user_id){
|
||||
\Log::debug("TeamController: Collected user ID: " . $subBusinessUser->user_id);
|
||||
// Schutz vor zu tiefer Rekursion (maximale Tiefe: 20 Levels)
|
||||
$maxDepth = 20;
|
||||
if ($depth > $maxDepth) {
|
||||
\Log::warning("TeamController: Maximale Sammlungstiefe ({$maxDepth}) erreicht bei Tiefe {$depth}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($businessUserItems as $businessUserItem) {
|
||||
if ($businessUserItem) {
|
||||
// WICHTIG: user_id korrekt über b_user abrufen (Magic Method Problem mit isset())
|
||||
$userId = $businessUserItem->user_id; // Über __get() Method
|
||||
if ($userId) {
|
||||
// KRITISCHER SCHUTZ: Prüfe ob User bereits gesammelt wurde
|
||||
if (isset($processedIds[$userId])) {
|
||||
\Log::debug("TeamController: Überspringe bereits gesammelten User {$userId} (Duplikat verhindert)");
|
||||
continue;
|
||||
}
|
||||
// Rekursiver Aufruf für weitere Unter-User
|
||||
$newDeep = $parentless ? 0 : $deep+1;
|
||||
$this->collectUserIdsFromBusinessUser($subBusinessUser, $allUsers, $newDeep, $parentless);
|
||||
|
||||
// User zu flacher Liste hinzufügen
|
||||
$processedIds[$userId] = true;
|
||||
$businessUserItem->deep = $depth;
|
||||
$allUsers[] = $businessUserItem;
|
||||
|
||||
\Log::debug("TeamController: Flach gesammelt - User ID: {$userId} at depth {$depth}");
|
||||
|
||||
// Rekursiv ALLE verschachtelten businessUserItems sammeln
|
||||
if (isset($businessUserItem->businessUserItems) && is_array($businessUserItem->businessUserItems) && !empty($businessUserItem->businessUserItems)) {
|
||||
\Log::debug("TeamController: Sammle " . count($businessUserItem->businessUserItems) . " verschachtelte Items von User {$userId}");
|
||||
$this->collectAllBusinessUserItemsFlat($businessUserItem->businessUserItems, $allUsers, $processedIds, $depth + 1);
|
||||
}
|
||||
} else {
|
||||
\Log::warning("TeamController: BusinessUserItem ohne user_id bei Tiefe {$depth} übersprungen");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Alte Methode zum rekursiven Sammeln von User-IDs aus BusinessUser-Struktur
|
||||
* Wird durch collectAllBusinessUserItemsFlat() ersetzt
|
||||
*/
|
||||
private function collectUserIdsFromBusinessUser($businessUser, &$allUsers, $deep, $parentless, &$processedIds = []): void
|
||||
{
|
||||
// Schutz vor zu tiefer Rekursion (maximale Tiefe: 20 Levels)
|
||||
$maxDepth = 20;
|
||||
if ($deep > $maxDepth) {
|
||||
\Log::warning("TeamController: Maximale Sammlungstiefe ({$maxDepth}) erreicht");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($businessUser->businessUserItems) && is_array($businessUser->businessUserItems)) {
|
||||
\Log::debug("TeamController: Collecting from businessUser with " . count($businessUser->businessUserItems) . " sub-items at depth {$deep}");
|
||||
|
||||
foreach ($businessUser->businessUserItems as $subBusinessUser) {
|
||||
if ($subBusinessUser) {
|
||||
// WICHTIG: user_id korrekt über b_user abrufen (Magic Method Problem mit isset())
|
||||
$userId = $subBusinessUser->user_id; // Über __get() Method
|
||||
|
||||
if ($userId) {
|
||||
// KRITISCHER BUGFIX: Prüfe ob User bereits gesammelt wurde
|
||||
if (isset($processedIds[$userId])) {
|
||||
\Log::debug("TeamController: Überspringe bereits gesammelten User {$userId} (zirkuläre Referenz verhindert)");
|
||||
continue;
|
||||
}
|
||||
|
||||
$processedIds[$userId] = true;
|
||||
$subBusinessUser->deep = $deep;
|
||||
$allUsers[] = $subBusinessUser;
|
||||
|
||||
\Log::debug("TeamController: Collected user ID: {$userId} at depth {$deep}");
|
||||
|
||||
// Rekursiver Aufruf für weitere Unter-User mit Schutz vor Zyklen
|
||||
$newDeep = $parentless ? 0 : $deep + 1;
|
||||
$this->collectUserIdsFromBusinessUser($subBusinessUser, $allUsers, $newDeep, $parentless, $processedIds);
|
||||
} else {
|
||||
\Log::warning("TeamController: SubBusinessUser ohne user_id bei Tiefe {$deep} übersprungen");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* KRITISCHE METHODE: Bereinigt BusinessUserItemOptimized Objekte für DataTables
|
||||
* Entfernt zirkuläre Referenzen und extrahiert nur nötige Properties
|
||||
*/
|
||||
private function cleanBusinessUserItemsForDataTable(array $businessUserItems): array
|
||||
{
|
||||
$cleanedUsers = [];
|
||||
|
||||
foreach ($businessUserItems as $businessUserItem) {
|
||||
if (!$businessUserItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// Extrahiere nur die Properties, die für DataTable benötigt werden
|
||||
$cleanedUser = new \stdClass();
|
||||
|
||||
// Basis Properties (direkt über Magic Method __get)
|
||||
$cleanedUser->user_id = $businessUserItem->user_id;
|
||||
$cleanedUser->m_account = $businessUserItem->m_account;
|
||||
$cleanedUser->email = $businessUserItem->email;
|
||||
$cleanedUser->first_name = $businessUserItem->first_name;
|
||||
$cleanedUser->last_name = $businessUserItem->last_name;
|
||||
$cleanedUser->user_level_name = $businessUserItem->user_level_name;
|
||||
$cleanedUser->active_account = $businessUserItem->active_account;
|
||||
$cleanedUser->active_date = $businessUserItem->active_date;
|
||||
|
||||
// Sales Volume Properties
|
||||
$cleanedUser->sales_volume_points_KP_sum = $businessUserItem->sales_volume_points_KP_sum ?? 0;
|
||||
$cleanedUser->payline_points_qual_kp = $businessUserItem->payline_points_qual_kp ?? 0;
|
||||
|
||||
// Depth für Debug/Sortierung (falls gesetzt)
|
||||
$cleanedUser->deep = $businessUserItem->deep ?? 0;
|
||||
|
||||
// Level-Informationen für Filter
|
||||
$cleanedUser->m_level_id = $businessUserItem->m_level_id;
|
||||
$cleanedUser->next_qual_user_level = $businessUserItem->next_qual_user_level;
|
||||
$cleanedUser->next_can_user_level = $businessUserItem->next_can_user_level;
|
||||
|
||||
$cleanedUsers[] = $cleanedUser;
|
||||
|
||||
\Log::debug("TeamController: Cleaned user {$cleanedUser->user_id} for DataTable");
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("TeamController: Error cleaning BusinessUserItem for DataTable: " . $e->getMessage());
|
||||
// Skip diesen User, statt alles abzubrechen
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
\Log::info("TeamController: Cleaned " . count($cleanedUsers) . " users for DataTable (from " . count($businessUserItems) . " raw items)");
|
||||
|
||||
return $cleanedUsers;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue