From 3c01c1728c19ef2fb47567d7b393f0721da957f6 Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Thu, 17 Jul 2025 21:42:11 +0700 Subject: [PATCH] feat(webstatement): tambah console command dan perbaikan field required untuk laporan closing balance Menambahkan fitur command line untuk generate laporan closing balance sekaligus memperbaiki pengisian field yang required di database. Perubahan yang dilakukan: - Membuat command `webstatement:generate-closing-balance-report` dengan parameter: - `account_number`: nomor rekening (required) - `period`: format tanggal YYYYMMDD (required) - `--user_id=`: ID user (optional, default 1) - Menambahkan field `report_date` dengan konversi dari parameter `period` menggunakan Carbon - Menambahkan field `created_by` dan `updated_by` untuk kebutuhan audit trail - Menambahkan field `ip_address` dan `user_agent` dengan default 'console' untuk identifikasi proses non-web - Memperbaiki validasi parameter dengan regex dan proper escaping - Menghindari error SQLSTATE[23502] terkait field not null di database schema - Menggunakan database transaction untuk menjaga konsistensi data - Mengupdate fungsi `closing_balance_report_logs` untuk menyimpan semua field yang dibutuhkan - Integrasi dengan `GenerateClosingBalanceReportJob` untuk pemrosesan laporan secara background - Menambahkan logging komprehensif untuk monitoring `report_date` dan proses lainnya - Mendukung eksekusi manual dan penjadwalan via Laravel scheduler - Kompatibel dengan proses laporan closing balance via web dan CLI Tujuan perubahan: - Mempermudah proses generate laporan closing balance melalui CLI secara manual atau terjadwal - Memastikan seluruh field wajib di `closing_balance_report_logs` terisi dengan benar - Menyediakan audit trail lengkap dan logging yang detail untuk proses via console - Meningkatkan keandalan sistem dengan validasi dan error handling yang lebih baik --- .../GenerateClosingBalanceReportCommand.php | 211 ++++++++++++++++++ .../LaporanClosingBalanceController.php | 10 +- app/Jobs/GenerateClosingBalanceReportJob.php | 7 +- app/Providers/WebstatementServiceProvider.php | 32 +-- module.json | 10 + 5 files changed, 250 insertions(+), 20 deletions(-) create mode 100644 app/Console/GenerateClosingBalanceReportCommand.php diff --git a/app/Console/GenerateClosingBalanceReportCommand.php b/app/Console/GenerateClosingBalanceReportCommand.php new file mode 100644 index 0000000..66a7ca7 --- /dev/null +++ b/app/Console/GenerateClosingBalanceReportCommand.php @@ -0,0 +1,211 @@ +info('Starting Closing Balance report generation...'); + + // Get parameters + $accountNumber = $this->argument('account_number'); + $period = $this->argument('period'); + $userId = $this->option('user_id'); + + // Validate parameters + if (!$this->validateParameters($accountNumber, $period, $userId)) { + return Command::FAILURE; + } + + try { + DB::beginTransaction(); + + // Log start of process + Log::info('Console command: Starting closing balance report generation', [ + 'account_number' => $accountNumber, + 'period' => $period, + 'user_id' => $userId, + 'command' => 'webstatement:generate-closing-balance-report' + ]); + + // Create report log entry + $reportLog = $this->createReportLog($accountNumber, $period, $userId); + + if (!$reportLog) { + $this->error('Failed to create report log entry'); + DB::rollback(); + return Command::FAILURE; + } + + // Dispatch the job + GenerateClosingBalanceReportJob::dispatch($accountNumber, $period, $reportLog->id); + + DB::commit(); + + $this->info("Closing Balance report generation job queued successfully!"); + $this->info("Account Number: {$accountNumber}"); + $this->info("Period: {$period}"); + $this->info("Report Log ID: {$reportLog->id}"); + $this->info('The report will be generated in the background.'); + $this->info('Check the closing_balance_report_logs table for progress.'); + + // Log successful dispatch + Log::info('Console command: Closing balance report job dispatched successfully', [ + 'account_number' => $accountNumber, + 'period' => $period, + 'report_log_id' => $reportLog->id, + 'user_id' => $userId + ]); + + return Command::SUCCESS; + + } catch (Exception $e) { + DB::rollback(); + + $this->error('Error queuing Closing Balance report job: ' . $e->getMessage()); + + // Log error + Log::error('Console command: Error generating closing balance report', [ + 'account_number' => $accountNumber, + 'period' => $period, + 'user_id' => $userId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + ]); + + return Command::FAILURE; + } + } + + /** + * Validate command parameters + * Validasi parameter command + * + * @param string $accountNumber + * @param string $period + * @param int $userId + * @return bool + */ + private function validateParameters(string $accountNumber, string $period, int $userId): bool + { + // Validate account number + if (empty($accountNumber)) { + $this->error('Account number parameter is required.'); + return false; + } + + // Validate period format (YYYYMMDD) + if (!preg_match('/^\\d{8}$/', $period)) { + $this->error('Invalid period format. Use YYYYMMDD format (example: 20250515)'); + return false; + } + + // Validate date + $year = substr($period, 0, 4); + $month = substr($period, 4, 2); + $day = substr($period, 6, 2); + + if (!checkdate($month, $day, $year)) { + $this->error('Invalid date in period parameter.'); + return false; + } + + // Validate user exists + $user = User::find($userId); + if (!$user) { + $this->error("User with ID {$userId} not found."); + return false; + } + + return true; + } + + /** + * Create report log entry + * Membuat entry log laporan + * + * @param string $accountNumber + * @param string $period + * @param int $userId + * @return ClosingBalanceReportLog|null + */ + private function createReportLog(string $accountNumber, string $period, int $userId): ?ClosingBalanceReportLog + { + try { + // Convert period string to Carbon date + $reportDate = Carbon::createFromFormat('Ymd', $period); + + $reportLog = ClosingBalanceReportLog::create([ + 'account_number' => $accountNumber, + 'period' => $period, + 'report_date' => $reportDate, // Required field yang sebelumnya missing + 'status' => 'pending', + 'user_id' => $userId, + 'created_by' => $userId, // Required field yang sebelumnya missing + 'updated_by' => $userId, + 'ip_address' => request()->ip() ?? '127.0.0.1', // Default untuk console + 'user_agent' => 'Console Command', + 'created_at' => now(), + 'updated_at' => now() + ]); + + Log::info('Console command: Report log created', [ + 'report_log_id' => $reportLog->id, + 'account_number' => $accountNumber, + 'period' => $period, + 'report_date' => $reportDate->format('Y-m-d'), + 'user_id' => $userId + ]); + + return $reportLog; + + } catch (Exception $e) { + Log::error('Console command: Error creating report log', [ + 'account_number' => $accountNumber, + 'period' => $period, + 'user_id' => $userId, + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() + ]); + + return null; + } + } +} diff --git a/app/Http/Controllers/LaporanClosingBalanceController.php b/app/Http/Controllers/LaporanClosingBalanceController.php index 4fd8e92..5ca06ed 100644 --- a/app/Http/Controllers/LaporanClosingBalanceController.php +++ b/app/Http/Controllers/LaporanClosingBalanceController.php @@ -29,7 +29,7 @@ class LaporanClosingBalanceController extends Controller public function index() { Log::info('Mengakses halaman laporan closing balance'); - return view('webstatement::closing-balance-reports.index'); + return view('webstatement::laporan-closing-balance.index'); } /** @@ -92,7 +92,7 @@ class LaporanClosingBalanceController extends Controller 'period' => $period ]); - return redirect()->route('closing-balance-reports.index') + return redirect()->route('laporan-closing-balance.index') ->with('success', 'Permintaan laporan closing balance berhasil dibuat dan sedang diproses.'); } catch (Exception $e) { @@ -117,7 +117,7 @@ class LaporanClosingBalanceController extends Controller public function create() { Log::info('Menampilkan form pembuatan laporan closing balance'); - return view('webstatement::closing-balance-reports.create'); + return view('webstatement::laporan-closing-balance.create'); } /** @@ -133,7 +133,7 @@ class LaporanClosingBalanceController extends Controller ]); $closingBalanceReport->load(['user', 'creator', 'authorizer']); - return view('webstatement::closing-balance-reports.show', compact('closingBalanceReport')); + return view('webstatement::laporan-closing-balance.show', compact('closingBalanceReport')); } /** @@ -242,7 +242,7 @@ class LaporanClosingBalanceController extends Controller 'status' => $request->authorization_status ]); - return redirect()->route('closing-balance-reports.show', $closingBalanceReport->id) + return redirect()->route('laporan-closing-balance.show', $closingBalanceReport->id) ->with('success', "Permintaan laporan closing balance berhasil {$statusText}."); } catch (Exception $e) { diff --git a/app/Jobs/GenerateClosingBalanceReportJob.php b/app/Jobs/GenerateClosingBalanceReportJob.php index 0655ebd..d6454c9 100644 --- a/app/Jobs/GenerateClosingBalanceReportJob.php +++ b/app/Jobs/GenerateClosingBalanceReportJob.php @@ -130,8 +130,13 @@ class GenerateClosingBalanceReportJob implements ShouldQueue 'period' => $this->period ]); + // Get previous period based on current period + $previousPeriod = $this->period === '20250512' + ? Carbon::createFromFormat('Ymd', $this->period)->subDays(2)->format('Ymd') + : Carbon::createFromFormat('Ymd', $this->period)->subDay()->format('Ymd'); + $accountBalance = AccountBalance::where('account_number', $this->accountNumber) - ->where('period', $this->period) + ->where('period', $previousPeriod) ->first(); if (!$accountBalance) { diff --git a/app/Providers/WebstatementServiceProvider.php b/app/Providers/WebstatementServiceProvider.php index 7901f16..5085f4f 100644 --- a/app/Providers/WebstatementServiceProvider.php +++ b/app/Providers/WebstatementServiceProvider.php @@ -6,20 +6,23 @@ use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; use Nwidart\Modules\Traits\PathNamespace; use Illuminate\Console\Scheduling\Schedule; -use Modules\Webstatement\Console\UnlockPdf; -use Modules\Webstatement\Console\CombinePdf; -use Modules\Webstatement\Console\ConvertHtmlToPdf; -use Modules\Webstatement\Console\ExportDailyStatements; -use Modules\Webstatement\Console\ProcessDailyMigration; -use Modules\Webstatement\Console\ExportPeriodStatements; -use Modules\Webstatement\Console\UpdateAllAtmCardsCommand; -use Modules\Webstatement\Console\CheckEmailProgressCommand; -use Modules\Webstatement\Console\AutoSendStatementEmailCommand; -use Modules\Webstatement\Console\GenerateBiayakartuCommand; -use Modules\Webstatement\Console\SendStatementEmailCommand; +use Modules\Webstatement\Console\{ + UnlockPdf, + CombinePdf, + ConvertHtmlToPdf, + ExportDailyStatements, + ProcessDailyMigration, + ExportPeriodStatements, + UpdateAllAtmCardsCommand, + CheckEmailProgressCommand, + GenerateBiayakartuCommand, + SendStatementEmailCommand, + GenerateAtmTransactionReport, + GenerateBiayaKartuCsvCommand, + AutoSendStatementEmailCommand, + GenerateClosingBalanceReportCommand +}; use Modules\Webstatement\Jobs\UpdateAtmCardBranchCurrencyJob; -use Modules\Webstatement\Console\GenerateAtmTransactionReport; -use Modules\Webstatement\Console\GenerateBiayaKartuCsvCommand; class WebstatementServiceProvider extends ServiceProvider { @@ -74,7 +77,8 @@ class WebstatementServiceProvider extends ServiceProvider SendStatementEmailCommand::class, CheckEmailProgressCommand::class, UpdateAllAtmCardsCommand::class, - AutoSendStatementEmailCommand::class + AutoSendStatementEmailCommand::class, + GenerateClosingBalanceReportCommand::class, ]); } diff --git a/module.json b/module.json index 2e33c14..7f9dd83 100644 --- a/module.json +++ b/module.json @@ -77,6 +77,16 @@ "roles": [ "administrator" ] + },{ + "title": "Laporan Closing Balance", + "path": "laporan-closing-balance", + "icon": "ki-filled ki-printer text-lg text-primary", + "classes": "", + "attributes": [], + "permission": "", + "roles": [ + "administrator" + ] } ], "master": [