refactor(webstatement): restrukturisasi kode pada SendStatementEmailJob
- **Perbaikan Struktural:** - Melakukan perapihan kode dengan konsistensi indentasi dan penyusunan namespace seluruh file. - Menambahkan dan mengimpor namespace baru seperti `Throwable`, `InvalidArgumentException`, dan `Exception`. - **Peningkatan Readability:** - Menambahkan format dan penyesuaian pada komentar, khususnya penjelasan method dan atribut. - Menggunakan alignment untuk parameter pada log dan constructor untuk meningkatkan keterbacaan. - **Pengelolaan Job:** - Menambahkan logging detail saat memulai, menjalankan, hingga menyelesaikan job. - Menambahkan penanganan proses tiap akun dalam batch, termasuk logging sukses/gagal dan pembaruan status log. - **Penanganan Error:** - Menambahkan rollback database jika terjadi exception pada saat proses pengiriman email. - Melakukan logging error dengan detail tambahan termasuk pesan dan trace. - **Penambahan Utility:** - Menambahkan metode reusable seperti `updateLogStatus` untuk update status log dengan parameter dinamis. - Menambahkan validasi seperti pengecekan eksistensi file PDF dan email terkait sebelum pengiriman. - **Peningkatan Proses Batch:** - Menambahkan pengelolaan batch berbasis properti `batchId` untuk tracking. - Memperbaiki handle retries dan status akhir batch secara komprehensif (completed, failed). - Menambahkan logging agregat untuk jumlah akun yang diproses dan tingkat keberhasilan. - **Peningkatan Validasi Email:** - Menambahkan skenario untuk pengambilan email dari `stmt_email` atau fallback ke data customer jika tersedia. - Menambahkan peringatan saat akun tertentu tidak memiliki email yang valid. - **Pemeliharaan File PDF:** - Mengecek keberadaan file PDF terkait sebelum proses pengiriman. - Menampilkan log error jika file tidak ditemukan. - **Peningkatan Retry dan Logging Gagal:** - Implementasi metode `failed()` untuk logging pada job yang gagal permanen. - Menangani detail error dan rollback pada level tiap akun dan batch. Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
@@ -1,27 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Webstatement\Jobs;
|
||||
namespace Modules\Webstatement\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Modules\Webstatement\Models\Account;
|
||||
use Modules\Webstatement\Models\PrintStatementLog;
|
||||
use Modules\Webstatement\Mail\StatementEmail;
|
||||
use Modules\Basicdata\Models\Branch;
|
||||
use Exception;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use InvalidArgumentException;
|
||||
use Modules\Webstatement\Mail\StatementEmail;
|
||||
use Modules\Webstatement\Models\Account;
|
||||
use Modules\Webstatement\Models\PrintStatementLog;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Job untuk mengirim email PDF statement ke nasabah
|
||||
* Mendukung pengiriman per rekening, per cabang, atau seluruh cabang
|
||||
*/
|
||||
class SendStatementEmailJob implements ShouldQueue
|
||||
{
|
||||
class SendStatementEmailJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $period;
|
||||
@@ -59,7 +61,8 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
/**
|
||||
* Menjalankan job pengiriman email statement
|
||||
*/
|
||||
public function handle(): void
|
||||
public function handle()
|
||||
: void
|
||||
{
|
||||
Log::info('Starting SendStatementEmailJob execution', [
|
||||
'batch_id' => $this->batchId,
|
||||
@@ -118,7 +121,7 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
'email' => $this->getEmailForAccount($account),
|
||||
'batch_id' => $this->batchId
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$failedCount++;
|
||||
|
||||
Log::error('Failed to send statement email', [
|
||||
@@ -161,7 +164,7 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
'final_status' => $finalStatus
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
$this->updateLogStatus('failed', [
|
||||
@@ -179,6 +182,27 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update status log
|
||||
*/
|
||||
private function updateLogStatus($status, $additionalData = [])
|
||||
{
|
||||
if (!$this->logId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$updateData = array_merge(['status' => $status], $additionalData);
|
||||
PrintStatementLog::where('id', $this->logId)->update($updateData);
|
||||
} catch (Exception $e) {
|
||||
Log::error('Failed to update log status', [
|
||||
'log_id' => $this->logId,
|
||||
'status' => $status,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil accounts berdasarkan request type
|
||||
*/
|
||||
@@ -211,7 +235,7 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Invalid request type: {$this->requestType}");
|
||||
throw new InvalidArgumentException("Invalid request type: {$this->requestType}");
|
||||
}
|
||||
|
||||
$accounts = $query->get();
|
||||
@@ -233,30 +257,64 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
}
|
||||
|
||||
/**
|
||||
* Update status log
|
||||
* Mengirim email statement untuk account tertentu
|
||||
*
|
||||
* @param Account $account
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function updateLogStatus($status, $additionalData = [])
|
||||
private function sendStatementEmail(Account $account)
|
||||
{
|
||||
if (!$this->logId) {
|
||||
return;
|
||||
// Dapatkan email untuk pengiriman
|
||||
$emailAddress = $this->getEmailForAccount($account);
|
||||
|
||||
if (!$emailAddress) {
|
||||
throw new Exception("No email address found for account {$account->account_number}");
|
||||
}
|
||||
|
||||
try {
|
||||
$updateData = array_merge(['status' => $status], $additionalData);
|
||||
PrintStatementLog::where('id', $this->logId)->update($updateData);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to update log status', [
|
||||
'log_id' => $this->logId,
|
||||
'status' => $status,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
// 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
|
||||
// Add delay between email sends to prevent rate limiting
|
||||
sleep(1); // 2 second delay
|
||||
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 email untuk pengiriman statement
|
||||
*
|
||||
* @param Account $account
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function getEmailForAccount(Account $account)
|
||||
@@ -291,64 +349,12 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
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
|
||||
// Add delay between email sends to prevent rate limiting
|
||||
sleep(1); // 2 second delay
|
||||
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)
|
||||
@@ -360,6 +366,7 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
* Membuat atau update log statement
|
||||
*
|
||||
* @param Account $account
|
||||
*
|
||||
* @return PrintStatementLog
|
||||
*/
|
||||
private function createOrUpdateStatementLog(Account $account)
|
||||
@@ -399,7 +406,7 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
/**
|
||||
* Handle job failure
|
||||
*/
|
||||
public function failed(\Throwable $exception)
|
||||
public function failed(Throwable $exception)
|
||||
{
|
||||
$this->updateLogStatus('failed', [
|
||||
'completed_at' => now(),
|
||||
@@ -415,4 +422,4 @@ class SendStatementEmailJob implements ShouldQueue
|
||||
'trace' => $exception->getTraceAsString()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user