period = $period; $this->accountNumber = $accountNumber; $this->batchId = $batchId ?? uniqid('batch_'); Log::info('SendStatementEmailJob created', [ 'period' => $this->period, 'account_number' => $this->accountNumber, 'batch_id' => $this->batchId ]); } /** * Menjalankan job pengiriman email statement * * @return void */ public function handle(): void { Log::info('Starting SendStatementEmailJob execution', [ 'batch_id' => $this->batchId, 'period' => $this->period, 'account_number' => $this->accountNumber ]); DB::beginTransaction(); try { // Ambil accounts yang memiliki email $accounts = $this->getAccountsWithEmail(); if ($accounts->isEmpty()) { Log::warning('No accounts with email found', [ 'period' => $this->period, 'account_number' => $this->accountNumber, 'batch_id' => $this->batchId ]); DB::commit(); return; } $successCount = 0; $failedCount = 0; foreach ($accounts as $account) { try { $this->sendStatementEmail($account); $successCount++; Log::info('Statement email sent successfully', [ 'account_number' => $account->account_number, 'branch_code' => $account->branch_code, 'email' => $account->stmt_email, 'batch_id' => $this->batchId ]); } catch (\Exception $e) { $failedCount++; Log::error('Failed to send statement email', [ 'account_number' => $account->account_number, 'branch_code' => $account->branch_code, 'email' => $account->stmt_email, 'error' => $e->getMessage(), 'batch_id' => $this->batchId ]); } } DB::commit(); Log::info('SendStatementEmailJob completed', [ 'batch_id' => $this->batchId, 'total_accounts' => $accounts->count(), 'success_count' => $successCount, 'failed_count' => $failedCount ]); } catch (\Exception $e) { DB::rollBack(); Log::error('SendStatementEmailJob failed', [ 'batch_id' => $this->batchId, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); throw $e; } } /** * Mengambil accounts yang memiliki email dan sesuai kriteria * * @return \Illuminate\Database\Eloquent\Collection */ private function getAccountsWithEmail() { Log::info('Fetching accounts with email', [ 'period' => $this->period, 'account_number' => $this->accountNumber ]); $query = Account::with('customer') ->where('stmt_sent_type', 'BY.EMAIL'); // Jika account number spesifik diberikan if ($this->accountNumber) { $query->where('account_number', $this->accountNumber); } // Ambil semua accounts yang memenuhi kriteria $accounts = $query->get(); // Filter accounts yang memiliki email (dari stmt_email atau customer email) $accountsWithEmail = $accounts->filter(function ($account) { // Cek apakah stmt_email ada dan tidak kosong if (!empty($account->stmt_email)) { return true; } // Jika stmt_email kosong, cek email di customer if ($account->customer && !empty($account->customer->email)) { return true; } return false; }); Log::info('Accounts with email retrieved', [ 'total_accounts' => $accounts->count(), 'accounts_with_email' => $accountsWithEmail->count(), 'batch_id' => $this->batchId ]); return $accountsWithEmail; } /** * Mendapatkan email untuk pengiriman statement * * @param Account $account * @return string|null */ private function getEmailForAccount(Account $account) { // Prioritas pertama: stmt_email dari account if (!empty($account->stmt_email)) { Log::info('Using stmt_email from account', [ 'account_number' => $account->account_number, 'email' => $account->stmt_email, 'batch_id' => $this->batchId ]); return $account->stmt_email; } // Prioritas kedua: email dari customer if ($account->customer && !empty($account->customer->email)) { Log::info('Using email from customer', [ 'account_number' => $account->account_number, 'customer_code' => $account->customer_code, 'email' => $account->customer->email, 'batch_id' => $this->batchId ]); return $account->customer->email; } Log::warning('No email found for account', [ 'account_number' => $account->account_number, 'customer_code' => $account->customer_code, 'batch_id' => $this->batchId ]); return null; } /** * Mengirim email statement untuk account tertentu * * @param Account $account * @return void * @throws \Exception */ private function sendStatementEmail(Account $account) { // Dapatkan email untuk pengiriman $emailAddress = $this->getEmailForAccount($account); if (!$emailAddress) { throw new \Exception("No email address found for account {$account->account_number}"); } // Cek apakah file PDF ada $pdfPath = $this->getPdfPath($account->account_number, $account->branch_code); if (!Storage::exists($pdfPath)) { throw new \Exception("PDF file not found: {$pdfPath}"); } // Buat atau update log statement $statementLog = $this->createOrUpdateStatementLog($account); // Dapatkan path absolut file $absolutePdfPath = Storage::path($pdfPath); // Kirim email Mail::to($emailAddress)->send( new StatementEmail($statementLog, $absolutePdfPath, false) ); // Update status log dengan email yang digunakan $statementLog->update([ 'email_sent_at' => now(), 'email_status' => 'sent', 'email_address' => $emailAddress // Simpan email yang digunakan untuk tracking ]); Log::info('Email sent for account', [ 'account_number' => $account->account_number, 'branch_code' => $account->branch_code, 'email' => $emailAddress, 'email_source' => !empty($account->stmt_email) ? 'account.stmt_email' : 'customer.email', 'pdf_path' => $pdfPath, 'batch_id' => $this->batchId ]); } /** * Mendapatkan path file PDF statement * * @param string $accountNumber * @param string $branchCode * @return string */ private function getPdfPath($accountNumber, $branchCode) { return "combine/{$this->period}/{$branchCode}/{$accountNumber}_{$this->period}.pdf"; } /** * Membuat atau update log statement * * @param Account $account * @return PrintStatementLog */ private function createOrUpdateStatementLog(Account $account) { $emailAddress = $this->getEmailForAccount($account); $logData = [ 'account_number' => $account->account_number, 'customer_code' => $account->customer_code, 'branch_code' => $account->branch_code, 'period' => $this->period, 'print_date' => now(), 'batch_id' => $this->batchId, 'email_address' => $emailAddress, 'email_source' => !empty($account->stmt_email) ? 'account' : 'customer' ]; $statementLog = PrintStatementLog::updateOrCreate( [ 'account_number' => $account->account_number, 'period_from' => $this->period, 'period_to' => $this->period ], $logData ); Log::info('Statement log created/updated', [ 'log_id' => $statementLog->id, 'account_number' => $account->account_number, 'email_address' => $emailAddress, 'batch_id' => $this->batchId ]); return $statementLog; } /** * Handle job failure * * @param \Throwable $exception * @return void */ public function failed(\Throwable $exception) { Log::error('SendStatementEmailJob failed permanently', [ 'batch_id' => $this->batchId, 'period' => $this->period, 'account_number' => $this->accountNumber, 'error' => $exception->getMessage(), 'trace' => $exception->getTraceAsString() ]); } }