mivita/app/Console/Commands/TestUserLevelUpdate.php
Kevin 316a9b76d6 Pint: Formatierung des bisherigen Stands, ohne inhaltliche Aenderung
Die Dateien lagen im Arbeitsbaum formatiert und inhaltlich geaendert
zusammen. Dieser Commit enthaelt nur die Pint-Formatierung des alten
Stands, damit die folgenden Commits nur noch Inhalt zeigen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:39:17 +00:00

327 lines
12 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Cron\UserLevelUpdate;
use App\Models\UserBusiness;
use App\Models\UserLevel;
use App\User;
use Illuminate\Console\Command;
use ReflectionClass;
class TestUserLevelUpdate extends Command
{
/**
* php artisan test:user-level-update {month} {year} {--user_id=} {--send-mail} {--dry-run}
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test:user-level-update {month} {year} {--user_id= : Test für spezifischen User} {--send-mail : E-Mail senden} {--dry-run : Nur anzeigen, nicht speichern}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Testet die UserLevelUpdate-Funktion aus BusinessStoreOptimized für einen Monat/Jahr oder spezifischen User';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
try {
$month = (int) $this->argument('month');
$year = (int) $this->argument('year');
$userId = $this->option('user_id') ? (int) $this->option('user_id') : null;
$sendMail = $this->option('send-mail');
$dryRun = $this->option('dry-run');
$this->info('===========================================');
$this->info('UserLevelUpdate Test');
$this->info('===========================================');
$this->line("Monat: {$month}");
$this->line("Jahr: {$year}");
if ($userId) {
$this->line("User ID: {$userId}");
}
$this->line('E-Mail senden: '.($sendMail ? 'Ja' : 'Nein'));
$this->line('Dry-Run (nur zeigen): '.($dryRun ? 'Ja' : 'Nein'));
$this->line('');
if ($dryRun) {
// Im Dry-Run Modus zeigen wir nur die Analyse
$this->performDryRunAnalysis($month, $year, $userId);
} else {
// Nutze die originale Funktion aus BusinessStoreOptimized
$this->runOriginalFunction($month, $year, $sendMail);
}
$this->info('');
$this->info('===========================================');
$this->info('Test abgeschlossen!');
$this->info('===========================================');
return 0;
} catch (\Exception $e) {
$this->error('Test fehlgeschlagen: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
return 1;
}
}
/**
* Führt die originale userLevelUpdate Funktion aus BusinessStoreOptimized aus
*/
private function runOriginalFunction(int $month, int $year, bool $sendMail)
{
$this->info('Erstelle BusinessStoreOptimized Instanz...');
// Erstelle BusinessStoreOptimized Command-Instanz
$businessStoreCommand = new BusinessStoreOptimized;
// Setze Output auf aktuellen Command (damit Ausgaben weitergeleitet werden)
$businessStoreCommand->setOutput($this->output);
// Setze Monat und Jahr über Reflection (da private)
$reflection = new ReflectionClass($businessStoreCommand);
$monthProperty = $reflection->getProperty('month');
$monthProperty->setAccessible(true);
$monthProperty->setValue($businessStoreCommand, $month);
$yearProperty = $reflection->getProperty('year');
$yearProperty->setAccessible(true);
$yearProperty->setValue($businessStoreCommand, $year);
$timeStartProperty = $reflection->getProperty('timeStart');
$timeStartProperty->setAccessible(true);
$timeStartProperty->setValue($businessStoreCommand, microtime(true));
// Setze sendUpdateMail
$businessStoreCommand->setSendUpdateMail($sendMail);
$this->info('Führe originale userLevelUpdate() Funktion aus...');
$this->line('');
// Rufe die originale Funktion auf
$businessStoreCommand->userLevelUpdate();
}
/**
* Führt Dry-Run Analyse durch
*/
private function performDryRunAnalysis(int $month, int $year, ?int $userId)
{
$userLevelUpdate = new UserLevelUpdate($month, $year);
if ($userId) {
// Test für spezifischen User
$this->testSingleUserDryRun($userLevelUpdate, $userId);
} else {
// Test für alle User
$this->testAllUsersDryRun($userLevelUpdate);
}
}
/**
* Dry-Run Analyse für einen spezifischen User
*/
private function testSingleUserDryRun(UserLevelUpdate $userLevelUpdate, int $userId)
{
$userBusiness = UserBusiness::with('user')
->where('month', $this->argument('month'))
->where('year', $this->argument('year'))
->where('user_id', $userId)
->whereNotNull('next_qual_user_level')
->whereRaw('JSON_LENGTH(next_qual_user_level) > 0')
->first();
if (! $userBusiness) {
$this->warn("Keine UserBusiness mit next_qual_user_level gefunden für User ID: {$userId}");
// Zeige vorhandene UserBusiness-Daten
$anyUserBusiness = UserBusiness::where('user_id', $userId)
->where('month', $this->argument('month'))
->where('year', $this->argument('year'))
->first();
if ($anyUserBusiness) {
$this->info('UserBusiness existiert, aber hat kein next_qual_user_level');
$this->line('Current Level ID: '.($anyUserBusiness->m_level_id ?? 'NULL'));
$this->line('next_qual_user_level: '.(is_null($anyUserBusiness->next_qual_user_level) ? 'NULL' : json_encode($anyUserBusiness->next_qual_user_level)));
} else {
$this->warn('Keine UserBusiness gefunden für diesen Monat/Jahr');
}
return;
}
$this->displayUserBusinessInfo($userBusiness);
$this->info('');
$this->info('DRY-RUN MODUS: Änderungen werden nicht gespeichert');
$this->analyzeLevelUpdate($userBusiness);
}
/**
* Dry-Run Analyse für alle User
*/
private function testAllUsersDryRun(UserLevelUpdate $userLevelUpdate)
{
$levelUpdateUsers = $userLevelUpdate->getUserBusinessByMonthYear();
$this->info('Gefunden: '.$levelUpdateUsers->count().' UserBusiness-Einträge mit next_qual_user_level');
$this->line('');
if ($levelUpdateUsers->count() === 0) {
$this->warn('Keine UserBusiness-Einträge mit Level-Updates gefunden.');
return;
}
$this->info('DRY-RUN MODUS: Änderungen werden nicht gespeichert');
$this->line('');
foreach ($levelUpdateUsers as $userBusiness) {
$this->line('---------------------------------------------------');
$this->displayUserBusinessInfo($userBusiness);
$this->analyzeLevelUpdate($userBusiness);
$this->line('');
}
}
/**
* Zeigt Informationen über UserBusiness
*/
private function displayUserBusinessInfo(UserBusiness $userBusiness)
{
$user = $userBusiness->user;
$this->line('User ID: '.($user ? $user->id : 'NULL'));
$this->line('E-Mail: '.($user ? $user->email : 'N/A'));
$this->line('Aktuelles Level: '.($user && $user->m_level ? $user->m_level.' ('.$this->getLevelName($user->m_level).')' : 'Kein Level'));
$this->line('UserBusiness Level ID: '.($userBusiness->m_level_id ?? 'NULL'));
$this->line('UserBusiness Level Name: '.($userBusiness->user_level_name ?? 'NULL'));
$nextQual = $userBusiness->next_qual_user_level;
if (is_array($nextQual)) {
if (isset($nextQual['id'])) {
// Einzelnes Level
$this->line('Nächstes qualifiziertes Level: ID '.$nextQual['id'].' - '.($nextQual['name'] ?? 'N/A').' (POS: '.($nextQual['pos'] ?? 'N/A').')');
$this->line(' Bereits aktualisiert: '.(isset($nextQual['hasUpdated']) && $nextQual['hasUpdated'] == 1 ? 'Ja' : 'Nein'));
} else {
// Array von Leveln
$this->line('Nächste qualifizierte Level: '.count($nextQual).' Level gefunden');
foreach ($nextQual as $idx => $level) {
if (is_array($level) && isset($level['id'])) {
$updated = isset($level['hasUpdated']) && $level['hasUpdated'] == 1 ? ' (bereits aktualisiert)' : '';
$this->line(" [{$idx}] ID ".$level['id'].' - '.($level['name'] ?? 'N/A').' (POS: '.($level['pos'] ?? 'N/A').')'.$updated);
}
}
}
} else {
$this->line('next_qual_user_level: '.(is_null($nextQual) ? 'NULL' : gettype($nextQual)));
}
$this->line('Total Qual PP: '.($userBusiness->total_qual_pp ?? 0));
}
/**
* Analysiert ob und wie ein Level-Update durchgeführt würde (Dry-Run)
*/
private function analyzeLevelUpdate(UserBusiness $userBusiness)
{
$user = $userBusiness->user;
if (! $user) {
$this->warn('⚠ Kein User-Objekt vorhanden');
return;
}
$nextQual = $userBusiness->next_qual_user_level;
if (! is_array($nextQual) || empty($nextQual)) {
$this->warn('⚠ next_qual_user_level ist kein gültiges Array');
return;
}
// Lade UserLevels für Vergleich
$userLevels = UserLevel::where('active', 1)->orderBy('pos')->get()->keyBy('id');
// Prüfe ob einzelnes Level oder Array
$levelArray = isset($nextQual['id']) ? [$nextQual] : $nextQual;
$currentUserLevel = null;
if ($user->m_level) {
$currentUserLevel = $userLevels->get($user->m_level);
}
$this->info('');
$this->info('📊 Analyse:');
if ($currentUserLevel) {
$this->line(" Aktuelles Level POS: {$currentUserLevel->pos}");
} else {
$this->line(' Aktuelles Level: Kein Level gesetzt');
}
$wouldUpdate = false;
$highestLevel = null;
$highestPos = 0;
foreach ($levelArray as $levelData) {
if (! is_array($levelData) || ! isset($levelData['id'])) {
continue;
}
if (isset($levelData['hasUpdated']) && $levelData['hasUpdated'] == 1) {
$this->line(" ⏭ Level ID {$levelData['id']} wurde bereits aktualisiert");
continue;
}
$newLevel = $userLevels->get($levelData['id']);
$newLevelPos = $newLevel ? $newLevel->pos : ($levelData['pos'] ?? 0);
$levelName = $levelData['name'] ?? 'N/A';
$this->line(" 📈 Level ID {$levelData['id']} ({$levelName}): POS {$newLevelPos}");
if (! $currentUserLevel || $newLevelPos > $currentUserLevel->pos) {
if ($newLevelPos > $highestPos) {
$highestPos = $newLevelPos;
$highestLevel = $levelData;
$wouldUpdate = true;
}
} else {
$this->line(" ⚠ Level ist nicht höher als aktuelles Level (POS {$currentUserLevel->pos})");
}
}
if ($wouldUpdate && $highestLevel) {
$this->info('');
$highestLevelName = $highestLevel['name'] ?? 'N/A';
$this->info("✅ Würde Level aktualisieren zu: {$highestLevel['id']} ({$highestLevelName})");
$this->line(' Von: '.($currentUserLevel ? "POS {$currentUserLevel->pos}" : 'Kein Level')." → Zu: POS {$highestPos}");
} else {
$this->info('');
$this->warn('⚠ Kein Level-Update würde durchgeführt:');
if (! $wouldUpdate) {
$this->line(' Kein höheres Level gefunden');
}
}
}
/**
* Holt Level-Name nach ID
*/
private function getLevelName($levelId)
{
$level = UserLevel::find($levelId);
return $level ? $level->name : 'Unbekannt';
}
}