diff --git a/app/Console/SendStatementEmailCommand.php b/app/Console/SendStatementEmailCommand.php
new file mode 100644
index 0000000..654db1b
--- /dev/null
+++ b/app/Console/SendStatementEmailCommand.php
@@ -0,0 +1,191 @@
+info('🚀 Memulai proses pengiriman email statement...');
+
+ try {
+ // Ambil parameter
+ $period = $this->argument('period');
+ $accountNumber = $this->option('account');
+ $batchId = $this->option('batch-id');
+ $queueName = $this->option('queue');
+ $delay = (int) $this->option('delay');
+
+ // Validasi parameter
+ if (!$this->validateParameters($period, $accountNumber)) {
+ return Command::FAILURE;
+ }
+
+ // Log command execution
+ Log::info('SendStatementEmailCommand started', [
+ 'period' => $period,
+ 'account_number' => $accountNumber,
+ 'batch_id' => $batchId,
+ 'queue' => $queueName,
+ 'delay' => $delay
+ ]);
+
+ // Dispatch job
+ $job = SendStatementEmailJob::dispatch($period, $accountNumber, $batchId)
+ ->onQueue($queueName);
+
+ if ($delay > 0) {
+ $job->delay(now()->addMinutes($delay));
+ $this->info("⏰ Job dijadwalkan untuk dijalankan dalam {$delay} menit");
+ }
+
+ // Tampilkan informasi
+ $this->displayJobInfo($period, $accountNumber, $batchId, $queueName);
+
+ $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 telescope:work (jika menggunakan Telescope)');
+
+ 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;
+ }
+ }
+
+ /**
+ * Validasi parameter input
+ *
+ * @param string $period
+ * @param string|null $accountNumber
+ * @return bool
+ */
+ private function validateParameters($period, $accountNumber = null)
+ {
+ // Validasi format periode
+ if (!preg_match('/^\d{4}\d{2}$/', $period)) {
+ $this->error('❌ Format periode tidak valid. Gunakan format YYYYMM (contoh: 202401)');
+ return false;
+ }
+
+ // Validasi account number jika diberikan
+ if ($accountNumber) {
+ $account = Account::with('customer')
+ ->where('account_number', $accountNumber)
+ ->first();
+
+ if (!$account) {
+ $this->error("❌ Account {$accountNumber} tidak ditemukan");
+ return false;
+ }
+
+ // Cek apakah ada email (dari stmt_email atau customer email)
+ $hasEmail = !empty($account->stmt_email) ||
+ ($account->customer && !empty($account->customer->email));
+
+ if (!$hasEmail) {
+ $this->error("❌ Account {$accountNumber} tidak memiliki email (baik di stmt_email maupun customer email)");
+ return false;
+ }
+
+ $emailSource = !empty($account->stmt_email) ? 'stmt_email' : 'customer email';
+ $emailAddress = !empty($account->stmt_email) ? $account->stmt_email : $account->customer->email;
+
+ $this->info("✅ Account {$accountNumber} ditemukan dengan email: {$emailAddress} (dari {$emailSource}) - Cabang: {$account->branch_code}");
+ } else {
+ // Cek apakah ada account dengan email (dari stmt_email atau customer email)
+ $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 (baik di stmt_email maupun customer email)');
+ return false;
+ }
+
+ $this->info("✅ Ditemukan {$accountCount} account dengan email");
+ }
+
+ return true;
+ }
+
+ /**
+ * Menampilkan informasi job yang akan dijalankan
+ *
+ * @param string $period
+ * @param string|null $accountNumber
+ * @param string|null $batchId
+ * @param string $queueName
+ * @return void
+ */
+ private function displayJobInfo($period, $accountNumber, $batchId, $queueName)
+ {
+ $this->info('📋 Detail Job:');
+ $this->line(" Periode: {$period}");
+ $this->line(" Account: " . ($accountNumber ?: 'Semua account dengan email'));
+ $this->line(" Batch ID: " . ($batchId ?: 'Auto-generated'));
+ $this->line(" Queue: {$queueName}");
+
+ // Estimasi path file
+ if ($accountNumber) {
+ $account = Account::where('account_number', $accountNumber)->first();
+ if ($account) {
+ $pdfPath = "storage/app/combine/{$period}/{$account->branch_code}/{$accountNumber}_{$period}.pdf";
+ $this->line(" File PDF: {$pdfPath}");
+ }
+ } else {
+ $this->line(" File PDF: storage/app/combine/{$period}/[branch_code]/[account_number]_{$period}.pdf");
+ }
+ }
+}
diff --git a/app/Jobs/SendStatementEmailJob.php b/app/Jobs/SendStatementEmailJob.php
new file mode 100644
index 0000000..a72e3f4
--- /dev/null
+++ b/app/Jobs/SendStatementEmailJob.php
@@ -0,0 +1,337 @@
+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()
+ ]);
+ }
+}
diff --git a/app/Mail/StatementEmail.php b/app/Mail/StatementEmail.php
index f6cbe5b..ba9b628 100644
--- a/app/Mail/StatementEmail.php
+++ b/app/Mail/StatementEmail.php
@@ -5,7 +5,8 @@
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
- use Modules\Webstatement\Models\PrintStatementLog;
+use Modules\Webstatement\Models\Account;
+use Modules\Webstatement\Models\PrintStatementLog;
class StatementEmail extends Mailable
{
@@ -36,12 +37,12 @@
*/
public function build()
{
- $subject = 'Your Account Statement';
+ $subject = 'Statement Rekening Bank Artha Graha Internasional';
if ($this->statement->is_period_range) {
$subject .= " - {$this->statement->period_from} to {$this->statement->period_to}";
} else {
- $subject .= " - {$this->statement->period_from}";
+ $subject .= " - " . \Carbon\Carbon::createFromFormat('Ym', $this->statement->period_from)->locale('id')->isoFormat('MMMM Y');
}
$email = $this->subject($subject)
@@ -52,6 +53,7 @@
'periodFrom' => $this->statement->period_from,
'periodTo' => $this->statement->period_to,
'isRange' => $this->statement->is_period_range,
+ 'accounts' => Account::where('account_number',$this->statement->account_number)->first()
]);
if ($this->isZip) {
diff --git a/app/Providers/WebstatementServiceProvider.php b/app/Providers/WebstatementServiceProvider.php
index a168c92..2e15316 100644
--- a/app/Providers/WebstatementServiceProvider.php
+++ b/app/Providers/WebstatementServiceProvider.php
@@ -16,6 +16,7 @@ use Modules\Webstatement\Console\GenerateBiayakartuCommand;
use Modules\Webstatement\Jobs\UpdateAtmCardBranchCurrencyJob;
use Modules\Webstatement\Console\GenerateAtmTransactionReport;
use Modules\Webstatement\Console\GenerateBiayaKartuCsvCommand;
+use Modules\Webstatement\Console\SendStatementEmailCommand;
class WebstatementServiceProvider extends ServiceProvider
{
@@ -67,6 +68,7 @@ class WebstatementServiceProvider extends ServiceProvider
UnlockPdf::class,
ExportPeriodStatements::class,
GenerateAtmTransactionReport::class,
+ SendStatementEmailCommand::class
]);
}
diff --git a/resources/views/statements/email.blade.php b/resources/views/statements/email.blade.php
index 76e274e..ae4665c 100644
--- a/resources/views/statements/email.blade.php
+++ b/resources/views/statements/email.blade.php
@@ -1,5 +1,6 @@
+
@@ -59,85 +60,96 @@
}
ul.dashed-list {
- list-style-type: none; /* Remove default bullet */
- padding-left: 1em; /* Add some left padding for spacing */
+ list-style-type: none;
+ /* Remove default bullet */
+ padding-left: 1em;
+ /* Add some left padding for spacing */
}
ul.dashed-list li::before {
- content: "– "; /* Use an en dash (U+2013) or a hyphen "-" */
- display: inline-block; /* Ensure proper spacing */
- width: 1em; /* Adjust width as needed */
- margin-left: 0.5em; /* Align the dash properly */
+ content: "– ";
+ /* Use an en dash (U+2013) or a hyphen "-" */
+ display: inline-block;
+ /* Ensure proper spacing */
+ width: 1em;
+ /* Adjust width as needed */
+ margin-left: 0.5em;
+ /* Align the dash properly */
}
+
-
-
-
- Yang Terhormat
Bapak/Ibu Daeng Deni Mardaeni,
+
+
+
+ Yang Terhormat
Bapak/Ibu {{ $accounts->customer->name }},
- Terlampir adalah Electronic Statement Rekening Anda.
- Silahkan gunakan password Electronic Statement Anda untuk membukanya.
- Password standar Elektronic Statement ini adalah
ddMonyyyyxx (contoh: 01Aug1970xx) dimana :
-
- - dd : 2 digit tanggal lahir anda, contoh: 01
- - Mon :
- 3 huruf pertama bulan lahir anda dalam bahasa Ingris. Huruf pertama adalah huruf besar dan selanjutnya huruf kecil, contoh : Aug
-
- - yyyy : 4 digit tahun kelahiran anda, contoh : 1970
- - xx : 2 digit terakhir dari nomer rekening anda, contoh : 12
-
-
+ Terlampir adalah Electronic Statement Rekening Anda.
+ Silahkan gunakan password Electronic Statement Anda untuk membukanya.
+ Password standar Elektronic Statement ini adalah
ddMonyyyyxx (contoh: 01Aug1970xx)
+ dimana :
+
+ - dd : 2 digit tanggal lahir anda, contoh: 01
+ - Mon :
+ 3 huruf pertama bulan lahir anda dalam bahasa Ingris. Huruf pertama adalah
+ huruf besar dan selanjutnya huruf kecil, contoh : Aug
+
+ - yyyy : 4 digit tahun kelahiran anda, contoh : 1970
+ - xx : 2 digit terakhir dari nomer rekening anda, contoh : 12
+
+
- Terima Kasih,
+ Terima Kasih,
-
Bank Artha Graha Internasional
- ------------------------------
-
- ------------------------------
-
- --------
- Kami sangat menghargai masukan dan saran Anda untuk meningkatkan layanan dan produk kami.
- Untuk memberikan masukan, silakan hubungi GrahaCall 24 Jam kami di
- 0-800-191-8880.
+ Bank Artha Graha Internasional
+ ------------------------------
+
+ ------------------------------
+
+ --------
+ Kami sangat menghargai masukan dan saran Anda untuk meningkatkan layanan dan produk kami.
+ Untuk memberikan masukan, silakan hubungi GrahaCall 24 Jam kami di
+ 0-800-191-8880.
- Dear Mr/Mrs/Ms Daeng Deni Mardaeni,
+ Dear Mr/Mrs/Ms {{ $accounts->customer->name }},
- Attached is your Electronic Account Statement.
- Please use your Electronic Statement password to open it.
+ Attached is your Electronic Account Statement.
+ Please use your Electronic Statement password to open it.
- The Electronic Statement standard password is ddMonyyyyxx (example: 01Aug1970xx) where:
-
- - dd : The first 2 digits of your birthdate, example: 01
- - Mon :
- The first 3 letters of your birth month in English. The first letter is uppercase and the rest are lowercase, example: Aug
-
- - yyyy : 4 digit of your birth year, example: 1970
- - xx : The last 2 digits of your account number, example: 12.
-
-
+ The Electronic Statement standard password is ddMonyyyyxx (example: 01Aug1970xx) where:
+
+ - dd : The first 2 digits of your birthdate, example: 01
+ - Mon :
+ The first 3 letters of your birth month in English. The first letter is
+ uppercase and the rest are lowercase, example: Aug
+
+ - yyyy : 4 digit of your birth year, example: 1970
+ - xx : The last 2 digits of your account number, example: 12.
+
+
- Regards,
+ Regards,
- Bank Artha Graha Internasional
- ------------------------------
-
- ------------------------------
-
- --------
- We welcome any feedback or suggestions to improve our product and services.
- If you have any feedback, please contact our GrahaCall 24 Hours at
- 0-800-191-8880.
-
-
+
Bank Artha Graha Internasional
+ ------------------------------
+
+ ------------------------------
+
+ --------
+ We welcome any feedback or suggestions to improve our product and services.
+ If you have any feedback, please contact our GrahaCall 24 Hours at
+ 0-800-191-8880.
+
+
+
+
-
-
+