feat(webstatement): tambah fungsi generatePdf ke ExportStatementPeriodJob
Perubahan yang dilakukan: - Menambahkan fungsi generatePdf() untuk proses generate PDF dalam job ExportStatementPeriodJob. - Mengintegrasikan logika PDF generation dari PrintStatementController ke dalam job. - Menggunakan data ProcessedStatement yang telah diproses sebagai sumber untuk pembuatan PDF. - Menambahkan import statement untuk Browsershot, Account, Customer, dan Branch. - Mengimplementasikan fungsi prepareHeaderTableBackground() untuk mengonversi gambar header menjadi base64. - Menggunakan database transaction untuk menjaga konsistensi saat generate dan menyimpan PDF. - Menyimpan PDF ke storage dengan struktur direktori yang terorganisir berdasarkan parameter tertentu. - Memperbarui PrintStatementLog dengan status akhir dan path file PDF yang dihasilkan. - Menambahkan error handling dan logging secara menyeluruh untuk memantau proses. - Menghapus file sementara (temporary) setelah PDF berhasil disimpan ke storage. - Menambahkan dukungan timeout dan konfigurasi Browsershot yang optimal. - Melakukan validasi terhadap data account, customer, dan branch sebelum proses generate PDF dilakukan. Tujuan perubahan: - Memindahkan logika generate PDF ke dalam background job agar lebih efisien dan terstruktur. - Menjamin integritas data dan hasil PDF yang valid melalui proses terstandarisasi. - Mengurangi beban proses di controller serta mendukung proses batch secara asynchronous.
This commit is contained in:
@@ -16,7 +16,7 @@ use Modules\Webstatement\Models\{Account, AccountBalance, PrintStatementLog, Pro
|
|||||||
use Spatie\Browsershot\Browsershot;
|
use Spatie\Browsershot\Browsershot;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
ini_set('memory_limit', '2G'); // Atau '1G' untuk data yang sangat besar
|
ini_set('memory_limit', '2G'); // Atau '1G' untuk data yang sangat besar
|
||||||
ini_set('max_execution_time', 300000);
|
ini_set('max_execution_time', 300000);
|
||||||
|
|
||||||
class PrintStatementController extends Controller
|
class PrintStatementController extends Controller
|
||||||
{
|
{
|
||||||
@@ -49,7 +49,7 @@ ini_set('max_execution_time', 300000);
|
|||||||
if($request->input('branch_code') && !empty($request->input('stmt_sent_type'))){
|
if($request->input('branch_code') && !empty($request->input('stmt_sent_type'))){
|
||||||
$request_type = 'multi_account'; // Default untuk request manual
|
$request_type = 'multi_account'; // Default untuk request manual
|
||||||
}
|
}
|
||||||
|
|
||||||
if($request_type=='single_account'){
|
if($request_type=='single_account'){
|
||||||
$account = Account::where('account_number', $accountNumber)->first();
|
$account = Account::where('account_number', $accountNumber)->first();
|
||||||
if ($account) {
|
if ($account) {
|
||||||
@@ -101,7 +101,7 @@ ini_set('max_execution_time', 300000);
|
|||||||
$validated['created_by'] = Auth::id();
|
$validated['created_by'] = Auth::id();
|
||||||
$validated['ip_address'] = $request->ip();
|
$validated['ip_address'] = $request->ip();
|
||||||
$validated['user_agent'] = $request->userAgent();
|
$validated['user_agent'] = $request->userAgent();
|
||||||
|
|
||||||
$validated['status'] = 'pending'; // Status awal
|
$validated['status'] = 'pending'; // Status awal
|
||||||
$validated['authorization_status'] = 'approved'; // Status otorisasi awal
|
$validated['authorization_status'] = 'approved'; // Status otorisasi awal
|
||||||
$validated['total_accounts'] = 1; // Untuk single account
|
$validated['total_accounts'] = 1; // Untuk single account
|
||||||
@@ -110,7 +110,7 @@ ini_set('max_execution_time', 300000);
|
|||||||
$validated['failed_count'] = 0;
|
$validated['failed_count'] = 0;
|
||||||
$validated['stmt_sent_type'] = $request->input('stmt_sent_type') ? implode(",",$request->input('stmt_sent_type')) : '';
|
$validated['stmt_sent_type'] = $request->input('stmt_sent_type') ? implode(",",$request->input('stmt_sent_type')) : '';
|
||||||
$validated['branch_code'] = $validated['branch_code'] ?? $branch_code; // Awal tidak tersedia
|
$validated['branch_code'] = $validated['branch_code'] ?? $branch_code; // Awal tidak tersedia
|
||||||
|
|
||||||
// Create the statement log
|
// Create the statement log
|
||||||
$statement = PrintStatementLog::create($validated);
|
$statement = PrintStatementLog::create($validated);
|
||||||
|
|
||||||
@@ -825,9 +825,6 @@ ini_set('max_execution_time', 300000);
|
|||||||
$period = $statement->period_from;
|
$period = $statement->period_from;
|
||||||
$format='pdf';
|
$format='pdf';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Generate nama file PDF
|
// Generate nama file PDF
|
||||||
$filename = $this->generatePdfFileName($norek, $period);
|
$filename = $this->generatePdfFileName($norek, $period);
|
||||||
|
|
||||||
@@ -967,10 +964,11 @@ ini_set('max_execution_time', 300000);
|
|||||||
Browsershot::html($html)
|
Browsershot::html($html)
|
||||||
->showBackground()
|
->showBackground()
|
||||||
->setOption('addStyleTag', json_encode(['content' => '@page { margin: 0; }']))
|
->setOption('addStyleTag', json_encode(['content' => '@page { margin: 0; }']))
|
||||||
|
->setOption('protocolTimeout', 2147483) // 120000 ms = 2 menit
|
||||||
->format('A4')
|
->format('A4')
|
||||||
->margins(0, 0, 0, 0)
|
->margins(0, 0, 0, 0)
|
||||||
->waitUntilNetworkIdle()
|
->waitUntil('load')
|
||||||
->timeout(6000)
|
->timeout(2147483)
|
||||||
->save($tempPath);
|
->save($tempPath);
|
||||||
|
|
||||||
// Verifikasi file berhasil dibuat
|
// Verifikasi file berhasil dibuat
|
||||||
@@ -1281,30 +1279,30 @@ ini_set('max_execution_time', 300000);
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// DB::beginTransaction();
|
// DB::beginTransaction();
|
||||||
|
|
||||||
Log::info('Starting statement processing', [
|
Log::info('Starting statement processing', [
|
||||||
'statement_id' => $statement->id,
|
'statement_id' => $statement->id,
|
||||||
'request_type' => $statement->request_type,
|
'request_type' => $statement->request_type,
|
||||||
'stmt_sent_type' => $statement->stmt_sent_type,
|
'stmt_sent_type' => $statement->stmt_sent_type,
|
||||||
'branch_code' => $statement->branch_code
|
'branch_code' => $statement->branch_code
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
if ($statement->request_type === 'multi_account') {
|
if ($statement->request_type === 'multi_account') {
|
||||||
return $this->processMultiAccountStatement($statement);
|
return $this->processMultiAccountStatement($statement);
|
||||||
} else {
|
} else {
|
||||||
return $this->processSingleAccountStatement($statement);
|
return $this->processSingleAccountStatement($statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
//DB::rollBack();
|
//DB::rollBack();
|
||||||
|
|
||||||
Log::error('Failed to process statement', [
|
Log::error('Failed to process statement', [
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'statement_id' => $statement->id,
|
'statement_id' => $statement->id,
|
||||||
'trace' => $e->getTraceAsString()
|
'trace' => $e->getTraceAsString()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Failed to process statement',
|
'message' => 'Failed to process statement',
|
||||||
@@ -1323,22 +1321,22 @@ ini_set('max_execution_time', 300000);
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$period = $statement->period_from ?? date('Ym');
|
$period = $statement->period_from ?? date('Ym');
|
||||||
|
|
||||||
// Validasi stmt_sent_type
|
// Validasi stmt_sent_type
|
||||||
if (empty($statement->stmt_sent_type)) {
|
if (empty($statement->stmt_sent_type)) {
|
||||||
throw new \Exception('stmt_sent_type is required for multi account processing');
|
throw new \Exception('stmt_sent_type is required for multi account processing');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode stmt_sent_type jika dalam format JSON array
|
// Decode stmt_sent_type jika dalam format JSON array
|
||||||
$stmtSentTypes = explode(',', $statement->stmt_sent_type);
|
$stmtSentTypes = explode(',', $statement->stmt_sent_type);
|
||||||
|
|
||||||
Log::info('Processing multi account statement', [
|
Log::info('Processing multi account statement', [
|
||||||
'statement_id' => $statement->id,
|
'statement_id' => $statement->id,
|
||||||
'branch_code' => $statement->branch_code,
|
'branch_code' => $statement->branch_code,
|
||||||
'stmt_sent_types' => $stmtSentTypes,
|
'stmt_sent_types' => $stmtSentTypes,
|
||||||
'period' => $period
|
'period' => $period
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$clientName = $statement->branch_code.'_'.$period.'_';//.implode('_'.$stmtSentTypes);
|
$clientName = $statement->branch_code.'_'.$period.'_';//.implode('_'.$stmtSentTypes);
|
||||||
@@ -1352,13 +1350,13 @@ ini_set('max_execution_time', 300000);
|
|||||||
if ($accounts->isEmpty()) {
|
if ($accounts->isEmpty()) {
|
||||||
throw new \Exception('No accounts found for the specified criteria');
|
throw new \Exception('No accounts found for the specified criteria');
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info('Found accounts for processing', [
|
Log::info('Found accounts for processing', [
|
||||||
'total_accounts' => $accounts->count(),
|
'total_accounts' => $accounts->count(),
|
||||||
'branch_code' => $statement->branch_code,
|
'branch_code' => $statement->branch_code,
|
||||||
'stmt_sent_types' => $stmtSentTypes
|
'stmt_sent_types' => $stmtSentTypes
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Update statement log dengan informasi accounts
|
// Update statement log dengan informasi accounts
|
||||||
$accountNumbers = $accounts->pluck('account_number')->toArray();
|
$accountNumbers = $accounts->pluck('account_number')->toArray();
|
||||||
|
|
||||||
@@ -1368,7 +1366,7 @@ ini_set('max_execution_time', 300000);
|
|||||||
'status' => 'processing',
|
'status' => 'processing',
|
||||||
'started_at' => now()
|
'started_at' => now()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Dispatch job untuk generate PDF multi account
|
// Dispatch job untuk generate PDF multi account
|
||||||
$job = GenerateMultiAccountPdfJob::dispatch(
|
$job = GenerateMultiAccountPdfJob::dispatch(
|
||||||
$statement,
|
$statement,
|
||||||
@@ -1376,16 +1374,16 @@ ini_set('max_execution_time', 300000);
|
|||||||
$period,
|
$period,
|
||||||
$clientName
|
$clientName
|
||||||
);
|
);
|
||||||
|
|
||||||
DB::commit();
|
DB::commit();
|
||||||
|
|
||||||
Log::info('Multi account PDF generation job dispatched', [
|
Log::info('Multi account PDF generation job dispatched', [
|
||||||
'job_id' => $job->job_id ?? null,
|
'job_id' => $job->job_id ?? null,
|
||||||
'statement_id' => $statement->id,
|
'statement_id' => $statement->id,
|
||||||
'total_accounts' => $accounts->count(),
|
'total_accounts' => $accounts->count(),
|
||||||
'period' => $period
|
'period' => $period
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Multi account statement processing queued successfully',
|
'message' => 'Multi account statement processing queued successfully',
|
||||||
@@ -1398,16 +1396,16 @@ ini_set('max_execution_time', 300000);
|
|||||||
'client_name' => $clientName
|
'client_name' => $clientName
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
DB::rollBack();
|
DB::rollBack();
|
||||||
|
|
||||||
Log::error('Failed to process multi account statement', [
|
Log::error('Failed to process multi account statement', [
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'statement_id' => $statement->id,
|
'statement_id' => $statement->id,
|
||||||
'trace' => $e->getTraceAsString()
|
'trace' => $e->getTraceAsString()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1491,24 +1489,24 @@ ini_set('max_execution_time', 300000);
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$statement = PrintStatementLog::findOrFail($statementId);
|
$statement = PrintStatementLog::findOrFail($statementId);
|
||||||
|
|
||||||
if ($statement->request_type !== 'multi_account') {
|
if ($statement->request_type !== 'multi_account') {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'This statement is not a multi account request'
|
'message' => 'This statement is not a multi account request'
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$statement->is_available) {
|
if (!$statement->is_available) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Statement files are not available for download'
|
'message' => 'Statement files are not available for download'
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find ZIP file
|
// Find ZIP file
|
||||||
$zipFiles = Storage::disk('local')->files("statements/{$statement->period_from}/multi_account/{$statementId}");
|
$zipFiles = Storage::disk('local')->files("statements/{$statement->period_from}/multi_account/{$statementId}");
|
||||||
|
|
||||||
$zipFile = null;
|
$zipFile = null;
|
||||||
foreach ($zipFiles as $file) {
|
foreach ($zipFiles as $file) {
|
||||||
if (pathinfo($file, PATHINFO_EXTENSION) === 'zip') {
|
if (pathinfo($file, PATHINFO_EXTENSION) === 'zip') {
|
||||||
@@ -1516,39 +1514,39 @@ ini_set('max_execution_time', 300000);
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$zipFile || !Storage::disk('local')->exists($zipFile)) {
|
if (!$zipFile || !Storage::disk('local')->exists($zipFile)) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'ZIP file not found'
|
'message' => 'ZIP file not found'
|
||||||
], 404);
|
], 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$zipPath = Storage::disk('local')->path($zipFile);
|
$zipPath = Storage::disk('local')->path($zipFile);
|
||||||
$filename = basename($zipFile);
|
$filename = basename($zipFile);
|
||||||
|
|
||||||
// Update download status
|
// Update download status
|
||||||
$statement->update([
|
$statement->update([
|
||||||
'is_downloaded' => true,
|
'is_downloaded' => true,
|
||||||
'downloaded_at' => now()
|
'downloaded_at' => now()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Log::info('Multi account ZIP downloaded', [
|
Log::info('Multi account ZIP downloaded', [
|
||||||
'statement_id' => $statementId,
|
'statement_id' => $statementId,
|
||||||
'zip_file' => $zipFile,
|
'zip_file' => $zipFile,
|
||||||
'user_id' => Auth::id()
|
'user_id' => Auth::id()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->download($zipPath, $filename, [
|
return response()->download($zipPath, $filename, [
|
||||||
'Content-Type' => 'application/zip'
|
'Content-Type' => 'application/zip'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Log::error('Failed to download multi account ZIP', [
|
Log::error('Failed to download multi account ZIP', [
|
||||||
'statement_id' => $statementId,
|
'statement_id' => $statementId,
|
||||||
'error' => $e->getMessage()
|
'error' => $e->getMessage()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Failed to download ZIP file',
|
'message' => 'Failed to download ZIP file',
|
||||||
|
|||||||
@@ -4,20 +4,32 @@ namespace Modules\Webstatement\Jobs;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\{
|
||||||
|
Queueable
|
||||||
|
};
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Queue\{
|
||||||
|
InteractsWithQueue,
|
||||||
|
SerializesModels
|
||||||
|
};
|
||||||
|
use Illuminate\Support\Facades\{
|
||||||
|
DB,
|
||||||
|
Log,
|
||||||
|
Storage
|
||||||
|
};
|
||||||
|
use Spatie\Browsershot\Browsershot;
|
||||||
|
use Modules\Webstatement\Models\{
|
||||||
|
PrintStatementLog,
|
||||||
|
ProcessedStatement,
|
||||||
|
StmtEntry,
|
||||||
|
TempFundsTransfer,
|
||||||
|
TempStmtNarrFormat,
|
||||||
|
TempStmtNarrParam,
|
||||||
|
Account,
|
||||||
|
Customer
|
||||||
|
};
|
||||||
|
use Modules\Basicdata\Models\Branch;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
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\Storage;
|
|
||||||
use Modules\Webstatement\Models\PrintStatementLog;
|
|
||||||
use Modules\Webstatement\Models\ProcessedStatement;
|
|
||||||
use Modules\Webstatement\Models\StmtEntry;
|
|
||||||
use Modules\Webstatement\Models\TempFundsTransfer;
|
|
||||||
use Modules\Webstatement\Models\TempStmtNarrFormat;
|
|
||||||
use Modules\Webstatement\Models\TempStmtNarrParam;
|
|
||||||
|
|
||||||
class ExportStatementPeriodJob implements ShouldQueue
|
class ExportStatementPeriodJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
@@ -92,6 +104,10 @@ class ExportStatementPeriodJob implements ShouldQueue
|
|||||||
if($this->toCsv){
|
if($this->toCsv){
|
||||||
$this->exportToCsv();
|
$this->exportToCsv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate PDF setelah data diproses
|
||||||
|
$this->generatePdf();
|
||||||
|
|
||||||
Log::info("Export statement period job completed successfully for account: {$this->account_number}, period: {$this->period}");
|
Log::info("Export statement period job completed successfully for account: {$this->account_number}, period: {$this->period}");
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Log::error("Error in ExportStatementPeriodJob: " . $e->getMessage());
|
Log::error("Error in ExportStatementPeriodJob: " . $e->getMessage());
|
||||||
@@ -110,10 +126,10 @@ class ExportStatementPeriodJob implements ShouldQueue
|
|||||||
$existingDataCount = $this->getExistingProcessedCount($accountQuery);
|
$existingDataCount = $this->getExistingProcessedCount($accountQuery);
|
||||||
|
|
||||||
// Only process if data is not fully processed
|
// Only process if data is not fully processed
|
||||||
//if ($existingDataCount !== $totalCount) {
|
if ($existingDataCount !== $totalCount) {
|
||||||
$this->deleteExistingProcessedData($accountQuery);
|
$this->deleteExistingProcessedData($accountQuery);
|
||||||
$this->processAndSaveStatementEntries($totalCount);
|
$this->processAndSaveStatementEntries($totalCount);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getTotalEntryCount(): int
|
private function getTotalEntryCount(): int
|
||||||
@@ -398,6 +414,166 @@ class ExportStatementPeriodJob implements ShouldQueue
|
|||||||
return str_replace('<NL>', ' ', $result);
|
return str_replace('<NL>', ' ', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate PDF statement untuk account yang diproses
|
||||||
|
* Menggunakan data yang sudah diproses dari ProcessedStatement
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function generatePdf(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
Log::info('ExportStatementPeriodJob: Memulai generate PDF', [
|
||||||
|
'account_number' => $this->account_number,
|
||||||
|
'period' => $this->period,
|
||||||
|
'statement_id' => $this->statementId
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Ambil data account dan customer
|
||||||
|
$account = Account::where('account_number', $this->account_number)->first();
|
||||||
|
if (!$account) {
|
||||||
|
throw new Exception("Account tidak ditemukan: {$this->account_number}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = Customer::where('customer_code', $account->customer_code)->first();
|
||||||
|
if (!$customer) {
|
||||||
|
throw new Exception("Customer tidak ditemukan untuk account: {$this->account_number}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil data branch
|
||||||
|
$branch = Branch::where('code', $account->branch_code)->first();
|
||||||
|
if (!$branch) {
|
||||||
|
throw new Exception("Branch tidak ditemukan: {$account->branch_code}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil statement entries yang sudah diproses
|
||||||
|
$stmtEntries = ProcessedStatement::where('account_number', $this->account_number)
|
||||||
|
->where('period', $this->period)
|
||||||
|
->orderBy('sequence_no')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($stmtEntries->isEmpty()) {
|
||||||
|
throw new Exception("Tidak ada data statement yang diproses untuk account: {$this->account_number}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare header table background (convert to base64 if needed)
|
||||||
|
$headerImagePath = public_path('assets/media/images/bg-header-table.png');
|
||||||
|
$headerTableBg = file_exists($headerImagePath)
|
||||||
|
? base64_encode(file_get_contents($headerImagePath))
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Hitung saldo awal bulan
|
||||||
|
$saldoAwalBulan = (object) ['actual_balance' => (float) $this->saldo];
|
||||||
|
|
||||||
|
// Generate filename
|
||||||
|
$filename = "statement_{$this->account_number}_{$this->period}.pdf";
|
||||||
|
|
||||||
|
// Tentukan path storage
|
||||||
|
$storagePath = "statements/{$this->period}/{$this->account_number}";
|
||||||
|
$tempPath = storage_path("app/temp/{$filename}");
|
||||||
|
$fullStoragePath = "{$storagePath}/{$filename}";
|
||||||
|
|
||||||
|
// Pastikan direktori temp ada
|
||||||
|
if (!file_exists(dirname($tempPath))) {
|
||||||
|
mkdir(dirname($tempPath), 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pastikan direktori storage ada
|
||||||
|
Storage::makeDirectory($storagePath);
|
||||||
|
|
||||||
|
$period = $this->period;
|
||||||
|
|
||||||
|
// Render HTML view
|
||||||
|
$html = view('webstatement::statements.stmt', compact(
|
||||||
|
'stmtEntries',
|
||||||
|
'account',
|
||||||
|
'customer',
|
||||||
|
'headerTableBg',
|
||||||
|
'branch',
|
||||||
|
'period',
|
||||||
|
'saldoAwalBulan'
|
||||||
|
))->render();
|
||||||
|
|
||||||
|
Log::info('ExportStatementPeriodJob: HTML view berhasil di-render', [
|
||||||
|
'account_number' => $this->account_number,
|
||||||
|
'html_length' => strlen($html)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Generate PDF menggunakan Browsershot
|
||||||
|
Browsershot::html($html)
|
||||||
|
->showBackground()
|
||||||
|
->setOption('addStyleTag', json_encode(['content' => '@page { margin: 0; }']))
|
||||||
|
->setOption('protocolTimeout', 2147483) // 2 menit timeout
|
||||||
|
->format('A4')
|
||||||
|
->margins(0, 0, 0, 0)
|
||||||
|
->waitUntil('load')
|
||||||
|
->timeout(2147483)
|
||||||
|
->save($tempPath);
|
||||||
|
|
||||||
|
// Verifikasi file berhasil dibuat
|
||||||
|
if (!file_exists($tempPath)) {
|
||||||
|
throw new Exception('PDF file gagal dibuat');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileSize = filesize($tempPath);
|
||||||
|
|
||||||
|
// Pindahkan file ke storage permanen
|
||||||
|
$pdfContent = file_get_contents($tempPath);
|
||||||
|
Storage::put($fullStoragePath, $pdfContent);
|
||||||
|
|
||||||
|
// Update print statement log
|
||||||
|
$printLog = PrintStatementLog::find($this->statementId);
|
||||||
|
if ($printLog) {
|
||||||
|
$printLog->update([
|
||||||
|
'is_available' => true,
|
||||||
|
'is_generated' => true,
|
||||||
|
'pdf_path' => $fullStoragePath,
|
||||||
|
'file_size' => $fileSize
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hapus file temporary
|
||||||
|
if (file_exists($tempPath)) {
|
||||||
|
unlink($tempPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('ExportStatementPeriodJob: PDF berhasil dibuat dan disimpan', [
|
||||||
|
'account_number' => $this->account_number,
|
||||||
|
'period' => $this->period,
|
||||||
|
'storage_path' => $fullStoragePath,
|
||||||
|
'file_size' => $fileSize,
|
||||||
|
'statement_id' => $this->statementId
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
Log::error('ExportStatementPeriodJob: Gagal generate PDF', [
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'account_number' => $this->account_number,
|
||||||
|
'period' => $this->period,
|
||||||
|
'statement_id' => $this->statementId,
|
||||||
|
'trace' => $e->getTraceAsString()
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Update print statement log dengan status error
|
||||||
|
$printLog = PrintStatementLog::find($this->statementId);
|
||||||
|
if ($printLog) {
|
||||||
|
$printLog->update([
|
||||||
|
'is_available' => false,
|
||||||
|
'error_message' => $e->getMessage()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Gagal generate PDF: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export processed data to CSV file
|
* Export processed data to CSV file
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user