From 8a728d6c6e4da7e953de188e5eaf60fd354b830b Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Mon, 2 Jun 2025 10:31:51 +0700 Subject: [PATCH] feat(webstatement): tambahkan fitur penggabungan dan proteksi file PDF - Menambahkan command baru `webstatement:combine-pdf` melalui `CombinePdf` untuk menjalankan proses penggabungan file PDF. - Proses ini mencakup penggabungan file PDF dari folder r14 dan r23 berdasarkan periode tertentu. - File PDF yang dihasilkan juga dilindungi dengan password berbasis nomor rekening. - Membuat controller `CombinePdfController` dengan fungsi utama `combinePdfs` untuk mengontrol alur penggabungan file PDF: - Mendapatkan daftar akun yang relevan. - Mengecek file dari folder r14 dan r23 untuk setiap akun. - Melakukan logging saat file tidak ditemukan atau jika terdapat error dalam proses. - Mendaftarkan job `CombinePdfJob` untuk memproses file secara async. - Menambahkan job baru `CombinePdfJob`: - Menggunakan library `PDFMerger` untuk menggabungkan file. - Terapkan proteksi password menggunakan library `PDFPasswordProtect`. - Memastikan direktori output dibuat jika belum ada. - Melakukan logging saat proses berhasil maupun saat terjadi error. - Memperbarui `WebstatementServiceProvider`: - Mendaftarkan command baru ke dalam provider. - Menambahkan penjadwalan otomatis untuk menjalankan perintah `webstatement:combine-pdf` setiap hari pada pukul 09:30. - Logging hasil eksekusi ke file log `logs/combine-pdf.log`. Signed-off-by: Daeng Deni Mardaeni --- app/Console/CombinePdf.php | 47 +++++++++ app/Http/Controllers/CombinePdfController.php | 93 ++++++++++++++++++ app/Jobs/CombinePdfJob.php | 95 +++++++++++++++++++ app/Providers/WebstatementServiceProvider.php | 20 ++-- 4 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 app/Console/CombinePdf.php create mode 100644 app/Http/Controllers/CombinePdfController.php create mode 100644 app/Jobs/CombinePdfJob.php diff --git a/app/Console/CombinePdf.php b/app/Console/CombinePdf.php new file mode 100644 index 0000000..97719d4 --- /dev/null +++ b/app/Console/CombinePdf.php @@ -0,0 +1,47 @@ +info('Starting combine pdf process...'); + $period = request()->set(['period' => $this->argument('period')]); + try { + $controller = app(CombinePdfController::class); + $response = $controller->combinePdfs($period); + + $responseData = json_decode($response->getContent(), true); + $this->info($responseData['message'] ?? 'Process completed'); + + return Command::SUCCESS; + } catch (Exception $e) { + $this->error('Error processing combine pdf: ' . $e->getMessage()); + return Command::FAILURE; + } + } + } diff --git a/app/Http/Controllers/CombinePdfController.php b/app/Http/Controllers/CombinePdfController.php new file mode 100644 index 0000000..4998c61 --- /dev/null +++ b/app/Http/Controllers/CombinePdfController.php @@ -0,0 +1,93 @@ +input('period', date('Ym')); + + // Get all accounts + $accounts = Account::all(); + $processedCount = 0; + $skippedCount = 0; + $errorCount = 0; + + foreach ($accounts as $account) { + $branchCode = $account->branch_code; + $accountNumber = $account->account_number; + + // Define file paths + $r14Path = storage_path("app/r14/{$period}/{$branchCode}/{$accountNumber}_{$period}.pdf"); + $r23Path = storage_path("app/r23/{$period}/{$branchCode}/{$accountNumber}_{$period}.pdf"); + $outputDir = storage_path("app/combine/{$period}/{$branchCode}"); + $outputFilename = "{$accountNumber}_{$period}.pdf"; + + // Check if files exist + $r14Exists = File::exists($r14Path); + $r23Exists = File::exists($r23Path); + + // Skip if neither file exists + if (!$r14Exists && !$r23Exists) { + Log::warning("No PDF files found for account {$accountNumber}"); + $skippedCount++; + continue; + } + + // If both files exist, combine them + if ($r14Exists && $r23Exists) { + Log::info("Combining PDFs for account {$accountNumber}"); + $pdfFiles = [$r14Path, $r23Path]; + } + // If only one file exists, just apply password protection + else { + Log::info("Applying password protection to single PDF for account {$accountNumber}"); + $pdfFile = $r14Exists ? $r14Path : $r23Path; + $pdfFiles = [$pdfFile]; + } + + try { + // Use the account number as password + $password = $accountNumber; + + // Dispatch job to combine PDFs or apply password protection + CombinePdfJob::dispatch($pdfFiles, $outputDir, $outputFilename, $password); + $processedCount++; + } catch (\Exception $e) { + Log::error("Error processing PDF for account {$accountNumber}: {$e->getMessage()}"); + $errorCount++; + } + } + + return response()->json([ + 'message' => 'PDF combination process has been queued', + 'processed' => $processedCount, + 'skipped' => $skippedCount, + 'errors' => $errorCount, + 'period' => $period + ]); + } +} diff --git a/app/Jobs/CombinePdfJob.php b/app/Jobs/CombinePdfJob.php new file mode 100644 index 0000000..d8e67a0 --- /dev/null +++ b/app/Jobs/CombinePdfJob.php @@ -0,0 +1,95 @@ +pdfFiles = $pdfFiles; + $this->outputPath = $outputPath; + $this->outputFilename = $outputFilename; + $this->password = $password; + } + + /** + * Execute the job. + */ + public function handle(): void + { + try { + // Initialize the PDF merger + $merger = PDFMerger::init(); + + // Add each PDF file to the merger + foreach ($this->pdfFiles as $pdfFile) { + if (file_exists($pdfFile)) { + $merger->addPDF($pdfFile, 'all'); + } else { + Log::warning("PDF file not found: {$pdfFile}"); + } + } + + // Make sure the output directory exists + if (!file_exists($this->outputPath)) { + mkdir($this->outputPath, 0755, true); + } + + // Merge the PDFs + $merger->merge(); + + // Save the merged PDF + $fullPath = $this->outputPath . '/' . $this->outputFilename; + $merger->save($fullPath); + + // Apply password protection if password is provided + if (!empty($this->password)) { + $tempPath = $this->outputPath . '/temp_' . $this->outputFilename; + + // Rename the original file to a temporary name + rename($fullPath, $tempPath); + + // Apply password protection and save to the original filename + PDFPasswordProtect::encrypt($tempPath, $fullPath, $this->password); + + // Remove the temporary file + if (file_exists($tempPath)) { + unlink($tempPath); + } + + Log::info("PDF password protection applied successfully."); + } + + Log::info("PDFs combined successfully. Output file: {$fullPath}"); + } catch (Exception $e) { + Log::error("Error combining PDFs: " . $e->getMessage()); + throw $e; + } + } +} diff --git a/app/Providers/WebstatementServiceProvider.php b/app/Providers/WebstatementServiceProvider.php index ca25ffb..2d40001 100644 --- a/app/Providers/WebstatementServiceProvider.php +++ b/app/Providers/WebstatementServiceProvider.php @@ -2,15 +2,16 @@ namespace Modules\Webstatement\Providers; -use Illuminate\Console\Scheduling\Schedule; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; -use Modules\Webstatement\Console\ExportDailyStatements; -use Modules\Webstatement\Console\GenerateBiayakartuCommand; -use Modules\Webstatement\Console\GenerateBiayaKartuCsvCommand; -use Modules\Webstatement\Console\ProcessDailyMigration; -use Modules\Webstatement\Jobs\UpdateAtmCardBranchCurrencyJob; use Nwidart\Modules\Traits\PathNamespace; +use Illuminate\Console\Scheduling\Schedule; +use Modules\Webstatement\Console\CombinePdf; +use Modules\Webstatement\Console\ExportDailyStatements; +use Modules\Webstatement\Console\ProcessDailyMigration; +use Modules\Webstatement\Console\GenerateBiayakartuCommand; +use Modules\Webstatement\Jobs\UpdateAtmCardBranchCurrencyJob; +use Modules\Webstatement\Console\GenerateBiayaKartuCsvCommand; class WebstatementServiceProvider extends ServiceProvider { @@ -57,6 +58,7 @@ class WebstatementServiceProvider extends ServiceProvider GenerateBiayaKartuCsvCommand::class, ProcessDailyMigration::class, ExportDailyStatements::class, + CombinePdf::class ]); } @@ -98,7 +100,11 @@ class WebstatementServiceProvider extends ServiceProvider ->withoutOverlapping() ->appendOutputTo(storage_path('logs/statement-export.log')); - + // Combine PDf + $schedule->command('webstatement:combine-pdf') + ->dailyAt('09:30') + ->withoutOverlapping() + ->appendOutputTo(storage_path('logs/combine-pdf.log')); } /**