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>
This commit is contained in:
Kevin 2026-09-23 15:39:17 +00:00
parent bdef77462d
commit 316a9b76d6
33 changed files with 880 additions and 841 deletions

View file

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use App\Models\UserBusinessStructure;
use App\Models\UserBusiness;
use App\Models\UserBusinessStructure;
use Illuminate\Console\Command;
class BusinessClearData extends Command
@ -37,12 +37,14 @@ class BusinessClearData extends Command
// Validierung
if ($month < 1 || $month > 12) {
$this->error('Invalid month. Must be between 1 and 12.');
return 1;
}
$currentYear = (int) date('Y');
if ($year < 2020 || $year > $currentYear + 1) {
$this->error('Invalid year. Must be between 2020 and ' . ($currentYear + 1));
$this->error('Invalid year. Must be between 2020 and '.($currentYear + 1));
return 1;
}
@ -53,8 +55,9 @@ class BusinessClearData extends Command
->where('month', $month)
->first();
if (!$existingStructure) {
if (! $existingStructure) {
$this->info('No stored business structure found for the specified month/year');
return 0;
}
@ -65,12 +68,13 @@ class BusinessClearData extends Command
$this->info("Found structure ID: {$structureId}");
$this->info("- UserBusiness records: {$userBusinessCount}");
$this->info("- Users in structure: {$userCount}");
$this->info("- Completed: " . ($existingStructure->completed ? 'Yes' : 'No'));
$this->info('- Completed: '.($existingStructure->completed ? 'Yes' : 'No'));
// Bestätigung (außer bei --force)
if (!$this->option('force')) {
if (!$this->confirm('Are you sure you want to delete this business structure data?')) {
if (! $this->option('force')) {
if (! $this->confirm('Are you sure you want to delete this business structure data?')) {
$this->info('Operation cancelled by user');
return 0;
}
}
@ -100,8 +104,9 @@ class BusinessClearData extends Command
return 0;
} catch (\Exception $e) {
$this->error('Error clearing business data: ' . $e->getMessage());
$this->error('Stack trace: ' . $e->getTraceAsString());
$this->error('Error clearing business data: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
return 1;
}
}
@ -125,12 +130,12 @@ class BusinessClearData 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

@ -44,7 +44,7 @@ class BusinessLevelReports extends Command
'month' => $this->option('month'),
'year' => $this->option('year'),
'user_id' => $this->option('user-id'),
'only_not_updated' => $this->option('not-updated')
'only_not_updated' => $this->option('not-updated'),
];
$exportCsv = $this->option('csv');
@ -54,22 +54,25 @@ class BusinessLevelReports extends Command
if ($levelPromotions->isEmpty()) {
$this->info('Keine Level-Aufstiege gefunden.');
return 0;
}
if ($exportCsv) {
$filepath = $this->levelReportService->exportToCsv($levelPromotions);
$this->info('');
$this->info('CSV-Export erstellt: ' . $filepath);
$this->info('Anzahl Datensätze: ' . $levelPromotions->count());
$this->info('CSV-Export erstellt: '.$filepath);
$this->info('Anzahl Datensätze: '.$levelPromotions->count());
} else {
$this->displayReport($levelPromotions);
}
$this->info('Report erfolgreich generiert.');
return 0;
} catch (\Exception $e) {
$this->error('Fehler beim Generieren des Reports: ' . $e->getMessage());
$this->error('Fehler beim Generieren des Reports: '.$e->getMessage());
return 1;
}
}
@ -77,13 +80,14 @@ class BusinessLevelReports extends Command
private function displayReport($promotions)
{
$statistics = $this->levelReportService->getStatistics($promotions);
$this->info('');
$this->info('=== LEVEL-AUFSTIEG REPORT ===');
$this->info('');
if ($promotions->isEmpty()) {
$this->info('Keine Level-Aufstiege gefunden.');
return;
}
@ -102,7 +106,7 @@ class BusinessLevelReports extends Command
'User PP',
'User KP',
'Level Update',
'Aktiv'
'Aktiv',
];
$rows = [];
@ -110,15 +114,15 @@ class BusinessLevelReports extends Command
$rows[] = [
$promotion['date'],
$promotion['user_id'],
$promotion['first_name'] . ' ' . $promotion['last_name'],
$promotion['first_name'].' '.$promotion['last_name'],
$promotion['email'],
$promotion['from_level_name'] . ' (ID:' . $promotion['from_level_id'] . ')',
$promotion['to_level_name'] . ' (ID:' . $promotion['to_level_id'] . ')',
$promotion['current_user_level_name'] . ' (ID:' . ($promotion['current_user_level_id'] ?? 'N/A') . ')',
$promotion['to_level_margin'] . '%',
$promotion['from_level_name'].' (ID:'.$promotion['from_level_id'].')',
$promotion['to_level_name'].' (ID:'.$promotion['to_level_id'].')',
$promotion['current_user_level_name'].' (ID:'.($promotion['current_user_level_id'] ?? 'N/A').')',
$promotion['to_level_margin'].'%',
number_format($promotion['to_level_qual_kp'], 0, ',', '.'),
number_format($promotion['to_level_qual_pp'], 0, ',', '.'),
$promotion['to_level_growth_bonus'] . '%',
$promotion['to_level_growth_bonus'].'%',
number_format($promotion['total_pp'], 0, ',', '.'),
number_format($promotion['sales_volume_points_sum'], 0, ',', '.'),
$promotion['level_updated'],
@ -131,7 +135,7 @@ class BusinessLevelReports extends Command
// Zusammenfassung
$this->info('');
$this->info('=== ZUSAMMENFASSUNG ===');
$this->info('Anzahl Level-Aufstiege: ' . $statistics['total_count']);
$this->info('Anzahl Level-Aufstiege: '.$statistics['total_count']);
$this->info('');
$this->info('Aufstiege nach Ziel-Level:');
@ -145,5 +149,4 @@ class BusinessLevelReports extends Command
$this->info(" - {$period}: {$count}");
}
}
}

View file

@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Cron\UserPaymentCredits;
use App\Models\UserBusiness;
use App\Models\UserSalesVolume;
use App\Services\BusinessPlan\BusinessUserItemOptimized;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
use App\User;
@ -45,37 +46,38 @@ class BusinessTestAccount extends Command
// Lade User mit Account
$user = User::with('account', 'user_level')->find($userId);
if (!$user) {
if (! $user) {
$this->error("User {$userId} not found");
return 1;
}
$this->info("User found: {$user->email}");
$this->info("Account ID: " . ($user->account_id ?? 'NULL'));
$this->info('Account ID: '.($user->account_id ?? 'NULL'));
if ($user->account) {
$this->info("Account loaded: YES");
$this->info("Account m_account: " . ($user->account->m_account ?? 'NULL'));
$this->info("Account first_name: " . ($user->account->first_name ?? 'NULL'));
$this->info("Account last_name: " . ($user->account->last_name ?? 'NULL'));
$this->info("Account birthday: " . ($user->account->birthday ?? 'NULL'));
$this->info("Account phone: " . ($user->account->getPhoneNumber() ?? 'NULL'));
$this->info('Account loaded: YES');
$this->info('Account m_account: '.($user->account->m_account ?? 'NULL'));
$this->info('Account first_name: '.($user->account->first_name ?? 'NULL'));
$this->info('Account last_name: '.($user->account->last_name ?? 'NULL'));
$this->info('Account birthday: '.($user->account->birthday ?? 'NULL'));
$this->info('Account phone: '.($user->account->getPhoneNumber() ?? 'NULL'));
} else {
$this->warn("Account loaded: NO");
$this->warn('Account loaded: NO');
}
$this->line('');
$this->info('Testing BusinessUserItemOptimized...');
// Erstelle Date Object
$date = new stdClass();
$date = new stdClass;
$date->month = $month;
$date->year = $year;
$date->start_date = "{$year}-{$month}-01 00:00:00";
$date->end_date = date('Y-m-t 23:59:59', strtotime("{$year}-{$month}-01"));
// Teste BusinessUserItemOptimized
$TreeCalcBot = new TreeCalcBotOptimized($date->month, $date->year, 'admin');
$TreeCalcBot = new TreeCalcBotOptimized($date->month, $date->year, 'admin');
$TreeCalcBot->initBusinesslUserDetail($user, true);
$businessUserItem = $TreeCalcBot->getItem();
@ -84,30 +86,30 @@ class BusinessTestAccount extends Command
$this->line('');
$this->info('Results from BusinessUserItemOptimized:');
$this->info("m_account: " . ($bUser->m_account ?? 'NULL'));
$this->info("first_name: " . ($bUser->first_name ?? 'NULL'));
$this->info("last_name: " . ($bUser->last_name ?? 'NULL'));
$this->info("user_birthday: " . ($bUser->user_birthday ?? 'NULL'));
$this->info("user_phone: " . ($bUser->user_phone ?? 'NULL'));
$this->info("email: " . ($bUser->email ?? 'NULL'));
$this->info('m_account: '.($bUser->m_account ?? 'NULL'));
$this->info('first_name: '.($bUser->first_name ?? 'NULL'));
$this->info('last_name: '.($bUser->last_name ?? 'NULL'));
$this->info('user_birthday: '.($bUser->user_birthday ?? 'NULL'));
$this->info('user_phone: '.($bUser->user_phone ?? 'NULL'));
$this->info('email: '.($bUser->email ?? 'NULL'));
$this->line('');
$this->info('Sales Volume Fields:');
$this->info("sales_volume_KP_points: " . ($bUser->sales_volume_KP_points ?? 'NULL'));
$this->info("sales_volume_TP_points: " . ($bUser->sales_volume_TP_points ?? 'NULL'));
$this->info("sales_volume_points_shop: " . ($bUser->sales_volume_points_shop ?? 'NULL'));
$this->info("sales_volume_points_KP_sum: " . ($bUser->sales_volume_points_KP_sum ?? 'NULL'));
$this->info("sales_volume_points_TP_sum: " . ($bUser->sales_volume_points_TP_sum ?? 'NULL'));
$this->info("sales_volume_total: " . ($bUser->sales_volume_total ?? 'NULL'));
$this->info("sales_volume_total_shop: " . ($bUser->sales_volume_total_shop ?? 'NULL'));
$this->info("sales_volume_total_sum: " . ($bUser->sales_volume_total_sum ?? 'NULL'));
$this->info('sales_volume_KP_points: '.($bUser->sales_volume_KP_points ?? 'NULL'));
$this->info('sales_volume_TP_points: '.($bUser->sales_volume_TP_points ?? 'NULL'));
$this->info('sales_volume_points_shop: '.($bUser->sales_volume_points_shop ?? 'NULL'));
$this->info('sales_volume_points_KP_sum: '.($bUser->sales_volume_points_KP_sum ?? 'NULL'));
$this->info('sales_volume_points_TP_sum: '.($bUser->sales_volume_points_TP_sum ?? 'NULL'));
$this->info('sales_volume_total: '.($bUser->sales_volume_total ?? 'NULL'));
$this->info('sales_volume_total_shop: '.($bUser->sales_volume_total_shop ?? 'NULL'));
$this->info('sales_volume_total_sum: '.($bUser->sales_volume_total_sum ?? 'NULL'));
$this->line('');
$this->info('Commission Fields:');
$this->info("payline_points: " . ($bUser->payline_points ?? 'NULL'));
$this->info("commission_pp_total: " . ($bUser->commission_pp_total ?? 'NULL'));
$this->info("commission_shop_sales: " . ($bUser->commission_shop_sales ?? 'NULL'));
$this->info("commission_growth_total: " . ($bUser->commission_growth_total ?? 'NULL'));
$this->info('payline_points: '.($bUser->payline_points ?? 'NULL'));
$this->info('commission_pp_total: '.($bUser->commission_pp_total ?? 'NULL'));
$this->info('commission_shop_sales: '.($bUser->commission_shop_sales ?? 'NULL'));
$this->info('commission_growth_total: '.($bUser->commission_growth_total ?? 'NULL'));
// Test UserSalesVolume directly
$this->line('');
@ -115,20 +117,20 @@ class BusinessTestAccount extends Command
$userSalesVolume = $user->getUserSalesVolume($month, $year, 'first');
if ($userSalesVolume) {
$this->info("UserSalesVolume found: ID {$userSalesVolume->id}");
$this->info("month_KP_points: " . ($userSalesVolume->month_KP_points ?? 'NULL'));
$this->info("month_TP_points: " . ($userSalesVolume->month_TP_points ?? 'NULL'));
$this->info("month_shop_points: " . ($userSalesVolume->month_shop_points ?? 'NULL'));
$this->info("month_total_net: " . ($userSalesVolume->month_total_net ?? 'NULL'));
$this->info("month_shop_total_net: " . ($userSalesVolume->month_shop_total_net ?? 'NULL'));
$this->info('month_KP_points: '.($userSalesVolume->month_KP_points ?? 'NULL'));
$this->info('month_TP_points: '.($userSalesVolume->month_TP_points ?? 'NULL'));
$this->info('month_shop_points: '.($userSalesVolume->month_shop_points ?? 'NULL'));
$this->info('month_total_net: '.($userSalesVolume->month_total_net ?? 'NULL'));
$this->info('month_shop_total_net: '.($userSalesVolume->month_shop_total_net ?? 'NULL'));
} else {
$this->warn("No UserSalesVolume found for month {$month}/{$year}");
// Check if any UserSalesVolume exists for this user
$anyVolume = \App\Models\UserSalesVolume::where('user_id', $userId)->orderBy('year', 'desc')->orderBy('month', 'desc')->first();
$anyVolume = UserSalesVolume::where('user_id', $userId)->orderBy('year', 'desc')->orderBy('month', 'desc')->first();
if ($anyVolume) {
$this->info("Latest UserSalesVolume found: {$anyVolume->month}/{$anyVolume->year}");
} else {
$this->warn("No UserSalesVolume records found for this user at all");
$this->warn('No UserSalesVolume records found for this user at all');
}
}
@ -142,12 +144,12 @@ class BusinessTestAccount extends Command
if ($existingUserBusiness) {
$this->info('Existing UserBusiness found:');
$this->info("m_account: " . ($existingUserBusiness->m_account ?? 'NULL'));
$this->info("first_name: " . ($existingUserBusiness->first_name ?? 'NULL'));
$this->info("last_name: " . ($existingUserBusiness->last_name ?? 'NULL'));
$this->info("user_birthday: " . ($existingUserBusiness->user_birthday ?? 'NULL'));
$this->info("user_phone: " . ($existingUserBusiness->user_phone ?? 'NULL'));
$this->info("email: " . ($existingUserBusiness->email ?? 'NULL'));
$this->info('m_account: '.($existingUserBusiness->m_account ?? 'NULL'));
$this->info('first_name: '.($existingUserBusiness->first_name ?? 'NULL'));
$this->info('last_name: '.($existingUserBusiness->last_name ?? 'NULL'));
$this->info('user_birthday: '.($existingUserBusiness->user_birthday ?? 'NULL'));
$this->info('user_phone: '.($existingUserBusiness->user_phone ?? 'NULL'));
$this->info('email: '.($existingUserBusiness->email ?? 'NULL'));
} else {
$this->info('No existing UserBusiness found for this period');
}
@ -161,11 +163,11 @@ class BusinessTestAccount extends Command
$userPaymentCredits = new UserPaymentCredits($month, $year);
$ret = $userPaymentCredits->addUserCreditItem($existingUserBusiness);
$this->info('UserBusinessCredit calculated:');
$this->info('User ID: ' . $ret->user_id);
$this->info('Team Commission: ' . $ret->commission_pp_total);
$this->info('Shop Commission: ' . $ret->commission_shop_sales);
$this->info('User ID: '.$ret->user_id);
$this->info('Team Commission: '.$ret->commission_pp_total);
$this->info('Shop Commission: '.$ret->commission_shop_sales);
} catch (\Exception $e) {
$this->error('Error calculating commissions: ' . $e->getMessage());
$this->error('Error calculating commissions: '.$e->getMessage());
}
} else {
$this->warn('No UserBusiness record found, cannot calculate commissions.');
@ -177,8 +179,9 @@ class BusinessTestAccount extends Command
return 0;
} catch (\Exception $e) {
$this->error('Test failed with error: ' . $e->getMessage());
$this->error('Stack trace: ' . $e->getTraceAsString());
$this->error('Test failed with error: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
return 1;
}
}

View file

@ -2,17 +2,14 @@
namespace App\Console\Commands;
use Carbon\Carbon;
use App\Models\UserBusiness;
use App\Models\UserLevel;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class BusinessUpdateCalculatedFields extends Command
{
/**
* php artisan business:update-calculated-fields {year} {month?}
*
*
* Aktualisiert bereits gespeicherte UserBusiness-Einträge mit den neuen berechneten Feldern:
* - calc_qual_kp
* - _calculated_qual_kp in Level-Arrays
@ -32,9 +29,13 @@ class BusinessUpdateCalculatedFields extends Command
protected $description = 'Aktualisiert gespeicherte UserBusiness-Einträge mit neuen berechneten Feldern für Level-Qualifikationen';
private $timeStart;
private $month;
private $year;
private $isDryRun = false;
private $processAllMonths = false;
/**
@ -69,9 +70,10 @@ class BusinessUpdateCalculatedFields extends Command
return $this->processSingleMonth();
}
} 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;
}
}
@ -91,15 +93,16 @@ class BusinessUpdateCalculatedFields extends Command
$this->month = $month;
$this->newLine();
$this->info("┌─────────────────────────────────────────────────────────────────────┐");
$this->info("│ Verarbeite Monat: " . str_pad($month, 2, '0', STR_PAD_LEFT) . "/" . $this->year . str_repeat(' ', 51) . "│");
$this->info("└─────────────────────────────────────────────────────────────────────┘");
$this->info('┌─────────────────────────────────────────────────────────────────────┐');
$this->info('│ Verarbeite Monat: '.str_pad($month, 2, '0', STR_PAD_LEFT).'/'.$this->year.str_repeat(' ', 51).'│');
$this->info('└─────────────────────────────────────────────────────────────────────┘');
try {
$userBusinesses = $this->getUserBusinesses();
if ($userBusinesses->isEmpty()) {
$this->warn(" Keine UserBusiness-Einträge für Monat {$month}/{$this->year} gefunden - überspringe");
continue;
}
@ -117,8 +120,9 @@ class BusinessUpdateCalculatedFields extends Command
$this->logMemoryUsage("Nach Monat {$month}");
} catch (\Exception $e) {
$monthsFailed++;
$this->error(" ✗ Fehler in Monat {$month}: " . $e->getMessage());
\Log::error("BusinessUpdateCalculatedFields: Error in month {$month}/{$this->year}: " . $e->getMessage());
$this->error(" ✗ Fehler in Monat {$month}: ".$e->getMessage());
\Log::error("BusinessUpdateCalculatedFields: Error in month {$month}/{$this->year}: ".$e->getMessage());
// Weiter mit nächstem Monat
continue;
}
@ -152,6 +156,7 @@ class BusinessUpdateCalculatedFields extends Command
if ($userBusinesses->isEmpty()) {
$this->error("Keine UserBusiness-Einträge für Monat {$this->month}/{$this->year} gefunden");
return 1;
}
@ -184,7 +189,7 @@ class BusinessUpdateCalculatedFields extends Command
{
$stats = $this->updateCalculatedFieldsWithStats($userBusinesses);
$this->info("Update abgeschlossen:");
$this->info('Update abgeschlossen:');
$this->info(" - Aktualisiert: {$stats['updated']}");
$this->info(" - Übersprungen: {$stats['skipped']}");
$this->info(" - Fehler: {$stats['errors']}");
@ -215,14 +220,15 @@ class BusinessUpdateCalculatedFields extends Command
$bar->advance();
// Memory-Check alle 100 Einträge (nur wenn nicht ganzes Jahr)
if (!$this->processAllMonths && ($updatedCount + $skippedCount) % 100 === 0) {
$this->logMemoryUsage("Nach " . ($updatedCount + $skippedCount) . " Einträgen");
if (! $this->processAllMonths && ($updatedCount + $skippedCount) % 100 === 0) {
$this->logMemoryUsage('Nach '.($updatedCount + $skippedCount).' Einträgen');
}
} catch (\Exception $e) {
$errorCount++;
$this->newLine();
$this->warn("Fehler bei UserBusiness ID {$userBusiness->id}: " . $e->getMessage());
\Log::error("BusinessUpdateCalculatedFields: Error for UserBusiness {$userBusiness->id}: " . $e->getMessage());
$this->warn("Fehler bei UserBusiness ID {$userBusiness->id}: ".$e->getMessage());
\Log::error("BusinessUpdateCalculatedFields: Error for UserBusiness {$userBusiness->id}: ".$e->getMessage());
continue;
}
}
@ -245,7 +251,7 @@ class BusinessUpdateCalculatedFields extends Command
$hasChanges = false;
// 1. Aktualisiere calc_qual_kp für qual_user_level
if (!$userBusiness->calc_qual_kp) {
if (! $userBusiness->calc_qual_kp) {
$qualKp = $userBusiness->qual_user_level['qual_kp'] ?? null;
if ($qualKp !== null) {
@ -263,7 +269,7 @@ class BusinessUpdateCalculatedFields extends Command
}
// 2. Aktualisiere qual_user_level_next
if (!empty($userBusiness->qual_user_level_next) && is_array($userBusiness->qual_user_level_next)) {
if (! empty($userBusiness->qual_user_level_next) && is_array($userBusiness->qual_user_level_next)) {
$levelData = $userBusiness->qual_user_level_next;
$updated = $this->addCalculatedFieldsToLevel($levelData, $userBusiness);
@ -274,7 +280,7 @@ class BusinessUpdateCalculatedFields extends Command
}
// 3. Aktualisiere next_qual_user_level
if (!empty($userBusiness->next_qual_user_level) && is_array($userBusiness->next_qual_user_level)) {
if (! empty($userBusiness->next_qual_user_level) && is_array($userBusiness->next_qual_user_level)) {
$levelData = $userBusiness->next_qual_user_level;
$updated = $this->addCalculatedFieldsToLevel($levelData, $userBusiness);
@ -285,7 +291,7 @@ class BusinessUpdateCalculatedFields extends Command
}
// 4. Aktualisiere next_can_user_level
if (!empty($userBusiness->next_can_user_level) && is_array($userBusiness->next_can_user_level)) {
if (! empty($userBusiness->next_can_user_level) && is_array($userBusiness->next_can_user_level)) {
$levelData = $userBusiness->next_can_user_level;
$updated = $this->addCalculatedFieldsToLevel($levelData, $userBusiness);
@ -296,7 +302,7 @@ class BusinessUpdateCalculatedFields extends Command
}
// Speichere nur wenn Änderungen vorhanden sind und nicht im Dry-Run Mode
if ($hasChanges && !$this->isDryRun) {
if ($hasChanges && ! $this->isDryRun) {
$userBusiness->save();
}
@ -305,7 +311,7 @@ class BusinessUpdateCalculatedFields extends Command
/**
* Füge berechnete Felder zu einem Level-Array hinzu
*
*
* @return array|false Array mit neuen Feldern oder false wenn keine Änderungen
*/
private function addCalculatedFieldsToLevel(array $levelData, UserBusiness $userBusiness)
@ -369,7 +375,7 @@ class BusinessUpdateCalculatedFields extends Command
$sec = intval($diff);
$micro = $diff - $sec;
$this->info($message . ' | Zeit: ' . $sec . 'sec :' . round($micro * 1000, 4) . " ms");
$this->info($message.' | Zeit: '.$sec.'sec :'.round($micro * 1000, 4).' ms');
}
/**
@ -419,12 +425,12 @@ class BusinessUpdateCalculatedFields 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

@ -30,7 +30,7 @@ class DhlBackfillEmails extends Command
$dryRun = $this->option('dry-run');
$this->info('DHL E-Mail Backfill gestartet');
$this->info('Modus: ' . ($dryRun ? 'DRY-RUN (keine Änderungen)' : 'LIVE'));
$this->info('Modus: '.($dryRun ? 'DRY-RUN (keine Änderungen)' : 'LIVE'));
$this->newLine();
// Hole alle Sendungen ohne E-Mail
@ -59,6 +59,7 @@ class DhlBackfillEmails extends Command
if (empty($email)) {
$skipped++;
continue;
}

View file

@ -2,10 +2,10 @@
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
class LogCleanup extends Command
{
@ -33,8 +33,9 @@ class LogCleanup extends Command
$days = $this->option('days');
$logPath = storage_path('logs');
if (!File::isDirectory($logPath)) {
if (! File::isDirectory($logPath)) {
$this->error("Log directory not found: {$logPath}");
return 1;
}
@ -64,24 +65,24 @@ class LogCleanup extends Command
$deletedFiles++;
$deletedSize += $fileSize;
$this->line("Deleted: {$filename} (" . $this->formatBytes($fileSize) . ", modified: {$lastModified->toDateString()})");
$this->line("Deleted: {$filename} (".$this->formatBytes($fileSize).", modified: {$lastModified->toDateString()})");
} catch (\Exception $e) {
$this->error("Failed to delete {$filename}: " . $e->getMessage());
$this->error("Failed to delete {$filename}: ".$e->getMessage());
}
}
}
if ($deletedFiles > 0) {
$this->info("\nCleanup complete!");
$this->info("Deleted {$deletedFiles} file(s), freed " . $this->formatBytes($deletedSize));
$this->info("Deleted {$deletedFiles} file(s), freed ".$this->formatBytes($deletedSize));
Log::channel('cleanup')->info("Log cleanup completed", [
Log::channel('cleanup')->info('Log cleanup completed', [
'deleted_files' => $deletedFiles,
'freed_space' => $this->formatBytes($deletedSize),
'days' => $days
'days' => $days,
]);
} else {
$this->info("No old log files found to delete.");
$this->info('No old log files found to delete.');
}
return 0;
@ -90,7 +91,7 @@ class LogCleanup extends Command
/**
* Format bytes to human readable format
*
* @param int $bytes
* @param int $bytes
* @return string
*/
private function formatBytes($bytes)
@ -101,6 +102,6 @@ class LogCleanup extends Command
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, 2) . ' ' . $units[$pow];
return round($bytes, 2).' '.$units[$pow];
}
}

View file

@ -3,6 +3,7 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class PayoneFailedPaypalReport extends Command
@ -45,14 +46,14 @@ class PayoneFailedPaypalReport extends Command
$this->newLine();
$this->info("CSV-Bericht: {$fullPath}");
$this->info('TXT-Bericht: ' . str_replace('.csv', '.txt', $fullPath));
$this->info('TXT-Bericht: '.str_replace('.csv', '.txt', $fullPath));
$this->info("E-Mail Berater: {$dir}/emails-berater.csv");
$this->info("E-Mail Shop-Kunden: {$dir}/emails-shop-kunden.csv");
return self::SUCCESS;
}
private function getAffectedOrders(string $from, string $to): \Illuminate\Support\Collection
private function getAffectedOrders(string $from, string $to): Collection
{
return DB::table('shopping_orders')
->join('shopping_payments', function ($join) {
@ -91,7 +92,7 @@ class PayoneFailedPaypalReport extends Command
->get();
}
private function displaySummary(\Illuminate\Support\Collection $rows, string $from, string $to): void
private function displaySummary(Collection $rows, string $from, string $to): void
{
$uniqueOrders = $rows->unique('order_id');
$paidOrders = $uniqueOrders->where('paid', 1);
@ -105,17 +106,17 @@ class PayoneFailedPaypalReport extends Command
['Betroffene Bestellungen (eindeutig)', $uniqueOrders->count()],
['Davon nachträglich bezahlt (andere Zahlungsart)', $paidOrders->count()],
['Nicht bezahlt (offen/verloren)', $unpaidOrders->count()],
['Summe nicht bezahlter Bestellungen', number_format($unpaidOrders->sum('total_shipping'), 2, ',', '.') . ' EUR'],
['Summe aller betroffenen Bestellungen', number_format($uniqueOrders->sum('total_shipping'), 2, ',', '.') . ' EUR'],
['Summe nicht bezahlter Bestellungen', number_format($unpaidOrders->sum('total_shipping'), 2, ',', '.').' EUR'],
['Summe aller betroffenen Bestellungen', number_format($uniqueOrders->sum('total_shipping'), 2, ',', '.').' EUR'],
]
);
}
private function writeCsvReport(string $path, \Illuminate\Support\Collection $rows, string $from, string $to): void
private function writeCsvReport(string $path, Collection $rows, string $from, string $to): void
{
$fp = fopen($path, 'w');
fprintf($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
fputcsv($fp, [
'Fehler-Datum',
@ -156,13 +157,13 @@ class PayoneFailedPaypalReport extends Command
fputcsv($fp, ['Fehlgeschlagene Transaktionen', $rows->count()], ';');
fputcsv($fp, ['Betroffene Bestellungen', $uniqueOrders->count()], ';');
fputcsv($fp, ['Nicht bezahlt (offen/verloren)', $unpaidOrders->count()], ';');
fputcsv($fp, ['Summe nicht bezahlter Bestellungen', number_format($unpaidOrders->sum('total_shipping'), 2, ',', '') . ' EUR'], ';');
fputcsv($fp, ['Summe aller betroffenen Bestellungen', number_format($uniqueOrders->sum('total_shipping'), 2, ',', '') . ' EUR'], ';');
fputcsv($fp, ['Summe nicht bezahlter Bestellungen', number_format($unpaidOrders->sum('total_shipping'), 2, ',', '').' EUR'], ';');
fputcsv($fp, ['Summe aller betroffenen Bestellungen', number_format($uniqueOrders->sum('total_shipping'), 2, ',', '').' EUR'], ';');
fclose($fp);
}
private function writeTxtReport(string $path, \Illuminate\Support\Collection $rows, string $from, string $to): void
private function writeTxtReport(string $path, Collection $rows, string $from, string $to): void
{
$uniqueOrders = $rows->unique('order_id');
$paidOrders = $uniqueOrders->where('paid', 1);
@ -174,7 +175,7 @@ class PayoneFailedPaypalReport extends Command
$lines[] = '================================================================================';
$lines[] = '';
$lines[] = "Zeitraum: {$from} bis {$to}";
$lines[] = 'Erstellt am: ' . now()->format('d.m.Y H:i:s');
$lines[] = 'Erstellt am: '.now()->format('d.m.Y H:i:s');
$lines[] = 'Ursache: PayPal-Kontoverknüpfung bei PAYONE nicht migriert (Vertragsübernahme GmbH)';
$lines[] = 'Portal-ID: 2030693';
$lines[] = 'Merchant-ID: 42504';
@ -199,7 +200,7 @@ class PayoneFailedPaypalReport extends Command
$lines[] = '--------------------------------------------------------------------------------';
$lines[] = '';
$byDate = $rows->groupBy(fn($r) => substr($r->error_date, 0, 10));
$byDate = $rows->groupBy(fn ($r) => substr($r->error_date, 0, 10));
foreach ($byDate as $date => $dayRows) {
$dayOrders = $dayRows->unique('order_id');
$dayUnpaid = $dayOrders->where('paid', 0);
@ -226,7 +227,7 @@ class PayoneFailedPaypalReport extends Command
'Betrag (EUR)',
'Status'
);
$lines[] = ' ' . str_repeat('-', 80);
$lines[] = ' '.str_repeat('-', 80);
foreach ($unpaidOrders->sortBy('order_date') as $order) {
$lines[] = sprintf(
@ -239,12 +240,12 @@ class PayoneFailedPaypalReport extends Command
);
}
$lines[] = ' ' . str_repeat('-', 80);
$lines[] = ' '.str_repeat('-', 80);
$lines[] = sprintf(
' %-12s %-20s %-18s %14s',
'GESAMT',
'',
$unpaidOrders->count() . ' Bestellungen',
$unpaidOrders->count().' Bestellungen',
number_format($unpaidOrders->sum('total_shipping'), 2, ',', '.')
);
@ -265,7 +266,7 @@ class PayoneFailedPaypalReport extends Command
'Betrag (EUR)',
'Status'
);
$lines[] = ' ' . str_repeat('-', 80);
$lines[] = ' '.str_repeat('-', 80);
foreach ($paidOrders->sortBy('order_date') as $order) {
$lines[] = sprintf(
@ -278,12 +279,12 @@ class PayoneFailedPaypalReport extends Command
);
}
$lines[] = ' ' . str_repeat('-', 80);
$lines[] = ' '.str_repeat('-', 80);
$lines[] = sprintf(
' %-12s %-20s %-18s %14s',
'GESAMT',
'',
$paidOrders->count() . ' Bestellungen',
$paidOrders->count().' Bestellungen',
number_format($paidOrders->sum('total_shipping'), 2, ',', '.')
);
}
@ -299,21 +300,21 @@ class PayoneFailedPaypalReport extends Command
file_put_contents($path, implode("\n", $lines));
}
private function appendEmailSectionToTxt(array &$lines, \Illuminate\Support\Collection $unpaidOrders): void
private function appendEmailSectionToTxt(array &$lines, Collection $unpaidOrders): void
{
$berater = $unpaidOrders->filter(fn($o) => ! empty($o->auth_user_id))->sortBy('billing_email');
$shopKunden = $unpaidOrders->filter(fn($o) => empty($o->auth_user_id))->sortBy('billing_email');
$berater = $unpaidOrders->filter(fn ($o) => ! empty($o->auth_user_id))->sortBy('billing_email');
$shopKunden = $unpaidOrders->filter(fn ($o) => empty($o->auth_user_id))->sortBy('billing_email');
$lines[] = '--------------------------------------------------------------------------------';
$lines[] = ' BETROFFENE BERATER (mit Auth-User-ID) - nicht bezahlt';
$lines[] = '--------------------------------------------------------------------------------';
$lines[] = '';
$lines[] = sprintf(' %-12s %-8s %-30s %-30s %14s', 'Bestell-Nr', 'User-ID', 'Name', 'E-Mail', 'Betrag (EUR)');
$lines[] = ' ' . str_repeat('-', 100);
$lines[] = ' '.str_repeat('-', 100);
$beraterSum = 0;
foreach ($berater as $order) {
$name = trim(($order->billing_firstname ?? '') . ' ' . ($order->billing_lastname ?? ''));
$name = trim(($order->billing_firstname ?? '').' '.($order->billing_lastname ?? ''));
$lines[] = sprintf(
' %-12s %-8s %-30s %-30s %14s',
$order->order_id,
@ -325,8 +326,8 @@ class PayoneFailedPaypalReport extends Command
$beraterSum += $order->total_shipping;
}
$lines[] = ' ' . str_repeat('-', 100);
$lines[] = sprintf(' %-12s %-8s %-30s %-30s %14s', 'GESAMT', '', $berater->count() . ' Bestellungen', '', number_format($beraterSum, 2, ',', '.'));
$lines[] = ' '.str_repeat('-', 100);
$lines[] = sprintf(' %-12s %-8s %-30s %-30s %14s', 'GESAMT', '', $berater->count().' Bestellungen', '', number_format($beraterSum, 2, ',', '.'));
$lines[] = '';
$lines[] = '--------------------------------------------------------------------------------';
@ -334,11 +335,11 @@ class PayoneFailedPaypalReport extends Command
$lines[] = '--------------------------------------------------------------------------------';
$lines[] = '';
$lines[] = sprintf(' %-12s %-30s %-30s %14s', 'Bestell-Nr', 'Name', 'E-Mail', 'Betrag (EUR)');
$lines[] = ' ' . str_repeat('-', 90);
$lines[] = ' '.str_repeat('-', 90);
$shopSum = 0;
foreach ($shopKunden as $order) {
$name = trim(($order->billing_firstname ?? '') . ' ' . ($order->billing_lastname ?? ''));
$name = trim(($order->billing_firstname ?? '').' '.($order->billing_lastname ?? ''));
$lines[] = sprintf(
' %-12s %-30s %-30s %14s',
$order->order_id,
@ -349,16 +350,16 @@ class PayoneFailedPaypalReport extends Command
$shopSum += $order->total_shipping;
}
$lines[] = ' ' . str_repeat('-', 90);
$lines[] = sprintf(' %-12s %-30s %-30s %14s', 'GESAMT', $shopKunden->count() . ' Bestellungen', '', number_format($shopSum, 2, ',', '.'));
$lines[] = ' '.str_repeat('-', 90);
$lines[] = sprintf(' %-12s %-30s %-30s %14s', 'GESAMT', $shopKunden->count().' Bestellungen', '', number_format($shopSum, 2, ',', '.'));
}
private function writeEmailLists(string $dir, \Illuminate\Support\Collection $rows): void
private function writeEmailLists(string $dir, Collection $rows): void
{
$unpaidOrders = $rows->unique('order_id')->where('paid', 0);
$berater = $unpaidOrders->filter(fn($o) => ! empty($o->auth_user_id))->sortBy('order_date');
$shopKunden = $unpaidOrders->filter(fn($o) => empty($o->auth_user_id))->sortBy('order_date');
$berater = $unpaidOrders->filter(fn ($o) => ! empty($o->auth_user_id))->sortBy('order_date');
$shopKunden = $unpaidOrders->filter(fn ($o) => empty($o->auth_user_id))->sortBy('order_date');
$this->writeEmailCsv("{$dir}/emails-berater.csv", $berater, true);
$this->writeEmailCsv("{$dir}/emails-shop-kunden.csv", $shopKunden, false);
@ -371,22 +372,22 @@ class PayoneFailedPaypalReport extends Command
'Berater (mit Auth-User-ID)',
$berater->count(),
$berater->pluck('billing_email')->filter()->unique()->count(),
number_format($berater->sum('total_shipping'), 2, ',', '.') . ' EUR',
number_format($berater->sum('total_shipping'), 2, ',', '.').' EUR',
],
[
'Shop-Kunden (ohne Auth-User-ID)',
$shopKunden->count(),
$shopKunden->pluck('billing_email')->filter()->unique()->count(),
number_format($shopKunden->sum('total_shipping'), 2, ',', '.') . ' EUR',
number_format($shopKunden->sum('total_shipping'), 2, ',', '.').' EUR',
],
]
);
}
private function writeEmailCsv(string $path, \Illuminate\Support\Collection $orders, bool $includeUserId): void
private function writeEmailCsv(string $path, Collection $orders, bool $includeUserId): void
{
$fp = fopen($path, 'w');
fprintf($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
$headers = ['Bestell-Nr', 'Bestell-Datum', 'Vorname', 'Nachname', 'E-Mail', 'Betrag (EUR)', 'Status'];
if ($includeUserId) {
@ -411,7 +412,7 @@ class PayoneFailedPaypalReport extends Command
}
fputcsv($fp, [], ';');
fputcsv($fp, ['GESAMT', '', '', '', $orders->count() . ' Bestellungen', number_format($orders->sum('total_shipping'), 2, ',', '') . ' EUR'], ';');
fputcsv($fp, ['GESAMT', '', '', '', $orders->count().' Bestellungen', number_format($orders->sum('total_shipping'), 2, ',', '').' EUR'], ';');
fputcsv($fp, ['Eindeutige E-Mail-Adressen', $orders->pluck('billing_email')->filter()->unique()->count()], ';');
fclose($fp);

View file

@ -7,6 +7,7 @@ use App\Models\ShoppingPayment;
use App\Services\AboHelper;
use App\Services\Incentive\IncentiveTracker;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class RepairMissingAboFromOrders extends Command
@ -96,9 +97,9 @@ class RepairMissingAboFromOrders extends Command
}
/**
* @return \Illuminate\Database\Eloquent\Builder<ShoppingOrder>
* @return Builder<ShoppingOrder>
*/
private function queryMissingOrders(): \Illuminate\Database\Eloquent\Builder
private function queryMissingOrders(): Builder
{
$q = ShoppingOrder::query()
->where('is_abo', true)

View file

@ -11,6 +11,7 @@ use App\Services\MyLog;
use App\Services\Payment;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
class RetryFailedPaypalAbos extends Command
@ -100,9 +101,9 @@ class RetryFailedPaypalAbos extends Command
}
/**
* @return \Illuminate\Database\Eloquent\Collection<int, UserAbo>
* @return Collection<int, UserAbo>
*/
private function getAffectedAbos(?string $singleAboId): \Illuminate\Database\Eloquent\Collection
private function getAffectedAbos(?string $singleAboId): Collection
{
$query = UserAbo::query()
->where('status', 3)
@ -119,7 +120,7 @@ class RetryFailedPaypalAbos extends Command
return $query->orderBy('id')->get();
}
private function displayAboList(\Illuminate\Database\Eloquent\Collection $abos): void
private function displayAboList(Collection $abos): void
{
$rows = $abos->map(fn (UserAbo $abo) => [
$abo->id,

View file

@ -2,17 +2,18 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use App\Services\ShoppingUserService;
use App\User;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class SyncShoppingUserData extends Command
{
//aufruf: php artisan shopping:sync-user-data --force --start=4
// aufruf: php artisan shopping:sync-user-data --force --start=4
protected $signature = 'shopping:sync-user-data {user_id?} {--force} {--start=1}';
protected $description = 'Synchronisiere Shopping User Daten für einen oder alle User';
public function handle()
@ -28,11 +29,12 @@ class SyncShoppingUserData extends Command
$this->syncAllUsers($force, $startId);
}
} catch (Exception $e) {
$this->error("Ein Fehler ist aufgetreten: " . $e->getMessage());
Log::error("Shopping User Sync Fehler: ", [
$this->error('Ein Fehler ist aufgetreten: '.$e->getMessage());
Log::error('Shopping User Sync Fehler: ', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
'trace' => $e->getTraceAsString(),
]);
return 1;
}
@ -50,27 +52,27 @@ class SyncShoppingUserData extends Command
User::where('id', '>=', $startId)
->orderBy('id')
->chunk(10, function($users) use (&$count, &$errors, $force) {
foreach($users as $user) {
->chunk(10, function ($users) use (&$count, &$errors, $force) {
foreach ($users as $user) {
try {
$this->info("\nVerarbeite User ID: {$user->id} ({$user->email})");
$this->syncUser($user);
$count++;
$this->info("✓ User ID {$user->id} erfolgreich synchronisiert");
} catch (Exception $e) {
$errorMessage = "Fehler bei User ID {$user->id} ({$user->email}): " . $e->getMessage();
$errorMessage = "Fehler bei User ID {$user->id} ({$user->email}): ".$e->getMessage();
$errors[] = $errorMessage;
$this->error($errorMessage);
// Log die letzten SQL Queries
Log::error("Letzte SQL Queries:", [
'queries' => DB::getQueryLog()
Log::error('Letzte SQL Queries:', [
'queries' => DB::getQueryLog(),
]);
if (!$force) {
if (! $force) {
throw $e;
}
}
@ -78,13 +80,13 @@ class SyncShoppingUserData extends Command
});
$this->newLine();
$this->info("Synchronisierung abgeschlossen!");
$this->info('Synchronisierung abgeschlossen!');
$this->info("Gesamt synchronisierte User: {$count}");
if (count($errors) > 0) {
$this->warn("Es gab " . count($errors) . " Fehler während der Synchronisierung:");
foreach($errors as $error) {
$this->warn("- " . $error);
$this->warn('Es gab '.count($errors).' Fehler während der Synchronisierung:');
foreach ($errors as $error) {
$this->warn('- '.$error);
}
}
}
@ -92,38 +94,37 @@ class SyncShoppingUserData extends Command
private function syncUser(User $user)
{
try {
$this->output->write(" Setze Faker Mail... ");
$this->output->write(' Setze Faker Mail... ');
ShoppingUserService::setFakerMail($user);
$this->info("✓");
$this->info('✓');
$this->output->write(" Synchronisiere Numbers... ");
$this->output->write(' Synchronisiere Numbers... ');
ShoppingUserService::syncNumbersByEmail($user);
$this->info("✓");
$this->info('✓');
$this->output->write(" Synchronisiere Orders... ");
$this->output->write(' Synchronisiere Orders... ');
ShoppingUserService::syncOrdersByEmail($user);
$this->info("✓");
$this->info('✓');
} catch (Exception $e) {
throw new Exception($e->getMessage() . "\n" . $e->getTraceAsString());
throw new Exception($e->getMessage()."\n".$e->getTraceAsString());
}
}
private function syncSingleUser($userId)
{
$user = User::find($userId);
if (!$user) {
if (! $user) {
throw new Exception("User ID {$userId} nicht gefunden");
}
$this->info("Starte Synchronisierung für User ID {$userId}...");
try {
$this->syncUser($user);
$this->info("✓ Synchronisierung erfolgreich abgeschlossen");
$this->info('✓ Synchronisierung erfolgreich abgeschlossen');
} catch (Exception $e) {
throw new Exception("Fehler bei User ID {$userId}: " . $e->getMessage());
throw new Exception("Fehler bei User ID {$userId}: ".$e->getMessage());
}
}
}
}

View file

@ -2,13 +2,13 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
use App\Models\UserBusiness;
use App\Services\BusinessPlan\BusinessUserItemOptimized;
use App\Services\BusinessPlan\GrowthBonusCalculator;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
use App\User;
use App\Models\UserBusiness;
use Carbon\Carbon;
use Illuminate\Console\Command;
class TestGrowthBonusCalculation extends Command
{
@ -29,14 +29,15 @@ class TestGrowthBonusCalculation extends Command
$debug = $this->option('debug');
$fromDb = $this->option('from-db');
$this->info("=== Growth Bonus Test ===");
$this->info('=== Growth Bonus Test ===');
$this->info("User: {$userId}, Monat: {$month}/{$year}");
$this->newLine();
// User laden
$user = User::find($userId);
if (!$user) {
if (! $user) {
$this->error("User {$userId} nicht gefunden!");
return 1;
}
@ -49,7 +50,7 @@ class TestGrowthBonusCalculation extends Command
->first();
if ($userBusiness) {
$this->info("=== GESPEICHERTE DATEN (UserBusiness) ===");
$this->info('=== GESPEICHERTE DATEN (UserBusiness) ===');
$qualLevel = $userBusiness->qual_user_level;
$this->table(
['Feld', 'Wert'],
@ -63,10 +64,11 @@ class TestGrowthBonusCalculation extends Command
);
} else {
$this->warn("Keine gespeicherten UserBusiness-Daten für {$month}/{$year}");
if (!$fromDb) {
$this->info("Versuche Live-Berechnung...");
if (! $fromDb) {
$this->info('Versuche Live-Berechnung...');
} else {
$this->error("--from-db erfordert gespeicherte Daten!");
$this->error('--from-db erfordert gespeicherte Daten!');
return 1;
}
}
@ -78,7 +80,7 @@ class TestGrowthBonusCalculation extends Command
}
$this->newLine();
$this->info("=== TEST ABGESCHLOSSEN ===");
$this->info('=== TEST ABGESCHLOSSEN ===');
return 0;
}
@ -86,7 +88,7 @@ class TestGrowthBonusCalculation extends Command
private function testFromDatabase(int $userId, int $month, int $year, bool $debug): void
{
$this->newLine();
$this->info("=== ANALYSE AUS DATENBANK ===");
$this->info('=== ANALYSE AUS DATENBANK ===');
// Lade User und seine Firstlines
$userBusiness = UserBusiness::where('user_id', $userId)
@ -100,16 +102,17 @@ class TestGrowthBonusCalculation extends Command
$this->info("Mein Growth Bonus Anspruch: {$myGrowthBonus}%");
if ($myGrowthBonus <= 0) {
$this->warn("Kein Growth Bonus Anspruch!");
$this->warn('Kein Growth Bonus Anspruch!');
return;
}
// Lade Firstlines
$firstlineIds = User::where('m_sponsor', $userId)->pluck('id')->toArray();
$this->info("Anzahl Firstlines: " . count($firstlineIds));
$this->info('Anzahl Firstlines: '.count($firstlineIds));
$this->newLine();
$this->info("=== FIRSTLINE ANALYSE ===");
$this->info('=== FIRSTLINE ANALYSE ===');
$totalExpectedGrowth = 0;
$problemsFound = false;
@ -120,7 +123,7 @@ class TestGrowthBonusCalculation extends Command
->where('year', $year)
->first();
if (!$flBusiness) {
if (! $flBusiness) {
continue;
}
@ -137,7 +140,7 @@ class TestGrowthBonusCalculation extends Command
$expectedDiff = max(0, $myGrowthBonus - $flGrowthBonus);
$expectedCommission = round($flTPSum / 100 * $expectedDiff, 2);
// Problem-Erkennung: Wenn FL einen Growth Bonus hat aber wir
// Problem-Erkennung: Wenn FL einen Growth Bonus hat aber wir
// trotzdem den vollen Betrag bekommen
$isPotentialProblem = $flGrowthBonus > 0 && $expectedDiff < $myGrowthBonus;
@ -146,11 +149,11 @@ class TestGrowthBonusCalculation extends Command
['Feld', 'Wert'],
[
['Level erreicht', $flLevelName],
['Growth Bonus (FL)', $flGrowthBonus . '%'],
['Growth Bonus (FL)', $flGrowthBonus.'%'],
['Team-Punkte (TP_sum)', number_format($flTPSum, 0, ',', '.')],
['Mein Anspruch', $myGrowthBonus . '%'],
['Differenz (erwartet)', $expectedDiff . '%'],
['Erwartete Provision', number_format($expectedCommission, 2, ',', '.') . ' €'],
['Mein Anspruch', $myGrowthBonus.'%'],
['Differenz (erwartet)', $expectedDiff.'%'],
['Erwartete Provision', number_format($expectedCommission, 2, ',', '.').' €'],
['ACHTUNG: Blockade?', $isPotentialProblem ? 'JA - FL sollte blockieren!' : 'Nein'],
]
);
@ -165,19 +168,19 @@ class TestGrowthBonusCalculation extends Command
}
$this->newLine();
$this->info("=== ZUSAMMENFASSUNG ===");
$this->info("Erwartete Growth Bonus Summe (mit korrekter Differenz): " . number_format($totalExpectedGrowth, 2, ',', '.') . ' €');
$this->info("Gespeicherte Growth Bonus Summe: " . number_format($userBusiness->commission_growth_total ?? 0, 2, ',', '.') . ' €');
$this->info('=== ZUSAMMENFASSUNG ===');
$this->info('Erwartete Growth Bonus Summe (mit korrekter Differenz): '.number_format($totalExpectedGrowth, 2, ',', '.').' €');
$this->info('Gespeicherte Growth Bonus Summe: '.number_format($userBusiness->commission_growth_total ?? 0, 2, ',', '.').' €');
if ($problemsFound) {
$this->newLine();
$this->error("⚠️ PROBLEME GEFUNDEN! Die Blockade durch qualifizierte Firstlines funktioniert möglicherweise nicht korrekt.");
$this->error('⚠️ PROBLEME GEFUNDEN! Die Blockade durch qualifizierte Firstlines funktioniert möglicherweise nicht korrekt.');
}
// Detailanalyse: Wie wurde die Berechnung durchgeführt?
if ($debug) {
$this->newLine();
$this->info("=== DEBUG: Rekursive Volumen-Analyse ===");
$this->info('=== DEBUG: Rekursive Volumen-Analyse ===');
$this->analyzeVolumeDistribution($userId, $month, $year, $myGrowthBonus, 1);
}
}
@ -193,14 +196,14 @@ class TestGrowthBonusCalculation extends Command
->where('year', $year)
->first();
if (!$userBusiness) {
if (! $userBusiness) {
return ['0.0' => 0];
}
$qualLevel = $userBusiness->qual_user_level;
$myProtection = (float) ($qualLevel['growth_bonus'] ?? 0);
$indent = str_repeat(" ", $depth);
$indent = str_repeat(' ', $depth);
// Eigenes Volumen (TP_sum - aber nur direkte Punkte, nicht Team)
// Bei gespeicherten Daten ist das schwer zu unterscheiden
@ -219,7 +222,7 @@ class TestGrowthBonusCalculation extends Command
->where('year', $year)
->first();
if (!$childBusiness) {
if (! $childBusiness) {
continue;
}
@ -251,7 +254,7 @@ class TestGrowthBonusCalculation extends Command
private function testLiveCalculation(User $user, Carbon $date, int $month, int $year, bool $debug): void
{
$this->newLine();
$this->info("=== LIVE-BERECHNUNG ===");
$this->info('=== LIVE-BERECHNUNG ===');
// TreeCalcBot erstellen
$treeCalcBot = new TreeCalcBotOptimized($month, $year, 'member', true);
@ -283,15 +286,15 @@ class TestGrowthBonusCalculation extends Command
);
$this->newLine();
$this->info("=== FIRSTLINES (Kinder) ===");
$this->info('=== FIRSTLINES (Kinder) ===');
if (empty($businessUserItem->businessUserItems)) {
$this->warn("Keine Firstlines geladen!");
$this->warn('Keine Firstlines geladen!');
} else {
foreach ($businessUserItem->businessUserItems as $index => $childItem) {
$childQual = $childItem->getQualUserLevel();
$this->info("--- Firstline " . ($index + 1) . " ---");
$this->info('--- Firstline '.($index + 1).' ---');
$this->table(
['Feld', 'Wert'],
[
@ -308,7 +311,7 @@ class TestGrowthBonusCalculation extends Command
}
if ($qualUserLevel && ($qualUserLevel['growth_bonus'] ?? 0) > 0) {
$calculator = new GrowthBonusCalculator();
$calculator = new GrowthBonusCalculator;
$qualData = (object) $qualUserLevel;
$totalGrowthBonus = $calculator->calculate($businessUserItem, $qualData);

View file

@ -2,11 +2,10 @@
namespace App\Console\Commands;
use App\User;
use App\Cron\UserLevelUpdate;
use App\Models\UserBusiness;
use App\Models\UserLevel;
use App\Cron\UserLevelUpdate;
use App\Console\Commands\BusinessStoreOptimized;
use App\User;
use Illuminate\Console\Command;
use ReflectionClass;
@ -41,17 +40,17 @@ class TestUserLevelUpdate extends Command
$sendMail = $this->option('send-mail');
$dryRun = $this->option('dry-run');
$this->info("===========================================");
$this->info("UserLevelUpdate Test");
$this->info("===========================================");
$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("");
$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
@ -61,15 +60,16 @@ class TestUserLevelUpdate extends Command
$this->runOriginalFunction($month, $year, $sendMail);
}
$this->info("");
$this->info("===========================================");
$this->info("Test abgeschlossen!");
$this->info("===========================================");
$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());
$this->error('Test fehlgeschlagen: '.$e->getMessage());
$this->error('Stack trace: '.$e->getTraceAsString());
return 1;
}
}
@ -79,10 +79,10 @@ class TestUserLevelUpdate extends Command
*/
private function runOriginalFunction(int $month, int $year, bool $sendMail)
{
$this->info("Erstelle BusinessStoreOptimized Instanz...");
$this->info('Erstelle BusinessStoreOptimized Instanz...');
// Erstelle BusinessStoreOptimized Command-Instanz
$businessStoreCommand = new BusinessStoreOptimized();
$businessStoreCommand = new BusinessStoreOptimized;
// Setze Output auf aktuellen Command (damit Ausgaben weitergeleitet werden)
$businessStoreCommand->setOutput($this->output);
@ -105,8 +105,8 @@ class TestUserLevelUpdate extends Command
// Setze sendUpdateMail
$businessStoreCommand->setSendUpdateMail($sendMail);
$this->info("Führe originale userLevelUpdate() Funktion aus...");
$this->line("");
$this->info('Führe originale userLevelUpdate() Funktion aus...');
$this->line('');
// Rufe die originale Funktion auf
$businessStoreCommand->userLevelUpdate();
@ -138,10 +138,10 @@ class TestUserLevelUpdate extends Command
->where('year', $this->argument('year'))
->where('user_id', $userId)
->whereNotNull('next_qual_user_level')
->whereRaw("JSON_LENGTH(next_qual_user_level) > 0")
->whereRaw('JSON_LENGTH(next_qual_user_level) > 0')
->first();
if (!$userBusiness) {
if (! $userBusiness) {
$this->warn("Keine UserBusiness mit next_qual_user_level gefunden für User ID: {$userId}");
// Zeige vorhandene UserBusiness-Daten
@ -151,18 +151,19 @@ class TestUserLevelUpdate extends Command
->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)));
$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");
$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->info('');
$this->info('DRY-RUN MODUS: Änderungen werden nicht gespeichert');
$this->analyzeLevelUpdate($userBusiness);
}
@ -173,22 +174,23 @@ class TestUserLevelUpdate extends Command
{
$levelUpdateUsers = $userLevelUpdate->getUserBusinessByMonthYear();
$this->info("Gefunden: " . $levelUpdateUsers->count() . " UserBusiness-Einträge mit next_qual_user_level");
$this->line("");
$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.");
$this->warn('Keine UserBusiness-Einträge mit Level-Updates gefunden.');
return;
}
$this->info("DRY-RUN MODUS: Änderungen werden nicht gespeichert");
$this->line("");
$this->info('DRY-RUN MODUS: Änderungen werden nicht gespeichert');
$this->line('');
foreach ($levelUpdateUsers as $userBusiness) {
$this->line("---------------------------------------------------");
$this->line('---------------------------------------------------');
$this->displayUserBusinessInfo($userBusiness);
$this->analyzeLevelUpdate($userBusiness);
$this->line("");
$this->line('');
}
}
@ -199,33 +201,33 @@ class TestUserLevelUpdate extends Command
{
$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'));
$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'));
$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");
$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);
$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('next_qual_user_level: '.(is_null($nextQual) ? 'NULL' : gettype($nextQual)));
}
$this->line("Total Qual PP: " . ($userBusiness->total_qual_pp ?? 0));
$this->line('Total Qual PP: '.($userBusiness->total_qual_pp ?? 0));
}
/**
@ -234,14 +236,16 @@ class TestUserLevelUpdate extends Command
private function analyzeLevelUpdate(UserBusiness $userBusiness)
{
$user = $userBusiness->user;
if (!$user) {
$this->warn("⚠ Kein User-Objekt vorhanden");
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");
if (! is_array($nextQual) || empty($nextQual)) {
$this->warn('⚠ next_qual_user_level ist kein gültiges Array');
return;
}
@ -256,13 +260,13 @@ class TestUserLevelUpdate extends Command
$currentUserLevel = $userLevels->get($user->m_level);
}
$this->info("");
$this->info("📊 Analyse:");
$this->info('');
$this->info('📊 Analyse:');
if ($currentUserLevel) {
$this->line(" Aktuelles Level POS: {$currentUserLevel->pos}");
} else {
$this->line(" Aktuelles Level: Kein Level gesetzt");
$this->line(' Aktuelles Level: Kein Level gesetzt');
}
$wouldUpdate = false;
@ -270,12 +274,13 @@ class TestUserLevelUpdate extends Command
$highestPos = 0;
foreach ($levelArray as $levelData) {
if (!is_array($levelData) || !isset($levelData['id'])) {
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;
}
@ -285,7 +290,7 @@ class TestUserLevelUpdate extends Command
$levelName = $levelData['name'] ?? 'N/A';
$this->line(" 📈 Level ID {$levelData['id']} ({$levelName}): POS {$newLevelPos}");
if (!$currentUserLevel || $newLevelPos > $currentUserLevel->pos) {
if (! $currentUserLevel || $newLevelPos > $currentUserLevel->pos) {
if ($newLevelPos > $highestPos) {
$highestPos = $newLevelPos;
$highestLevel = $levelData;
@ -297,15 +302,15 @@ class TestUserLevelUpdate extends Command
}
if ($wouldUpdate && $highestLevel) {
$this->info("");
$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}");
$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");
$this->info('');
$this->warn('⚠ Kein Level-Update würde durchgeführt:');
if (! $wouldUpdate) {
$this->line(' Kein höheres Level gefunden');
}
}
}
@ -316,6 +321,7 @@ class TestUserLevelUpdate extends Command
private function getLevelName($levelId)
{
$level = UserLevel::find($levelId);
return $level ? $level->name : 'Unbekannt';
}
}