info('🚀 Memulai proses pengiriman email statement...'); try { $period = $this->argument('period'); $type = $this->option('type'); $accountNumber = $this->option('account'); $branchCode = $this->option('branch'); $batchId = $this->option('batch-id'); $queueName = $this->option('queue'); $delay = (int) $this->option('delay'); // Validasi parameter if (!$this->validateParameters($period, $type, $accountNumber, $branchCode)) { return Command::FAILURE; } // Tentukan request type dan target value [$requestType, $targetValue] = $this->determineRequestTypeAndTarget($type, $accountNumber, $branchCode); // Buat log entry $log = $this->createLogEntry($period, $requestType, $targetValue, $batchId); // Dispatch job $job = SendStatementEmailJob::dispatch($period, $requestType, $targetValue, $batchId, $log->id) ->onQueue($queueName); if ($delay > 0) { $job->delay(now()->addMinutes($delay)); $this->info("⏰ Job dijadwalkan untuk dijalankan dalam {$delay} menit"); } $this->displayJobInfo($period, $requestType, $targetValue, $queueName, $log); $this->info('✅ Job pengiriman email statement berhasil didispatch!'); $this->info('📊 Gunakan command berikut untuk monitoring:'); $this->line(" php artisan queue:work {$queueName}"); $this->line(' php artisan webstatement:check-progress ' . $log->id); return Command::SUCCESS; } catch (Exception $e) { $this->error('❌ Error saat mendispatch job: ' . $e->getMessage()); Log::error('SendStatementEmailCommand failed', [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return Command::FAILURE; } } private function validateParameters($period, $type, $accountNumber, $branchCode) { // Validasi format periode if (!preg_match('/^\d{6}$/', $period)) { $this->error('❌ Format periode tidak valid. Gunakan format YYYYMM (contoh: 202401)'); return false; } // Validasi type if (!in_array($type, ['single', 'branch', 'all'])) { $this->error('❌ Type tidak valid. Gunakan: single, branch, atau all'); return false; } // Validasi parameter berdasarkan type switch ($type) { case 'single': if (!$accountNumber) { $this->error('❌ Parameter --account diperlukan untuk type=single'); return false; } $account = Account::with('customer') ->where('account_number', $accountNumber) ->first(); if (!$account) { $this->error("❌ Account {$accountNumber} tidak ditemukan"); return false; } $hasEmail = !empty($account->stmt_email) || ($account->customer && !empty($account->customer->email)); if (!$hasEmail) { $this->error("❌ Account {$accountNumber} tidak memiliki email"); return false; } $this->info("✅ Account {$accountNumber} ditemukan dengan email"); break; case 'branch': if (!$branchCode) { $this->error('❌ Parameter --branch diperlukan untuk type=branch'); return false; } $branch = Branch::where('code', $branchCode)->first(); if (!$branch) { $this->error("❌ Branch {$branchCode} tidak ditemukan"); return false; } $accountCount = Account::with('customer') ->where('branch_code', $branchCode) ->where('stmt_sent_type', 'BY.EMAIL') ->get() ->filter(function ($account) { return !empty($account->stmt_email) || ($account->customer && !empty($account->customer->email)); }) ->count(); if ($accountCount === 0) { $this->error("❌ Tidak ada account dengan email di branch {$branchCode}"); return false; } $this->info("✅ Ditemukan {$accountCount} account dengan email di branch {$branch->name}"); break; case 'all': $accountCount = Account::with('customer') ->where('stmt_sent_type', 'BY.EMAIL') ->get() ->filter(function ($account) { return !empty($account->stmt_email) || ($account->customer && !empty($account->customer->email)); }) ->count(); if ($accountCount === 0) { $this->error('❌ Tidak ada account dengan email ditemukan'); return false; } $this->info("✅ Ditemukan {$accountCount} account dengan email di seluruh cabang"); break; } return true; } private function determineRequestTypeAndTarget($type, $accountNumber, $branchCode) { switch ($type) { case 'single': return ['single_account', $accountNumber]; case 'branch': return ['branch', $branchCode]; case 'all': return ['all_branches', null]; default: throw new InvalidArgumentException("Invalid type: {$type}"); } } private function createLogEntry($period, $requestType, $targetValue, $batchId) { $logData = [ 'user_id' => null, // Command line execution 'period_from' => $period, 'period_to' => $period, 'is_period_range' => false, 'request_type' => $requestType, 'batch_id' => $batchId ?? uniqid('cmd_'), 'status' => 'pending', 'authorization_status' => 'approved', // Auto-approved untuk command line 'created_by' => null, 'ip_address' => '127.0.0.1', 'user_agent' => 'Command Line' ]; // Set branch_code dan account_number berdasarkan request type switch ($requestType) { case 'single_account': $account = Account::where('account_number', $targetValue)->first(); $logData['branch_code'] = $account->branch_code; $logData['account_number'] = $targetValue; break; case 'branch': $logData['branch_code'] = $targetValue; $logData['account_number'] = null; break; case 'all_branches': $logData['branch_code'] = 'ALL'; $logData['account_number'] = null; break; } return PrintStatementLog::create($logData); } private function displayJobInfo($period, $requestType, $targetValue, $queueName, $log) { $this->info('📋 Detail Job:'); $this->line(" Log ID: {$log->id}"); $this->line(" Periode: {$period}"); $this->line(" Request Type: {$requestType}"); switch ($requestType) { case 'single_account': $this->line(" Account: {$targetValue}"); break; case 'branch': $branch = Branch::where('code', $targetValue)->first(); $this->line(" Branch: {$targetValue} ({$branch->name})"); break; case 'all_branches': $this->line(" Target: Seluruh cabang"); break; } $this->line(" Batch ID: {$log->batch_id}"); $this->line(" Queue: {$queueName}"); } }