20-02-2026

This commit is contained in:
Kevin Adametz 2026-02-20 17:55:06 +01:00
parent a8b395e20d
commit a00c42e770
252 changed files with 28785 additions and 8907 deletions

View file

@ -2,11 +2,11 @@
namespace App\Console\Commands;
use App\Models\Setting;
use Illuminate\Console\Command;
use App\Cron\BusinessUsersStore;
use App\Cron\UserLevelUpdate;
use App\Cron\UserPaymentCredits;
use App\Models\Setting;
use Illuminate\Console\Command;
class BusinessStore extends Command
{
@ -27,14 +27,15 @@ class BusinessStore extends Command
protected $description = 'Create Business Structure and UserDetails with optimized performance';
private $timeStart;
private $month;
private $year;
private $sendCreditMail = false;
private $sendUpdateMail = false;
/**
* Create a new command instance.
*
@ -45,6 +46,58 @@ class BusinessStore extends Command
parent::__construct();
}
/**
* Prüft ob der Command heute ausgeführt werden soll
*
* WICHTIG: Diese Methode verhindert, dass der Command täglich läuft!
* Der Command sollte nur am konfigurierten Tag des Monats laufen.
*
* @return bool True wenn Command ausgeführt werden soll, False sonst
*/
private function shouldExecuteToday(): bool
{
// Hole konfigurierten Ausführungstag (Standard: 1 = Monatserster)
$executeDay = (int) Setting::getContentBySlug('day-exectute-business-structur');
// Fallback: Wenn Setting leer oder 0, verwende Tag 1
if ($executeDay === 0) {
$executeDay = 1;
$this->warn('Setting "day-exectute-business-structur" ist leer oder 0. Verwende Standard: Tag 1');
\Log::channel('cron')->warning('BusinessStore: Setting day-exectute-business-structur is empty, using default: 1');
}
$presentDay = (int) date('d');
// Logging für Debugging
$this->info("BusinessStore: Configured Day: {$executeDay}, Present Day: {$presentDay}");
\Log::channel('cron')->info("BusinessStore: Configured Day: {$executeDay}, Present Day: {$presentDay}");
// Prüfe ob heute der konfigurierte Tag ist
if ($executeDay !== $presentDay) {
// Erlaubnis zum Überschreiben für Entwicklung/Testing
// ENV-Variable BUSINESS_FORCE_EXECUTE=true überschreibt den Check
if (env('BUSINESS_FORCE_EXECUTE', false) === true) {
$this->warn('⚠️ BUSINESS_FORCE_EXECUTE ist aktiv - Command wird trotz falschem Tag ausgeführt!');
$this->warn('⚠️ Dies sollte NUR auf Test-Servern verwendet werden!');
\Log::channel('cron')->warning('BusinessStore: FORCED execution via BUSINESS_FORCE_EXECUTE');
return true;
}
// Command sollte heute NICHT laufen
$this->info("❌ Command wird NICHT ausgeführt - falscher Tag (erwartet: {$executeDay}, heute: {$presentDay})");
\Log::channel('cron')->info("BusinessStore: NOT EXECUTED - wrong day (expected: {$executeDay}, today: {$presentDay})");
return false;
}
// Command wird ausgeführt
$this->info("✅ Command wird ausgeführt - korrekter Tag ({$presentDay})");
\Log::channel('cron')->info("BusinessStore: EXECUTING - correct day ({$presentDay})");
return true;
}
/**
* Execute the console command.
*
@ -53,29 +106,21 @@ class BusinessStore extends Command
public function handle()
{
try {
$executeDay = (int) Setting::getContentBySlug('day-exectute-business-structur');
$presentDay = (int) date('d');
$this->info('RUN Command BusinessStore on Day: ' . $executeDay);
$this->info('RUN Command BusinessStore present Day: ' . $presentDay);
\Log::channel('cron')->info('RUN Command BusinessStore on Day: ' . $executeDay);
\Log::channel('cron')->info('RUN Command BusinessStore present Day: ' . $presentDay);
$this->logMemoryUsage('Command Start');
if ($executeDay !== $presentDay) {
$this->info('NOT RUN Command BusinessStore is not present Day: ' . $presentDay);
\Log::channel('cron')->info('NOT RUN Command BusinessStore is not present Day: ' . $presentDay);
// Prüfe ob Command am richtigen Tag ausgeführt werden soll
if (! $this->shouldExecuteToday()) {
return 0;
}
$this->logMemoryUsage('Command Start');
$this->timeStart = microtime(true);
// Argumente mit Standardwerten für den Vormonat
$this->month = $this->argument('month') ?: (int) date("m", strtotime("-1 month"));
$this->year = $this->argument('year') ?: (int) date("Y", strtotime("-1 month"));
$this->month = $this->argument('month') ?: (int) date('m', strtotime('-1 month'));
$this->year = $this->argument('year') ?: (int) date('Y', strtotime('-1 month'));
$this->info('RUN Command BusinessStore on month: ' . $this->month . ' | year: ' . $this->year);
\Log::channel('cron')->info('RUN Command BusinessStore on month: ' . $this->month . ' | year: ' . $this->year);
$this->info('RUN Command BusinessStore on month: '.$this->month.' | year: '.$this->year);
\Log::channel('cron')->info('RUN Command BusinessStore on month: '.$this->month.' | year: '.$this->year);
$this->logMemoryUsage('Parameters initialized');
// Prozesse ausführen mit Fehlerbehandlung
@ -98,9 +143,10 @@ class BusinessStore extends Command
return 0;
} catch (\Exception $e) {
$this->error('Command failed with error: ' . $e->getMessage());
$this->error('Stack trace: ' . $e->getTraceAsString());
$this->error('Command failed with error: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
$this->logExecutionTime('COMMAND FAILED');
return 1;
}
}
@ -108,25 +154,25 @@ class BusinessStore extends Command
private function storeBusinessStructureUsersDetailMonth()
{
$this->info('storeBusinessStructureUsersDetailMonth month: ' . $this->month . ' year:' . $this->year);
$this->info('storeBusinessStructureUsersDetailMonth month: '.$this->month.' year:'.$this->year);
$businessUsersStore = new BusinessUsersStore($this->month, $this->year);
$businessUsersStore->storeUserBusinessStructure();
$businessUsersStore->storeBusinessUsersDetail();
$bool = $businessUsersStore->storeBusinessCompleted();
$this->logExecutionTime('END Command storeBusinessStructureUsersDetailMonth: ' . $bool);
$this->logExecutionTime('END Command storeBusinessStructureUsersDetailMonth: '.$bool);
}
private function userBusinessCommissionsToCredit()
{
$this->info('userBusinessCommissionsToCredit month: ' . $this->month . ' year:' . $this->year);
$this->info('userBusinessCommissionsToCredit month: '.$this->month.' year:'.$this->year);
$userPaymentCredits = new UserPaymentCredits($this->month, $this->year);
$userBusinesses = $userPaymentCredits->getUserBusinessByMonthYear();
foreach ($userBusinesses as $userBusiness) {
$ret = $userPaymentCredits->addUserCreditItem($userBusiness);
$this->info('userBusinessCredit: ' . $ret->user_id . ' : Team: ' . $ret->commission_pp_total . ' | Shop: ' . $ret->commission_shop_sales);
$this->info('userBusinessCredit: '.$ret->user_id.' : Team: '.$ret->commission_pp_total.' | Shop: '.$ret->commission_shop_sales);
}
$this->logExecutionTime('END Command userBusinessCommissionsToCredit:');
}
@ -134,13 +180,13 @@ class BusinessStore extends Command
private function userCreatePaymentCreditsPDF()
{
$this->info('userCreatePaymentCreditsPDF month: ' . $this->month . ' year:' . $this->year);
$this->info('userCreatePaymentCreditsPDF month: '.$this->month.' year:'.$this->year);
$userPaymentCredits = new UserPaymentCredits($this->month, $this->year);
$creditItemUsers = $userPaymentCredits->getUserCreditItemUsersByMonthYear();
foreach ($creditItemUsers as $creditItemUser) {
$bool = $userPaymentCredits->makeCreditPaymentPDF($creditItemUser->user_id, $this->sendCreditMail);
$this->info('creditsPDF: ' . $bool . ' user_id: ' . $creditItemUser->user_id);
$this->info('creditsPDF: '.$bool.' user_id: '.$creditItemUser->user_id);
}
$this->logExecutionTime('END Command userCreatePaymentCreditsPDF:');
@ -149,7 +195,7 @@ class BusinessStore extends Command
private function userLevelUpdate()
{
$this->info('userLevelUpdate month: ' . $this->month . ' year:' . $this->year);
$this->info('userLevelUpdate month: '.$this->month.' year:'.$this->year);
$userLevelUpdate = new UserLevelUpdate($this->month, $this->year);
$levelUpdateUsers = $userLevelUpdate->getUserBusinessByMonthYear();
@ -157,26 +203,24 @@ class BusinessStore extends Command
foreach ($levelUpdateUsers as $userBusiness) {
$ret = $userLevelUpdate->makeUserLevelUpdate($userBusiness, $this->sendUpdateMail);
if ($ret) {
$this->info('updateLevel: ' . $userBusiness->user->id . ' | ' . $userBusiness->user->email . ' | ' .
'from: ' . $userBusiness->m_level_id . ' ' . $userBusiness->user_level_name . ' | ' .
'to: ' . $ret);
$this->info('updateLevel: '.$userBusiness->user->id.' | '.$userBusiness->user->email.' | '.
'from: '.$userBusiness->m_level_id.' '.$userBusiness->user_level_name.' | '.
'to: '.$ret);
}
}
$this->logExecutionTime('END Command userLevelUpdate:');
}
private function storeBusinessStructureUsersDetailPeriod($from, $to)
{
for ($i = $from; $i <= $to; $i++) {
$this->info('Store Business Structure Users Detail month: ' . $i . ' year:' . $this->year);
$this->info('Store Business Structure Users Detail month: '.$i.' year:'.$this->year);
$businessUsersStore = new BusinessUsersStore($i, $this->year);
$businessUsersStore->storeUserBusinessStructure();
$businessUsersStore->storeBusinessUsersDetail();
$bool = $businessUsersStore->storeBusinessCompleted();
$this->logExecutionTime('Period BusinessStore: ' . $bool);
$this->logExecutionTime('Period BusinessStore: '.$bool);
}
}
@ -186,6 +230,6 @@ class BusinessStore extends Command
$sec = intval($diff);
$micro = $diff - $sec;
$this->info($message . ' | Time: ' . $sec . 'sec :' . round($micro * 1000, 4) . " ms");
$this->info($message.' | Time: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
}
}

View file

@ -2,13 +2,13 @@
namespace App\Console\Commands;
use App\Models\Setting;
use App\Models\UserBusinessStructure;
use App\Models\UserBusiness;
use Illuminate\Console\Command;
use App\Cron\BusinessUsersStoreOptimized;
use App\Cron\UserLevelUpdate;
use App\Cron\UserPaymentCredits;
use App\Models\Setting;
use App\Models\UserBusiness;
use App\Models\UserBusinessStructure;
use Illuminate\Console\Command;
class BusinessStoreOptimized extends Command
{
@ -29,10 +29,13 @@ class BusinessStoreOptimized extends Command
protected $description = 'Create Business Structure and UserDetails with optimized performance and monitoring';
private $timeStart;
private $month;
private $year;
private $sendCreditMail = false;
private $sendUpdateMail = false;
/**
@ -51,6 +54,58 @@ class BusinessStoreOptimized extends Command
$this->sendUpdateMail = $sendUpdateMail;
}
/**
* Prüft ob der Command heute ausgeführt werden soll
*
* WICHTIG: Diese Methode verhindert, dass der Command täglich läuft!
* Der Command sollte nur am konfigurierten Tag des Monats laufen.
*
* @return bool True wenn Command ausgeführt werden soll, False sonst
*/
private function shouldExecuteToday(): bool
{
// Hole konfigurierten Ausführungstag (Standard: 1 = Monatserster)
$executeDay = (int) Setting::getContentBySlug('day-exectute-business-structur');
// Fallback: Wenn Setting leer oder 0, verwende Tag 1
if ($executeDay === 0) {
$executeDay = 1;
$this->warn('Setting "day-exectute-business-structur" ist leer oder 0. Verwende Standard: Tag 1');
\Log::channel('cron')->warning('BusinessStoreOptimized: Setting day-exectute-business-structur is empty, using default: 1');
}
$presentDay = (int) date('d');
// Logging für Debugging
$this->info("BusinessStoreOptimized: Configured Day: {$executeDay}, Present Day: {$presentDay}");
\Log::channel('cron')->info("BusinessStoreOptimized: Configured Day: {$executeDay}, Present Day: {$presentDay}");
// Prüfe ob heute der konfigurierte Tag ist
if ($executeDay !== $presentDay) {
// Erlaubnis zum Überschreiben für Entwicklung/Testing
// ENV-Variable BUSINESS_FORCE_EXECUTE=true überschreibt den Check
if (env('BUSINESS_FORCE_EXECUTE', false) === true) {
$this->warn('⚠️ BUSINESS_FORCE_EXECUTE ist aktiv - Command wird trotz falschem Tag ausgeführt!');
$this->warn('⚠️ Dies sollte NUR auf Test-Servern verwendet werden!');
\Log::channel('cron')->warning('BusinessStoreOptimized: FORCED execution via BUSINESS_FORCE_EXECUTE');
return true;
}
// Command sollte heute NICHT laufen
$this->info("❌ Command wird NICHT ausgeführt - falscher Tag (erwartet: {$executeDay}, heute: {$presentDay})");
\Log::channel('cron')->info("BusinessStoreOptimized: NOT EXECUTED - wrong day (expected: {$executeDay}, today: {$presentDay})");
return false;
}
// Command wird ausgeführt
$this->info("✅ Command wird ausgeführt - korrekter Tag ({$presentDay})");
\Log::channel('cron')->info("BusinessStoreOptimized: EXECUTING - correct day ({$presentDay})");
return true;
}
/**
* Create a new command instance.
*
@ -69,28 +124,20 @@ class BusinessStoreOptimized extends Command
public function handle()
{
try {
$executeDay = (int) Setting::getContentBySlug('day-exectute-business-structur');
$presentDay = (int) date('d');
$this->info('RUN Command BusinessStoreOptimized on Day: ' . $executeDay);
$this->info('RUN Command BusinessStoreOptimized present Day: ' . $presentDay);
\Log::channel('cron')->info('RUN Command BusinessStoreOptimized on Day: ' . $executeDay);
\Log::channel('cron')->info('RUN Command BusinessStoreOptimized present Day: ' . $presentDay);
$this->logMemoryUsage('Command Start');
if ($executeDay !== $presentDay) {
$this->info('NOT RUN Command BusinessStoreOptimized is not present Day: ' . $presentDay);
\Log::channel('cron')->info('NOT RUN Command BusinessStoreOptimized is not present Day: ' . $presentDay);
// return 0;
// Prüfe ob Command am richtigen Tag ausgeführt werden soll
if (! $this->shouldExecuteToday()) {
return 0;
}
$this->logMemoryUsage('Command Start');
$this->timeStart = microtime(true);
// Argumente mit Standardwerten für den Vormonat
$this->month = $this->argument('month') ?: (int) date("m", strtotime("-1 month"));
$this->year = $this->argument('year') ?: (int) date("Y", strtotime("-1 month"));
$this->month = $this->argument('month') ?: (int) date('m', strtotime('-1 month'));
$this->year = $this->argument('year') ?: (int) date('Y', strtotime('-1 month'));
$this->info('RUN Command BusinessStoreOptimized on month: ' . $this->month . ' | year: ' . $this->year);
$this->info('RUN Command BusinessStoreOptimized on month: '.$this->month.' | year: '.$this->year);
$this->logMemoryUsage('Parameters initialized');
// Prüfe --clear Option und lösche gespeicherte Daten falls gewünscht
@ -126,17 +173,18 @@ class BusinessStoreOptimized extends Command
return 0;
} catch (\Exception $e) {
$this->error('Command failed with error: ' . $e->getMessage());
$this->error('Stack trace: ' . $e->getTraceAsString());
$this->error('Command failed with error: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
$this->logExecutionTime('COMMAND FAILED');
\Log::channel('cron')->info('COMMAND FAILED');
return 1;
}
}
private function storeBusinessStructureUsersDetailMonth()
{
$this->info('storeBusinessStructureUsersDetailMonth month: ' . $this->month . ' year:' . $this->year);
$this->info('storeBusinessStructureUsersDetailMonth month: '.$this->month.' year:'.$this->year);
try {
$businessUsersStore = new BusinessUsersStoreOptimized($this->month, $this->year);
@ -144,16 +192,16 @@ class BusinessStoreOptimized extends Command
$businessUsersStore->storeBusinessUsersDetail();
$bool = $businessUsersStore->storeBusinessCompleted();
$this->logExecutionTime('END Command storeBusinessStructureUsersDetailMonth: ' . $bool);
$this->logExecutionTime('END Command storeBusinessStructureUsersDetailMonth: '.$bool);
} catch (\Exception $e) {
$this->error('Error in storeBusinessStructureUsersDetailMonth: ' . $e->getMessage());
$this->error('Error in storeBusinessStructureUsersDetailMonth: '.$e->getMessage());
throw $e;
}
}
private function userBusinessCommissionsToCredit()
{
$this->info('userBusinessCommissionsToCredit month: ' . $this->month . ' year:' . $this->year);
$this->info('userBusinessCommissionsToCredit month: '.$this->month.' year:'.$this->year);
try {
$userPaymentCredits = new UserPaymentCredits($this->month, $this->year);
@ -162,7 +210,7 @@ class BusinessStoreOptimized extends Command
$processedCount = 0;
foreach ($userBusinesses as $userBusiness) {
$ret = $userPaymentCredits->addUserCreditItem($userBusiness);
$this->info('userBusinessCredit: ' . $ret->user_id . ' : Team: ' . $ret->commission_pp_total . ' | Shop: ' . $ret->commission_shop_sales);
$this->info('userBusinessCredit: '.$ret->user_id.' : Team: '.$ret->commission_pp_total.' | Shop: '.$ret->commission_shop_sales);
$processedCount++;
// Memory-Check alle 100 User
@ -174,14 +222,14 @@ class BusinessStoreOptimized extends Command
$this->info("Processed {$processedCount} user businesses total");
$this->logExecutionTime('END Command userBusinessCommissionsToCredit:');
} catch (\Exception $e) {
$this->error('Error in userBusinessCommissionsToCredit: ' . $e->getMessage());
$this->error('Error in userBusinessCommissionsToCredit: '.$e->getMessage());
throw $e;
}
}
private function userCreatePaymentCreditsPDF()
{
$this->info('userCreatePaymentCreditsPDF month: ' . $this->month . ' year:' . $this->year);
$this->info('userCreatePaymentCreditsPDF month: '.$this->month.' year:'.$this->year);
try {
$userPaymentCredits = new UserPaymentCredits($this->month, $this->year);
@ -190,7 +238,7 @@ class BusinessStoreOptimized extends Command
$processedCount = 0;
foreach ($creditItemUsers as $creditItemUser) {
$bool = $userPaymentCredits->makeCreditPaymentPDF($creditItemUser->user_id, $this->sendCreditMail);
$this->info('creditsPDF: ' . $bool . ' user_id: ' . $creditItemUser->user_id);
$this->info('creditsPDF: '.$bool.' user_id: '.$creditItemUser->user_id);
$processedCount++;
// Memory-Check alle 50 PDFs
@ -202,7 +250,7 @@ class BusinessStoreOptimized extends Command
$this->info("Created {$processedCount} PDF files total");
$this->logExecutionTime('END Command userCreatePaymentCreditsPDF:');
} catch (\Exception $e) {
$this->error('Error in userCreatePaymentCreditsPDF: ' . $e->getMessage());
$this->error('Error in userCreatePaymentCreditsPDF: '.$e->getMessage());
throw $e;
}
}
@ -213,13 +261,13 @@ class BusinessStoreOptimized extends Command
*/
public function userLevelUpdate()
{
$this->info('userLevelUpdate month: ' . $this->month . ' year:' . $this->year);
$this->info('userLevelUpdate month: '.$this->month.' year:'.$this->year);
try {
$userLevelUpdate = new UserLevelUpdate($this->month, $this->year);
$levelUpdateUsers = $userLevelUpdate->getUserBusinessByMonthYear();
$this->info("Found " . $levelUpdateUsers->count() . " user businesses with level promotions to process");
$this->info('Found '.$levelUpdateUsers->count().' user businesses with level promotions to process');
$updatedCount = 0;
$skippedCount = 0;
@ -229,11 +277,11 @@ class BusinessStoreOptimized extends Command
try {
$ret = $userLevelUpdate->makeUserLevelUpdate($userBusiness, $this->sendUpdateMail);
if ($ret) {
$oldLevel = $userBusiness->m_level_id . ' ' . ($userBusiness->user_level_name ?? 'N/A');
$this->info('updateLevel: User ' . $userBusiness->user->id .
' | ' . $userBusiness->user->email .
' | from: ' . $oldLevel .
' | to: ' . $ret);
$oldLevel = $userBusiness->m_level_id.' '.($userBusiness->user_level_name ?? 'N/A');
$this->info('updateLevel: User '.$userBusiness->user->id.
' | '.$userBusiness->user->email.
' | from: '.$oldLevel.
' | to: '.$ret);
$updatedCount++;
} else {
$skippedCount++;
@ -241,12 +289,13 @@ class BusinessStoreOptimized extends Command
// Memory-Check alle 50 User
if (($updatedCount + $skippedCount) % 50 === 0) {
$this->logMemoryUsage("After processing " . ($updatedCount + $skippedCount) . " users");
$this->logMemoryUsage('After processing '.($updatedCount + $skippedCount).' users');
}
} catch (\Exception $e) {
$errorCount++;
$this->warn('Error updating level for UserBusiness ' . $userBusiness->id . ': ' . $e->getMessage());
\Log::channel('cron')->warning('UserLevelUpdate error for UserBusiness ' . $userBusiness->id . ': ' . $e->getMessage());
$this->warn('Error updating level for UserBusiness '.$userBusiness->id.': '.$e->getMessage());
\Log::channel('cron')->warning('UserLevelUpdate error for UserBusiness '.$userBusiness->id.': '.$e->getMessage());
// Weiter mit nächstem User statt abzubrechen
continue;
}
@ -256,9 +305,9 @@ class BusinessStoreOptimized extends Command
$this->logExecutionTime('END Command userLevelUpdate:');
$this->logMemoryUsage('After userLevelUpdate');
} catch (\Exception $e) {
$this->error('Error in userLevelUpdate: ' . $e->getMessage());
$this->error('Stack trace: ' . $e->getTraceAsString());
\Log::channel('cron')->error('UserLevelUpdate command failed: ' . $e->getMessage());
$this->error('Error in userLevelUpdate: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
\Log::channel('cron')->error('UserLevelUpdate command failed: '.$e->getMessage());
throw $e;
}
}
@ -267,7 +316,7 @@ class BusinessStoreOptimized extends Command
{
try {
for ($i = $from; $i <= $to; $i++) {
$this->info('Store Business Structure Users Detail month: ' . $i . ' year:' . $this->year);
$this->info('Store Business Structure Users Detail month: '.$i.' year:'.$this->year);
$this->logMemoryUsage("Before month {$i}");
$businessUsersStore = new BusinessUsersStoreOptimized($i, $this->year);
@ -275,11 +324,11 @@ class BusinessStoreOptimized extends Command
$businessUsersStore->storeBusinessUsersDetail();
$bool = $businessUsersStore->storeBusinessCompleted();
$this->logExecutionTime('Period BusinessStore: ' . $bool);
$this->logExecutionTime('Period BusinessStore: '.$bool);
$this->logMemoryUsage("After month {$i}");
}
} catch (\Exception $e) {
$this->error('Error in storeBusinessStructureUsersDetailPeriod: ' . $e->getMessage());
$this->error('Error in storeBusinessStructureUsersDetailPeriod: '.$e->getMessage());
throw $e;
}
}
@ -297,8 +346,9 @@ class BusinessStoreOptimized extends Command
->where('month', $this->month)
->first();
if (!$existingStructure) {
if (! $existingStructure) {
$this->info('No stored business structure found to clear');
return;
}
@ -322,7 +372,7 @@ class BusinessStoreOptimized extends Command
$this->info('Successfully cleared all stored business data');
$this->logMemoryUsage('After clearing data');
} catch (\Exception $e) {
$this->error('Error clearing stored data: ' . $e->getMessage());
$this->error('Error clearing stored data: '.$e->getMessage());
throw $e;
}
}
@ -333,7 +383,7 @@ class BusinessStoreOptimized extends Command
$sec = intval($diff);
$micro = $diff - $sec;
$this->info($message . ' | Time: ' . $sec . 'sec :' . round($micro * 1000, 4) . " ms");
$this->info($message.' | Time: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
}
/**
@ -353,8 +403,8 @@ class BusinessStoreOptimized extends Command
$this->info("Completed: {$processName} in {$duration}ms");
$this->logMemoryUsage("After {$processName}");
} catch (\Exception $e) {
$this->error("Error in {$processName}: " . $e->getMessage());
$this->error("Stack trace: " . $e->getTraceAsString());
$this->error("Error in {$processName}: ".$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
throw $e;
}
}
@ -406,12 +456,12 @@ class BusinessStoreOptimized extends Command
*/
private function formatBytes(int $bytes, int $precision = 2): string
{
$units = array('B', 'KB', 'MB', 'GB', 'TB');
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
$bytes /= 1024;
}
return round($bytes, $precision) . ' ' . $units[$i];
return round($bytes, $precision).' '.$units[$i];
}
}

View file

@ -17,18 +17,20 @@ class DhlUpdateTracking extends Command
* @var string
*/
protected $signature = 'dhl:update-tracking
{--days=14 : Sendungen der letzten X Tage aktualisieren}
{--days=30 : Sendungen der letzten X Tage aktualisieren}
{--send-emails : Automatisch E-Mails bei Transit-Status senden}
{--dry-run : Nur simulieren, keine Änderungen}
{--test-email= : Test-E-Mail an angegebene Adresse senden}
{--order= : Nur für bestimmte Bestellung (Order-ID)}';
{--order= : Nur für bestimmte Bestellung (Order-ID)}
{--force : Intervall-Filter überspringen, alle aktiven Sendungen aktualisieren}
{--stale-days=30 : Sendungen ohne Statusänderung nach X Tagen als abgeschlossen markieren}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Aktualisiert Tracking-Status für alle aktiven DHL Sendungen und sendet automatisch E-Mails bei Transit-Status';
protected $description = 'Aktualisiert Tracking-Status für DHL Sendungen (status-basierte Intervalle, Batch-API)';
/**
* Execute the console command.
@ -40,9 +42,14 @@ class DhlUpdateTracking extends Command
$dryRun = $this->option('dry-run');
$testEmail = $this->option('test-email');
$orderId = $this->option('order');
$force = $this->option('force');
$staleDays = (int) $this->option('stale-days');
$this->info('DHL Tracking Update gestartet');
$this->info("Optionen: --days={$days}, --send-emails=" . ($sendEmails ? 'ja' : 'nein') . ', --dry-run=' . ($dryRun ? 'ja' : 'nein'));
$this->info("Optionen: --days={$days}, --send-emails=".($sendEmails ? 'ja' : 'nein')
.', --dry-run='.($dryRun ? 'ja' : 'nein')
.', --force='.($force ? 'ja' : 'nein')
.", --stale-days={$staleDays}");
if ($testEmail) {
$this->info("Test-Modus: E-Mails werden an {$testEmail} gesendet");
}
@ -51,95 +58,185 @@ class DhlUpdateTracking extends Command
}
$this->newLine();
// Hole alle aktiven Sendungen der letzten X Tage
$query = DhlShipment::active()
// Step 1: Mark stale shipments as completed (before main query)
$staleCompleted = $this->markStaleShipmentsCompleted($staleDays, $dryRun);
// Step 2: Build query for shipments that need tracking update
$query = $this->buildShipmentQuery($days, $orderId, $force);
$shipments = $query->orderBy('created_at', 'desc')->get();
// Count total active shipments for statistics (before interval filter)
$totalActive = DhlShipment::active()
->whereNull('tracking_completed_at')
->where('created_at', '>=', now()->subDays($days))
->whereNotNull('dhl_shipment_no');
->whereNotNull('dhl_shipment_no')
->count();
$total = $shipments->count();
$skippedByInterval = $totalActive - $total;
$this->info("Aktive Sendungen gesamt: {$totalActive}");
$this->info('Übersprungen (Intervall): '.max(0, $skippedByInterval));
$this->info("Zu aktualisieren: {$total}");
if ($total === 0) {
$this->info('Keine Sendungen zum Aktualisieren gefunden.');
$this->printSummary(0, ['updated' => 0, 'failed' => 0, 'completed' => 0, 'emails_sent' => 0, 'skipped' => 0], $staleCompleted, max(0, $skippedByInterval));
return self::SUCCESS;
}
$trackingService = new DhlTrackingService;
$stats = [
'updated' => 0,
'failed' => 0,
'completed' => 0,
'emails_sent' => 0,
'skipped' => 0,
];
if ($dryRun) {
$stats['skipped'] = $total;
$this->info("Dry-Run: {$total} Sendungen würden aktualisiert.");
} else {
// Collect old statuses for email decision
$oldStatuses = $shipments->pluck('status', 'id')->toArray();
// Use batch API for efficient processing
$this->info('Starte Batch-Tracking-Update...');
$bar = $this->output->createProgressBar($total);
$bar->start();
$batchResult = $trackingService->updateTrackingBatch($shipments);
$stats['updated'] = $batchResult['updated'];
$stats['failed'] = $batchResult['failed'];
$stats['completed'] = $batchResult['completed'];
$bar->advance($total);
$bar->finish();
$this->newLine(2);
// Send tracking emails if enabled
if ($sendEmails) {
$this->info('Prüfe E-Mail-Versand...');
foreach ($shipments as $shipment) {
$shipment->refresh();
$oldStatus = $oldStatuses[$shipment->id] ?? '';
if ($this->shouldSendEmail($shipment, $oldStatus)) {
try {
$this->sendTrackingEmail($shipment, $testEmail);
$stats['emails_sent']++;
} catch (\Exception $e) {
Log::error('[DHL Cron] Failed to send tracking email', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
]);
}
}
}
}
}
$this->printSummary($total, $stats, $staleCompleted, max(0, $skippedByInterval));
Log::info('[DHL Cron] Tracking update completed', array_merge($stats, [
'total' => $total,
'stale_completed' => $staleCompleted,
'skipped_interval' => max(0, $skippedByInterval),
]));
return self::SUCCESS;
}
/**
* Build the shipment query with or without interval filtering.
*/
private function buildShipmentQuery(int $days, ?string $orderId, bool $force)
{
if ($force) {
// --force: Alle aktiven Sendungen ohne Intervall-Filter
$query = DhlShipment::active()
->whereNull('tracking_completed_at')
->where('created_at', '>=', now()->subDays($days))
->whereNotNull('dhl_shipment_no');
} else {
// Normal: Status-basierte Intervalle beachten
$query = DhlShipment::needsTrackingUpdate()
->where('created_at', '>=', now()->subDays($days));
}
// Filter nach Order-ID wenn angegeben
if ($orderId) {
$query->where('order_id', $orderId);
}
$shipments = $query->orderBy('created_at', 'desc')->get();
return $query;
}
$total = $shipments->count();
$this->info("Gefundene aktive Sendungen: {$total}");
/**
* Mark shipments as tracking-completed if they haven't changed status
* for a given number of days (stale shipments).
*/
private function markStaleShipmentsCompleted(int $staleDays, bool $dryRun): int
{
$staleShipments = DhlShipment::active()
->whereNull('tracking_completed_at')
->whereNotNull('last_tracked_at')
->where('last_tracked_at', '<', now()->subDays($staleDays))
->where('created_at', '<', now()->subDays($staleDays))
->get();
if ($total === 0) {
$this->info('Keine Sendungen zum Aktualisieren gefunden.');
$count = $staleShipments->count();
return self::SUCCESS;
}
if ($count > 0) {
$this->warn("Veraltete Sendungen gefunden: {$count} (>{$staleDays} Tage ohne Änderung)");
$bar = $this->output->createProgressBar($total);
$bar->start();
if (! $dryRun) {
foreach ($staleShipments as $shipment) {
$shipment->markTrackingCompleted();
$trackingService = new DhlTrackingService;
$stats = [
'updated' => 0,
'failed' => 0,
'emails_sent' => 0,
'skipped' => 0,
];
foreach ($shipments as $shipment) {
try {
$oldStatus = $shipment->status;
if (! $dryRun) {
// Tracking aktualisieren
$result = $trackingService->updateTracking($shipment, ['auto_retrack' => false]);
if ($result['success']) {
$shipment->refresh();
$stats['updated']++;
// Prüfen ob E-Mail gesendet werden soll
if ($sendEmails && $this->shouldSendEmail($shipment, $oldStatus)) {
$this->sendTrackingEmail($shipment, $testEmail);
$stats['emails_sent']++;
}
} else {
$stats['failed']++;
Log::warning('[DHL Cron] Tracking update failed', [
'shipment_id' => $shipment->id,
'message' => $result['message'] ?? 'Unknown error',
]);
}
} else {
$stats['skipped']++;
Log::info('[DHL Cron] Stale shipment tracking completed', [
'shipment_id' => $shipment->id,
'dhl_shipment_no' => $shipment->dhl_shipment_no,
'status' => $shipment->status,
'last_tracked_at' => $shipment->last_tracked_at?->toDateTimeString(),
]);
}
} catch (\Exception $e) {
$stats['failed']++;
Log::error('[DHL Cron] Exception during tracking update', [
'shipment_id' => $shipment->id,
'error' => $e->getMessage(),
]);
}
$bar->advance();
$this->info("{$count} Sendungen als Tracking-abgeschlossen markiert.");
} else {
$this->info(" → Dry-Run: {$count} Sendungen würden als abgeschlossen markiert.");
}
}
$bar->finish();
$this->newLine(2);
$this->newLine();
// Zusammenfassung
return $count;
}
/**
* Print the final summary table.
*/
private function printSummary(int $total, array $stats, int $staleCompleted, int $skippedByInterval): void
{
$this->info('Zusammenfassung:');
$this->table(
['Metrik', 'Anzahl'],
[
['Gesamt', $total],
['Zu aktualisieren', $total],
['Aktualisiert', $stats['updated']],
['Fehlgeschlagen', $stats['failed']],
['Tracking abgeschlossen', $stats['completed']],
['E-Mails gesendet', $stats['emails_sent']],
['Übersprungen (Dry-Run)', $stats['skipped']],
['Übersprungen (Intervall)', $skippedByInterval],
['Veraltet → abgeschlossen', $staleCompleted],
]
);
Log::info('[DHL Cron] Tracking update completed', $stats);
return self::SUCCESS;
}
/**
@ -212,9 +309,9 @@ class DhlUpdateTracking extends Command
]);
if ($allShipments->count() > 1) {
$this->line(" -> E-Mail mit {$allShipments->count()} Sendungen gesendet an: {$recipientEmail}");
$this->line(" E-Mail mit {$allShipments->count()} Sendungen gesendet an: {$recipientEmail}");
} else {
$this->line(" -> E-Mail gesendet an: {$recipientEmail}");
$this->line(" E-Mail gesendet an: {$recipientEmail}");
}
} catch (\Exception $e) {
Log::error('[DHL Cron] Failed to send tracking email', [

View file

@ -0,0 +1,119 @@
<?php
namespace App\Console\Commands;
use App\Models\ShoppingInstance;
use App\Models\ShoppingPayment;
use Illuminate\Console\Command;
class FixPaymentLinkStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'payment:fix-link-status {--dry-run : Run without making changes}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix payment link status for paid orders that have incorrect status in shopping_instances';
/**
* Execute the console command.
*/
public function handle()
{
$isDryRun = $this->option('dry-run');
if ($isDryRun) {
$this->info(' DRY RUN MODE - No changes will be made');
$this->newLine();
}
$this->info('🔎 Searching for payment links with incorrect status...');
$this->newLine();
// Find all ShoppingPayments with identifier that are paid
$paidPayments = ShoppingPayment::whereNotNull('identifier')
->whereHas('shopping_order', function ($query) {
$query->where('paid', 1)
->where('txaction', 'paid');
})
->with(['shopping_order'])
->get();
$this->info("Found {$paidPayments->count()} paid payments with identifiers");
$this->newLine();
$fixed = 0;
$skipped = 0;
$errors = 0;
foreach ($paidPayments as $payment) {
$identifier = $payment->identifier;
// Find the corresponding ShoppingInstance
$instance = ShoppingInstance::where('identifier', $identifier)->first();
if (! $instance) {
$this->warn("⚠️ ShoppingInstance not found for identifier: {$identifier}");
$errors++;
continue;
}
// Check if status needs to be updated
if ($instance->status < 10) {
$oldStatus = $instance->status;
$oldStatusName = $instance->getStatus();
if (! $isDryRun) {
$instance->status = 10; // link_paid
$instance->save();
}
$this->line(sprintf(
'%s Payment #%d: %s → %s (Order #%d, Amount: %s)',
$isDryRun ? '📋' : '✅',
$payment->id,
$oldStatusName." ($oldStatus)",
'link_paid (10)',
$payment->shopping_order_id,
$payment->getPaymentAmount()
));
$fixed++;
} else {
$skipped++;
}
}
$this->newLine();
$this->info('📊 Summary:');
$this->table(
['Status', 'Count'],
[
['Fixed/Would fix', $fixed],
['Already correct', $skipped],
['Errors', $errors],
['Total processed', $paidPayments->count()],
]
);
if ($isDryRun && $fixed > 0) {
$this->newLine();
$this->warn('⚠️ This was a DRY RUN. Run without --dry-run to apply changes.');
}
if (! $isDryRun && $fixed > 0) {
$this->newLine();
$this->info("✨ Successfully updated {$fixed} payment link(s)!");
}
return 0;
}
}

View file

@ -2,17 +2,14 @@
namespace App\Console\Commands;
use App\Services\UserUtil;
use App\User;
use Carbon\Carbon;
use App\Services\UserUtil;
use Illuminate\Console\Command;
class UserCleanUp extends Command
{
/**
* ln -sfv /usr/bin/php73 /usr/bin/php
* php74 artisan user:cleanup
* The name and signature of the console command.
*
* @var string
@ -24,7 +21,8 @@ class UserCleanUp extends Command
*
* @var string
*/
protected $description = 'User Clean Up inactive for Business Structur and UserDetails';
protected $description = 'User Clean Up inactive for Business Structure and UserDetails';
private $timeStart;
/**
@ -44,118 +42,162 @@ class UserCleanUp extends Command
*/
public function handle()
{
$this->info('RUN Command user:cleanup');
\Log::channel('cleanup')->info('COMMAND [user:cleanup] started.');
$this->timeStart = microtime(true);
$this->deleteInavtiveUsers();
//alle inaktive User werden deaktivert, die childs werden dem nächsten aktiven Berater (parent) zugewiesen.
// Schritt 1: User löschen, die länger als 2 Monate inaktiv sind
$this->deleteInactiveUsers();
// Schritt 2: Alle inaktiven User deaktivieren (länger als 2 Wochen inaktiv)
// Ihre Downline wird dem nächsten aktiven Berater (Sponsor) zugewiesen
$this->cleanUpInActiveUser();
return 0;
\Log::channel('cleanup')->info('COMMAND [user:cleanup] finished.');
//return 0;
return 0;
}
//gibt es gelöschte Berater mit Kunden und childs???
private function deleteInavtiveUsers()
/**
* Löscht User, die länger als 2 Monate inaktiv sind (payment_account < -2 month)
* - Weist deren Vertriebspartner-Kinder dem nächsten aktiven Sponsor zu
* - Überträgt deren Shopping-Kunden zum neuen Sponsor
* - Konvertiert den User zu einem Shopping-Kunden
* - Löscht den User (soft delete)
*/
private function deleteInactiveUsers()
{
$this->info('START Command deleteInavtiveUsers');
$methodStartTime = microtime(true);
$this->info('START Command deleteInactiveUsers');
$count = 0;
$date = Carbon::now()->modify('-2 month');
$delete_users = User::where('admin', 0)->where('payment_account', '<', $date)->get();
foreach ($delete_users as $delete_user) {
/*
dump('delete_users ---------- ');
dump($delete_user->id);
dump($delete_user->email);
*/
//finde nächsten aktiven Sponsor $delete_user->id kann sponsor oder pre sponsor sein
$active_sponsor = UserUtil::findNextActiveSponsor($delete_user->id);
if ($active_sponsor) {
//setze alle Berater vom Sponsor für alle childs
\DB::beginTransaction();
try {
// Finde nächsten aktiven Sponsor
$active_sponsor = UserUtil::findNextActiveSponsor($delete_user->id);
if (! $active_sponsor) {
\Log::channel('cleanup')->error('deleteInactiveUsers find no active_sponsor by delete_user_id: '.$delete_user->id);
\DB::rollBack();
continue;
}
// Prüfe ob User Account-Daten hat
if (! $delete_user->account) {
\Log::channel('cleanup')->error('deleteInactiveUsers: User has no account data, skipping user_id: '.$delete_user->id);
\DB::rollBack();
continue;
}
// Setze alle Vertriebspartner-Kinder zum neuen Sponsor
UserUtil::setNewSponsorToChilds($delete_user->id, $active_sponsor->id);
// Übertrage Shopping-User zum neuen Sponsor
UserUtil::setShoppingUserToNewMember($delete_user->id, $active_sponsor->id);
} else {
\Log::channel('cleanup')->error('deleteInavtiveUsers find no active_sponsor by delete_user_id:' . $delete_user->id);
// Konvertiere User zu Client beim neuen Sponsor
UserUtil::setUserToClient($delete_user->id, $active_sponsor->id);
$data = [
'user_id' => $delete_user->id,
'email' => $delete_user->email,
'm_account' => $delete_user->account->m_account,
'm_first_name' => $delete_user->account->m_first_name,
'm_last_name' => $delete_user->account->m_last_name,
];
// Lösche User (soft delete)
UserUtil::deleteUser($delete_user);
\DB::commit();
$count++;
\Log::channel('cleanup')->info('deleteUser: '.json_encode($data));
} catch (\Exception $e) {
\DB::rollBack();
\Log::channel('cleanup')->error('deleteInactiveUsers failed for user_id: '.$delete_user->id.' | Error: '.$e->getMessage());
continue;
}
/*
dump('findNextActiveSponsor');
dump($active_sponsor->email);
*/
//make User to an Client from sponsor and delete User
UserUtil::setUserToClient($delete_user->id, $active_sponsor->id);
$data = [
'user_id' => $delete_user->id,
'email' => $delete_user->email,
'm_account' => $delete_user->account ? $delete_user->account->m_account : '',
'm_first_name' => $delete_user->account ? $delete_user->account->m_first_name : '',
'm_last_name' => $delete_user->account ? $delete_user->account->m_last_name : '',
];
$count++;
\Log::channel('cleanup')->info('deleteUser: ' . json_encode($data));
UserUtil::deleteUser($delete_user);
}
$diff = microtime(true) - $this->timeStart;
$diff = microtime(true) - $methodStartTime;
$sec = intval($diff);
$micro = $diff - $sec;
$this->info('END Command deleteInavtiveUsers: ' . $count . ' | Time: ' . $sec . 'sec :' . round($micro * 1000, 4) . " ms");
$this->info('END Command deleteInactiveUsers: '.$count.' | Time: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
}
/**
* Deaktiviert User, die länger als 2 Wochen inaktiv sind
* - Weist deren Vertriebspartner-Kinder dem nächsten aktiven Sponsor zu
* - Deaktiviert den User (behält Account, speichert Sponsor in pre_sponsor)
* - Shopping-Kunden werden NICHT übertragen (bleiben beim deaktivierten User)
*/
private function cleanUpInActiveUser()
{
$methodStartTime = microtime(true);
$this->info('START Command cleanUpInActiveUser');
$count = 0;
//clean up user where inactive since 2 weeks
// Finde User die länger als 2 Wochen inaktiv sind
$date = Carbon::now()->modify('-2 weeks');
$inactive_users = User::where('active', true)->where('m_sponsor', '!=', null)->where('payment_account', '<', $date)->get();
foreach ($inactive_users as $inactive_user) {
/*
dump('inactive_user ---------- ');
dump($inactive_user->id);
dump($inactive_user->email);
*/
$active_sponsor = UserUtil::findNextActiveSponsor($inactive_user->m_sponsor);
if ($active_sponsor) {
UserUtil::setNewSponsorToChilds($inactive_user->id, $active_sponsor->id);
} else {
\Log::channel('cleanup')->error('cleanUpInActiveUser find no active_sponsor by inactive_user:' . $inactive_user->id);
}
/*
dump('findNextActiveSponsor');
dump($active_sponsor->email);
*/
$data = [
'user_id' => $inactive_user->id,
'email' => $inactive_user->email,
'm_account' => $inactive_user->account ? $inactive_user->account->m_account : '',
'm_first_name' => $inactive_user->account ? $inactive_user->account->m_first_name : '',
'm_last_name' => $inactive_user->account ? $inactive_user->account->m_last_name : '',
];
$count++;
$inactive_users = User::where('active', true)
->where('m_sponsor', '!=', null)
->where('payment_account', '<', $date)
->get();
\Log::channel('cleanup')->info('inactive_user: ' . json_encode($data));
UserUtil::deactiveUser($inactive_user);
foreach ($inactive_users as $inactive_user) {
\DB::beginTransaction();
try {
// Finde nächsten aktiven Sponsor
$active_sponsor = UserUtil::findNextActiveSponsor($inactive_user->m_sponsor);
if (! $active_sponsor) {
\Log::channel('cleanup')->error('cleanUpInActiveUser find no active_sponsor by inactive_user: '.$inactive_user->id);
\DB::rollBack();
continue;
}
// Setze alle Vertriebspartner-Kinder zum neuen Sponsor
UserUtil::setNewSponsorToChilds($inactive_user->id, $active_sponsor->id);
$data = [
'user_id' => $inactive_user->id,
'email' => $inactive_user->email,
'm_account' => $inactive_user->account ? $inactive_user->account->m_account : '',
'm_first_name' => $inactive_user->account ? $inactive_user->account->m_first_name : '',
'm_last_name' => $inactive_user->account ? $inactive_user->account->m_last_name : '',
];
// Deaktiviere User (setzt pre_sponsor, entfernt m_sponsor, setzt active=false)
UserUtil::deactiveUser($inactive_user);
\DB::commit();
$count++;
\Log::channel('cleanup')->info('inactive_user: '.json_encode($data));
} catch (\Exception $e) {
\DB::rollBack();
\Log::channel('cleanup')->error('cleanUpInActiveUser failed for user_id: '.$inactive_user->id.' | Error: '.$e->getMessage());
continue;
}
}
$diff = microtime(true) - $this->timeStart;
$diff = microtime(true) - $methodStartTime;
$sec = intval($diff);
$micro = $diff - $sec;
$this->info('END Command cleanUpInActiveUser: ' . $count . ' | Time: ' . $sec . 'sec :' . round($micro * 1000, 4) . " ms");
$this->info('END Command cleanUpInActiveUser: '.$count.' | Time: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
}
}

View file

@ -2,17 +2,13 @@
namespace App\Console\Commands;
use App\User;
use Carbon\Carbon;
use App\Services\UserUtil;
use App\User;
use Illuminate\Console\Command;
class UserRestore extends Command
{
/**
* ln -sfv /usr/bin/php73 /usr/bin/php
* php artisan user:restore {user_id}
* The name and signature of the console command.
*
* @var string
@ -24,9 +20,9 @@ class UserRestore extends Command
*
* @var string
*/
protected $description = 'User Restore active User where inactive for Business Structur and UserDetails';
protected $description = 'User Restore: Reactivates an inactive user and restores their downline structure';
private $timeStart;
private $user_id;
/**
* Create a new command instance.
@ -45,68 +41,95 @@ class UserRestore extends Command
*/
public function handle()
{
$this->info('RUN Command user:restore');
\Log::channel('cleanup')->info('COMMAND [user:restore] started.');
$this->timeStart = microtime(true);
$this->restoreInavtiveUsers();
return 0;
//\Log::info('Cron is running');
//return 0;
$result = $this->restoreInactiveUsers();
\Log::channel('cleanup')->info('COMMAND [user:restore] finished.');
return $result;
}
//gibt es gelöschte Berater mit Kunden und childs???
private function restoreInavtiveUsers(){
/**
* Stellt einen deaktivierten User wieder her
* - Reaktiviert den User (setzt active=true, stellt m_sponsor wieder her)
* - Stellt die Vertriebspartner-Kinder (Downline) wieder her
* - Nutzt UserCleanUpLog um die ursprüngliche Struktur wiederherzustellen
*
* @return int
*/
private function restoreInactiveUsers()
{
$methodStartTime = microtime(true);
$this->info('START Command restoreInactiveUsers');
$this->info('START Command restoreInavtiveUsers');
$count = 0;
$user_id = $this->argument('user_id');
$this->user_id = $this->argument('user_id');
if (! $user_id) {
$this->error('ERROR: No user_id provided as argument');
\Log::channel('cleanup')->error('restoreInactiveUsers: No user_id provided');
if(!$this->user_id){
$this->info('NO user_id as argument');
return;
return 1;
}
$this->info('RUN Command restoreInavtiveUsers on user_id: '.$this->user_id);
$this->info('Restoring user with ID: '.$user_id);
$user = User::find($this->user_id);
$user = User::find($user_id);
if (! $user) {
$this->error('ERROR: User not found with ID: '.$user_id);
\Log::channel('cleanup')->error('restoreInactiveUsers: User not found, user_id: '.$user_id);
return 1;
}
// Prüfe ob User bereits aktiv ist
if ($user->active) {
$this->warn('WARNING: User is already active, user_id: '.$user_id);
\Log::channel('cleanup')->warning('restoreInactiveUsers: User is already active, user_id: '.$user_id);
if(!$user){
$this->info('restoreInavtiveUsers find no user by user_id:'.$this->user_id);
\Log::channel('cleanup')->error('restoreInavtiveUsers find no user by user_id:'.$this->user_id);
return 0;
}
$data = [
'user_id' => $user->id,
'email' => $user->email,
'm_account' => $user->account ? $user->account->m_account : '',
'm_first_name' => $user->account ? $user->account->m_first_name : '',
'm_last_name' => $user->account ? $user->account->m_last_name : '',
];
\Log::channel('cleanup')->info('reactiveUser: '.json_encode($data));
\DB::beginTransaction();
UserUtil::reactiveUser($user);
//childs wieder herstellen
UserUtil::resetChildsToSponsor($user->id);
try {
$data = [
'user_id' => $user->id,
'email' => $user->email,
'm_account' => $user->account ? $user->account->m_account : '',
'm_first_name' => $user->account ? $user->account->m_first_name : '',
'm_last_name' => $user->account ? $user->account->m_last_name : '',
];
// Reaktiviere User (setzt active=true, stellt m_sponsor aus pre_sponsor wieder her)
UserUtil::reactiveUser($user);
$diff = microtime(true) - $this->timeStart;
$sec = intval($diff);
$micro = $diff - $sec;
// Stelle alle Vertriebspartner-Kinder wieder her
UserUtil::resetChildsToSponsor($user->id);
$this->info('END Command deleteInavtiveUsers: '.$count. ' | Time: '.$sec. 'sec :' . round($micro * 1000, 4) . " ms");
\DB::commit();
$diff = microtime(true) - $methodStartTime;
$sec = intval($diff);
$micro = $diff - $sec;
$this->info('SUCCESS: User restored successfully');
$this->info('END Command restoreInactiveUsers | Time: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
\Log::channel('cleanup')->info('restoreInactiveUsers SUCCESS: '.json_encode($data));
return 0;
} catch (\Exception $e) {
\DB::rollBack();
$this->error('ERROR: Failed to restore user: '.$e->getMessage());
\Log::channel('cleanup')->error('restoreInactiveUsers FAILED for user_id: '.$user_id.' | Error: '.$e->getMessage());
return 1;
}
}
}
//497
//489 -> de
//478 new