- Menambahkan Command `SendStatementEmailCommand` untuk mengirim email statement PDF: - Mendukung parameter input seperti periode laporan (`YYYY-MM`), nomor rekening, ID batch, queue, dan delay waktu. - Menjalankan validasi parameter input, mencatat log eksekusi, dan mendispatch job pengiriman email. - Menyediakan feedback status eksekusi serta informasi job kepada user. - Menambahkan Job `SendStatementEmailJob` untuk pengiriman statement dalam latar belakang: - Memfilter account yang memiliki email terkait, baik dari `stmt_email` atau email dari data customer. - Melakukan pengiriman email dengan attachment file PDF statement. - Mencatat log sukses atau kegagalan pengiriman untuk setiap account. - Memperbarui Model dan Template Email: - Mengubah template email untuk mendukung pengisian nama rekening secara dinamis berdasarkan customer account. - Menambahkan pengisian dinamis untuk tahun copyright di footer. - Memperbarui Provider `WebstatementServiceProvider`: - Mendaftarkan Command baru `SendStatementEmailCommand` ke dalam aplikasi. Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
338 lines
10 KiB
PHP
338 lines
10 KiB
PHP
<?php
|
|
|
|
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;
|
|
|
|
/**
|
|
* Job untuk mengirim email PDF statement ke nasabah
|
|
*
|
|
* Job ini akan:
|
|
* 1. Mengambil data account yang memiliki email
|
|
* 2. Mencari file PDF statement di storage
|
|
* 3. Mengirim email dengan attachment PDF
|
|
* 4. Mencatat log pengiriman
|
|
*/
|
|
class SendStatementEmailJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
protected $period;
|
|
protected $accountNumber;
|
|
protected $batchId;
|
|
|
|
/**
|
|
* Membuat instance job baru
|
|
*
|
|
* @param string $period Format: YYYY-MM
|
|
* @param string|null $accountNumber Nomor rekening spesifik (opsional)
|
|
* @param string|null $batchId ID batch untuk tracking
|
|
*/
|
|
public function __construct($period, $accountNumber = null, $batchId = null)
|
|
{
|
|
$this->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()
|
|
]);
|
|
}
|
|
}
|