From ca92f32ccb288410333e09508d3ad1207e7d3591 Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Thu, 31 Jul 2025 08:13:02 +0700 Subject: [PATCH] feat(webstatement): tambah dukungan queue name pada StagingController dan WebstatementController Menambahkan parameter queue_name untuk mengatur queue spesifik pada job processing: - Menambahkan parameter queueName pada StagingController.processData() dan index() - Menggunakan onQueue() method saat dispatch job di StagingController - Memperbarui ProcessDailyStaging untuk mengirim queue_name ke controller - Menambahkan parameter Request pada WebstatementController untuk menerima queue_name - Menggunakan onQueue() method saat dispatch job di WebstatementController - Menambahkan logging untuk queue_name di semua proses - Memperbarui response JSON untuk menyertakan informasi queue_name - Menambahkan komentar fungsi yang menjelaskan parameter queue_name - Mempertahankan backward compatibility dengan default queue 'default' - Meningkatkan fleksibilitas dalam manajemen queue untuk berbagai environment - Memungkinkan pemisahan job berdasarkan prioritas atau resource yang tersedia --- app/Http/Controllers/StagingController.php | 413 +++++++++-------- .../Controllers/WebstatementController.php | 424 ++++++++++-------- 2 files changed, 460 insertions(+), 377 deletions(-) diff --git a/app/Http/Controllers/StagingController.php b/app/Http/Controllers/StagingController.php index 4feb970..b115c2f 100644 --- a/app/Http/Controllers/StagingController.php +++ b/app/Http/Controllers/StagingController.php @@ -1,199 +1,240 @@ ProcessTransactionDataJob::class, + 'stmtNarrParam' => ProcessStmtNarrParamDataJob::class, + 'stmtNarrFormat' => ProcessStmtNarrFormatDataJob::class, + 'ftTxnTypeCondition' => ProcessFtTxnTypeConditionJob::class, + 'category' => ProcessCategoryDataJob::class, + 'company' => ProcessCompanyDataJob::class, + 'customer' => ProcessCustomerDataJob::class, + 'account' => ProcessAccountDataJob::class, + 'stmtEntry' => ProcessStmtEntryDataJob::class, + 'stmtEntryDetail' => ProcessStmtEntryDetailDataJob::class, + 'dataCapture' => ProcessDataCaptureDataJob::class, + 'fundsTransfer' => ProcessFundsTransferDataJob::class, + 'teller' => ProcessTellerDataJob::class, + 'atmTransaction' => ProcessAtmTransactionJob::class, + 'arrangement' => ProcessArrangementDataJob::class, + 'billDetail' => ProcessBillDetailDataJob::class, + 'sector' => ProcessSectorDataJob::class, + 'province' => ProcessProvinceDataJob::class + ]; + + private const PARAMETER_PROCESSES = [ + 'transaction', + 'stmtNarrParam', + 'stmtNarrFormat', + 'ftTxnTypeCondition', + 'sector', + 'province' + ]; + + private const DATA_PROCESSES = [ + 'category', + 'company', + 'customer', + 'account', + 'stmtEntry', + 'stmtEntryDetail', + 'dataCapture', + 'fundsTransfer', + 'teller', + 'atmTransaction', + 'arrangement', + 'billDetail' + ]; + + public function __call($method, $parameters) { - private const PROCESS_TYPES = [ - 'transaction' => ProcessTransactionDataJob::class, - 'stmtNarrParam' => ProcessStmtNarrParamDataJob::class, - 'stmtNarrFormat' => ProcessStmtNarrFormatDataJob::class, - 'ftTxnTypeCondition' => ProcessFtTxnTypeConditionJob::class, - 'category' => ProcessCategoryDataJob::class, - 'company' => ProcessCompanyDataJob::class, - 'customer' => ProcessCustomerDataJob::class, - 'account' => ProcessAccountDataJob::class, - 'stmtEntry' => ProcessStmtEntryDataJob::class, - 'stmtEntryDetail' => ProcessStmtEntryDetailDataJob::class, // Tambahan baru - 'dataCapture' => ProcessDataCaptureDataJob::class, - 'fundsTransfer' => ProcessFundsTransferDataJob::class, - 'teller' => ProcessTellerDataJob::class, - 'atmTransaction' => ProcessAtmTransactionJob::class, - 'arrangement' => ProcessArrangementDataJob::class, - 'billDetail' => ProcessBillDetailDataJob::class, - 'sector' => ProcessSectorDataJob::class, - 'province' => ProcessProvinceDataJob::class - ]; - - private const PARAMETER_PROCESSES = [ - 'transaction', - 'stmtNarrParam', - 'stmtNarrFormat', - 'ftTxnTypeCondition', - 'sector', - 'province' - ]; - - private const DATA_PROCESSES = [ - 'category', - 'company', - 'customer', - 'account', - 'stmtEntry', - 'stmtEntryDetail', // Tambahan baru - 'dataCapture', - 'fundsTransfer', - 'teller', - 'atmTransaction', - 'arrangement', - 'billDetail' - ]; - - public function __call($method, $parameters) - { - if (strpos($method, 'process') === 0) { - $type = lcfirst(substr($method, 7)); - if (isset(self::PROCESS_TYPES[$type])) { - return $this->processData($type, $parameters[0] ?? ''); - } - } - throw new BadMethodCallException("Method {$method} does not exist."); - } - - private function processData(string $type, string $period) - : JsonResponse - { - try { - $jobClass = self::PROCESS_TYPES[$type]; - $jobClass::dispatch($period); - - $message = sprintf('%s data processing job has been queued successfully', ucfirst($type)); - Log::info($message); - - return response()->json(['message' => $message]); - } catch (Exception $e) { - Log::error(sprintf('Error in %s processing: %s', $type, $e->getMessage())); - return response()->json(['error' => $e->getMessage()], 500); + if (strpos($method, 'process') === 0) { + $type = lcfirst(substr($method, 7)); + if (isset(self::PROCESS_TYPES[$type])) { + return $this->processData($type, $parameters[0] ?? '', $parameters[1] ?? 'default'); } } - /** - * Proses migrasi data dengan parameter dan periode yang dapat dikustomisasi - * - * @param bool|string $processParameter Flag untuk memproses parameter - * @param string|null $period Periode yang akan diproses (default: -1 day) - * @return JsonResponse - */ - public function index($processParameter = false, $period = null) - { - try { - Log::info('Starting migration process', [ - 'process_parameter' => $processParameter, - 'period' => $period - ]); + throw new BadMethodCallException("Method {$method} does not exist."); + } - $disk = Storage::disk('staging'); + /** + * Memproses data dengan queue name yang dapat dikustomisasi + * + * @param string $type Tipe proses yang akan dijalankan + * @param string $period Periode data yang akan diproses + * @param string $queueName Nama queue untuk menjalankan job + * @return JsonResponse + */ + private function processData(string $type, string $period, string $queueName = 'default'): JsonResponse + { + try { + $jobClass = self::PROCESS_TYPES[$type]; - if ($processParameter) { - Log::info('Processing parameter data'); + // Dispatch job dengan queue name yang spesifik + $jobClass::dispatch($period)->onQueue($queueName); - foreach (self::PARAMETER_PROCESSES as $process) { - $this->processData($process, '_parameter'); - } + $message = sprintf('%s data processing job has been queued successfully on queue: %s', ucfirst($type), $queueName); + Log::info($message, [ + 'type' => $type, + 'period' => $period, + 'queue_name' => $queueName + ]); - Log::info('Parameter processes completed successfully'); - return response()->json(['message' => 'Parameter processes completed successfully']); - } - - // Tentukan periode yang akan diproses - $targetPeriod = $this->determinePeriod($period); - - Log::info('Processing data for period', ['period' => $targetPeriod]); - - if (!$disk->exists($targetPeriod)) { - $errorMessage = "Period {$targetPeriod} folder not found in SFTP storage"; - Log::warning($errorMessage); - - return response()->json([ - "message" => $errorMessage - ], 404); - } - - foreach (self::DATA_PROCESSES as $process) { - $this->processData($process, $targetPeriod); - } - - $successMessage = "Data processing for period {$targetPeriod} has been queued successfully"; - Log::info($successMessage); - - return response()->json([ - 'message' => $successMessage - ]); - } catch (Exception $e) { - Log::error('Error in migration index method: ' . $e->getMessage()); - return response()->json(['error' => $e->getMessage()], 500); - } - } - - /** - * Tentukan periode berdasarkan input atau gunakan default - * - * @param string|null $period Input periode - * @return string Periode dalam format Ymd - */ - private function determinePeriod($period = null): string - { - if ($period === null) { - // Default: -1 day - $calculatedPeriod = date('Ymd', strtotime('-1 day')); - Log::info('Using default period', ['period' => $calculatedPeriod]); - return $calculatedPeriod; - } - - // Jika periode sudah dalam format Ymd (8 digit) - if (preg_match('/^\d{8}$/', $period)) { - Log::info('Using provided period in Ymd format', ['period' => $period]); - return $period; - } - - // Jika periode dalam format relative date (contoh: -2 days, -1 week, etc.) - try { - $calculatedPeriod = date('Ymd', strtotime($period)); - Log::info('Calculated period from relative date', [ - 'input' => $period, - 'calculated' => $calculatedPeriod - ]); - return $calculatedPeriod; - } catch (Exception $e) { - Log::warning('Invalid period format, using default', [ - 'input' => $period, - 'error' => $e->getMessage() - ]); - return date('Ymd', strtotime('-1 day')); - } + return response()->json([ + 'message' => $message, + 'queue_name' => $queueName + ]); + } catch (Exception $e) { + Log::error(sprintf('Error in %s processing: %s', $type, $e->getMessage()), [ + 'type' => $type, + 'period' => $period, + 'queue_name' => $queueName, + 'error' => $e->getMessage() + ]); + return response()->json(['error' => $e->getMessage()], 500); } } + + /** + * Proses migrasi data dengan parameter, periode, dan queue name yang dapat dikustomisasi + * + * @param bool|string $processParameter Flag untuk memproses parameter + * @param string|null $period Periode yang akan diproses (default: -1 day) + * @param string $queueName Nama queue untuk menjalankan job (default: default) + * @return JsonResponse + */ + public function index($processParameter = false, $period = null, $queueName = 'default') + { + try { + Log::info('Starting migration process', [ + 'process_parameter' => $processParameter, + 'period' => $period, + 'queue_name' => $queueName + ]); + + $disk = Storage::disk('staging'); + + if ($processParameter) { + Log::info('Processing parameter data', ['queue_name' => $queueName]); + + foreach (self::PARAMETER_PROCESSES as $process) { + $this->processData($process, '_parameter', $queueName); + } + + Log::info('Parameter processes completed successfully', ['queue_name' => $queueName]); + return response()->json([ + 'message' => 'Parameter processes completed successfully', + 'queue_name' => $queueName + ]); + } + + // Tentukan periode yang akan diproses + $targetPeriod = $this->determinePeriod($period); + + Log::info('Processing data for period', [ + 'period' => $targetPeriod, + 'queue_name' => $queueName + ]); + + if (!$disk->exists($targetPeriod)) { + $errorMessage = "Period {$targetPeriod} folder not found in SFTP storage"; + Log::warning($errorMessage, ['queue_name' => $queueName]); + + return response()->json([ + "message" => $errorMessage, + 'queue_name' => $queueName + ], 404); + } + + foreach (self::DATA_PROCESSES as $process) { + $this->processData($process, $targetPeriod, $queueName); + } + + $successMessage = "Data processing for period {$targetPeriod} has been queued successfully on queue: {$queueName}"; + Log::info($successMessage, [ + 'period' => $targetPeriod, + 'queue_name' => $queueName + ]); + + return response()->json([ + 'message' => $successMessage, + 'queue_name' => $queueName + ]); + } catch (Exception $e) { + Log::error('Error in migration index method: ' . $e->getMessage(), [ + 'queue_name' => $queueName, + 'error' => $e->getMessage() + ]); + return response()->json([ + 'error' => $e->getMessage(), + 'queue_name' => $queueName + ], 500); + } + } + + /** + * Tentukan periode berdasarkan input atau gunakan default + * + * @param string|null $period Input periode + * @return string Periode dalam format Ymd + */ + private function determinePeriod($period = null): string + { + if ($period === null) { + // Default: -1 day + $calculatedPeriod = date('Ymd', strtotime('-1 day')); + Log::info('Using default period', ['period' => $calculatedPeriod]); + return $calculatedPeriod; + } + + // Jika periode sudah dalam format Ymd (8 digit) + if (preg_match('/^\d{8}$/', $period)) { + Log::info('Using provided period in Ymd format', ['period' => $period]); + return $period; + } + + // Jika periode dalam format relative date (contoh: -2 days, -1 week, etc.) + try { + $calculatedPeriod = date('Ymd', strtotime($period)); + Log::info('Calculated period from relative date', [ + 'input' => $period, + 'calculated' => $calculatedPeriod + ]); + return $calculatedPeriod; + } catch (Exception $e) { + Log::warning('Invalid period format, using default', [ + 'input' => $period, + 'error' => $e->getMessage() + ]); + return date('Ymd', strtotime('-1 day')); + } + } +} diff --git a/app/Http/Controllers/WebstatementController.php b/app/Http/Controllers/WebstatementController.php index 8cd76a2..e67be10 100644 --- a/app/Http/Controllers/WebstatementController.php +++ b/app/Http/Controllers/WebstatementController.php @@ -1,204 +1,246 @@ get('queue_name', 'default'); - foreach ($this->listAccount() as $clientName => $accounts) { - foreach ($accounts as $accountNumber) { - foreach ($this->listPeriod() as $period) { - $job = new ExportStatementJob( - $accountNumber, - $period, - $this->getAccountBalance($accountNumber, $period), - $clientName // Pass the client name to the job - ); - $jobIds[] = app(Dispatcher::class)->dispatch($job); - $data[] = [ - 'client_name' => $clientName, - 'account_number' => $accountNumber, - 'period' => $period - ]; - } + Log::info('Starting statement export process', [ + 'queue_name' => $queueName + ]); + + $jobIds = []; + $data = []; + + foreach ($this->listAccount() as $clientName => $accounts) { + foreach ($accounts as $accountNumber) { + foreach ($this->listPeriod() as $period) { + $job = new ExportStatementJob( + $accountNumber, + $period, + $this->getAccountBalance($accountNumber, $period), + $clientName // Pass the client name to the job + ); + + // Dispatch job dengan queue name yang spesifik + $jobIds[] = app(Dispatcher::class)->dispatch($job->onQueue($queueName)); + $data[] = [ + 'client_name' => $clientName, + 'account_number' => $accountNumber, + 'period' => $period, + 'queue_name' => $queueName + ]; } } + } + + Log::info('Statement export jobs queued successfully', [ + 'total_jobs' => count($jobIds), + 'queue_name' => $queueName + ]); + + return response()->json([ + 'message' => 'Statement export jobs have been queued', + 'queue_name' => $queueName, + 'jobs' => array_map(function ($index, $jobId) use ($data) { + return [ + 'job_id' => $jobId, + 'client_name' => $data[$index]['client_name'], + 'account_number' => $data[$index]['account_number'], + 'period' => $data[$index]['period'], + 'queue_name' => $data[$index]['queue_name'], + 'file_name' => "{$data[$index]['client_name']}_{$data[$index]['account_number']}_{$data[$index]['period']}.csv" + ]; + }, array_keys($jobIds), $jobIds) + ]); + } + + function listAccount(){ + return [ + 'PLUANG' => [ + '1080426085', + '1080425781', + ], + 'OY' => [ + '1081647484', + '1081647485', + ], + 'INDORAYA' => [ + '1083123710', + '1083123711', + '1083123712', + '1083123713', + '1083123714', + '1083123715', + '1083123716', + '1083123718', + '1083123719', + '1083123721', + '1083123722', + '1083123723', + '1083123724', + '1083123726', + '1083123727', + '1083123728', + '1083123730', + '1083123731', + '1083123732', + '1083123734', + '1083123735', + ], + 'TDC' => [ + '1086677889', + '1086677890', + '1086677891', + '1086677892', + '1086677893', + '1086677894', + '1086677895', + '1086677896', + '1086677897', + ], + 'ASIA_PARKING' => [ + '1080119298', + '1080119361', + '1080119425', + '1080119387', + '1082208069', + ], + 'DAU' => [ + '1085151668', + ], + 'EGR' => [ + '1085368601', + ], + 'SARANA_PACTINDO' => [ + '1078333878', + ], + 'SWADAYA_PANDU' => [ + '0081272689', + ], + "AWAN_LINTANG_SOLUSI"=> [ + "1084269430" + ], + "MONETA"=> [ + "1085667890" + ] + ]; + } + + function listPeriod(){ + return [ + date('Ymd', strtotime('-1 day')) + ]; + } + + + function getAccountBalance($accountNumber, $period) + { + $accountBalance = AccountBalance::where('account_number', $accountNumber) + ->where('period', '<', $period) + ->orderBy('period', 'desc') + ->first(); + + return $accountBalance->actual_balance ?? 0; + } + + + /** + * Print statement rekening dengan queue name yang dapat dikustomisasi + * + * @param string $accountNumber + * @param string|null $period + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + function printStatementRekening($accountNumber, $period = null, Request $request = null) { + $queueName = $request ? $request->get('queue_name', 'default') : 'default'; + $period = $period ?? date('Ym'); + + $balance = AccountBalance::where('account_number', $accountNumber) + ->when($period === '202505', function($query) { + return $query->where('period', '>=', '20250512') + ->orderBy('period', 'asc'); + }, function($query) use ($period) { + // Get balance from last day of previous month + $firstDayOfMonth = Carbon::createFromFormat('Ym', $period)->startOfMonth(); + $lastDayPrevMonth = $firstDayOfMonth->copy()->subDay()->format('Ymd'); + return $query->where('period', $lastDayPrevMonth); + }) + ->first() + ->actual_balance ?? '0.00'; + $clientName = 'client1'; + + try { + Log::info("Starting statement export for account: {$accountNumber}, period: {$period}, client: {$clientName}", [ + 'account_number' => $accountNumber, + 'period' => $period, + 'client_name' => $clientName, + 'queue_name' => $queueName + ]); + + // Validate inputs + if (empty($accountNumber) || empty($period) || empty($clientName)) { + throw new \Exception('Required parameters missing'); + } + + // Dispatch the job dengan queue name yang spesifik + $job = ExportStatementPeriodJob::dispatch($accountNumber, $period, $balance, $clientName) + ->onQueue($queueName); + + Log::info("Statement export job dispatched successfully", [ + 'job_id' => $job->job_id ?? null, + 'account' => $accountNumber, + 'period' => $period, + 'client' => $clientName, + 'queue_name' => $queueName + ]); return response()->json([ - 'message' => 'Statement export jobs have been queued', - 'jobs' => array_map(function ($index, $jobId) use ($data) { - return [ - 'job_id' => $jobId, - 'client_name' => $data[$index]['client_name'], - 'account_number' => $data[$index]['account_number'], - 'period' => $data[$index]['period'], - 'file_name' => "{$data[$index]['client_name']}_{$data[$index]['account_number']}_{$data[$index]['period']}.csv" - ]; - }, array_keys($jobIds), $jobIds) + 'success' => true, + 'message' => 'Statement export job queued successfully', + 'data' => [ + 'job_id' => $job->job_id ?? null, + 'account_number' => $accountNumber, + 'period' => $period, + 'client_name' => $clientName, + 'queue_name' => $queueName + ] + ]); + + } catch (\Exception $e) { + Log::error("Failed to export statement", [ + 'error' => $e->getMessage(), + 'account' => $accountNumber, + 'period' => $period, + 'queue_name' => $queueName + ]); + + return response()->json([ + 'success' => false, + 'message' => 'Failed to queue statement export job', + 'error' => $e->getMessage(), + 'queue_name' => $queueName ]); } - - function listAccount(){ - return [ - 'PLUANG' => [ - '1080426085', - '1080425781', - ], - 'OY' => [ - '1081647484', - '1081647485', - ], - 'INDORAYA' => [ - '1083123710', - '1083123711', - '1083123712', - '1083123713', - '1083123714', - '1083123715', - '1083123716', - '1083123718', - '1083123719', - '1083123721', - '1083123722', - '1083123723', - '1083123724', - '1083123726', - '1083123727', - '1083123728', - '1083123730', - '1083123731', - '1083123732', - '1083123734', - '1083123735', - ], - 'TDC' => [ - '1086677889', - '1086677890', - '1086677891', - '1086677892', - '1086677893', - '1086677894', - '1086677895', - '1086677896', - '1086677897', - ], - 'ASIA_PARKING' => [ - '1080119298', - '1080119361', - '1080119425', - '1080119387', - '1082208069', - ], - 'DAU' => [ - '1085151668', - ], - 'EGR' => [ - '1085368601', - ], - 'SARANA_PACTINDO' => [ - '1078333878', - ], - 'SWADAYA_PANDU' => [ - '0081272689', - ], - "AWAN_LINTANG_SOLUSI"=> [ - "1084269430" - ], - "MONETA"=> [ - "1085667890" - ] - ]; - } - - function listPeriod(){ - return [ - date('Ymd', strtotime('-1 day')) - ]; - } - - - function getAccountBalance($accountNumber, $period) - { - $accountBalance = AccountBalance::where('account_number', $accountNumber) - ->where('period', '<', $period) - ->orderBy('period', 'desc') - ->first(); - - return $accountBalance->actual_balance ?? 0; - } - - - function printStatementRekening($accountNumber, $period = null) { - $period = $period ?? date('Ym'); - $balance = AccountBalance::where('account_number', $accountNumber) - ->when($period === '202505', function($query) { - return $query->where('period', '>=', '20250512') - ->orderBy('period', 'asc'); - }, function($query) use ($period) { - // Get balance from last day of previous month - $firstDayOfMonth = Carbon::createFromFormat('Ym', $period)->startOfMonth(); - $lastDayPrevMonth = $firstDayOfMonth->copy()->subDay()->format('Ymd'); - return $query->where('period', $lastDayPrevMonth); - }) - ->first() - ->actual_balance ?? '0.00'; - $clientName = 'client1'; - - try { - \Log::info("Starting statement export for account: {$accountNumber}, period: {$period}, client: {$clientName}"); - - // Validate inputs - if (empty($accountNumber) || empty($period) || empty($clientName)) { - throw new \Exception('Required parameters missing'); - } - - // Dispatch the job - $job = ExportStatementPeriodJob::dispatch($accountNumber, $period, $balance, $clientName); - - \Log::info("Statement export job dispatched successfully", [ - 'job_id' => $job->job_id ?? null, - 'account' => $accountNumber, - 'period' => $period, - 'client' => $clientName - ]); - - return response()->json([ - 'success' => true, - 'message' => 'Statement export job queued successfully', - 'data' => [ - 'job_id' => $job->job_id ?? null, - 'account_number' => $accountNumber, - 'period' => $period, - 'client_name' => $clientName - ] - ]); - - } catch (\Exception $e) { - \Log::error("Failed to export statement", [ - 'error' => $e->getMessage(), - 'account' => $accountNumber, - 'period' => $period - ]); - - return response()->json([ - 'success' => false, - 'message' => 'Failed to queue statement export job', - 'error' => $e->getMessage() - ]); - } - } } +}