csvFilename = env('BIAYA_KARTU_CSV_FILENAME', 'biaya_kartu_atm.csv'); $this->periode = $periode ?? Carbon::now()->format('Y-m'); $this->syncLogId = KartuSyncLog::where('periode', $this->periode)->first(); } /** * Execute the job. */ public function handle() : void { set_time_limit(self::MAX_EXECUTION_TIME); // Load log sinkronisasi $this->syncLog = KartuSyncLog::findOrFail($this->syncLogId->id); try { // Update status CSV generation dimulai $this->updateCsvLogStart(); // Generate CSV file $result = $this->generateAtmCardCsv(); // Update status CSV generation berhasil $this->updateCsvLogSuccess($result); Log::info('Pembuatan dan upload file CSV biaya kartu ATM selesai', [ 'file' => $result['localFilePath'], 'jumlah_kartu' => $result['recordCount'], 'upload_sftp' => $result['uploadToSftp'] ? 'Berhasil' : 'Gagal', 'waktu' => $result['timestamp'] ]); if (!$result['uploadToSftp']) { Log::warning('File CSV biaya kartu ATM tidak berhasil diunggah ke SFTP, tetapi tersedia secara lokal di: ' . $result['localFilePath']); } } catch (Exception $e) { $this->updateCsvLogFailed($e->getMessage()); Log::error('Gagal membuat atau mengunggah file CSV biaya kartu ATM: ' . $e->getMessage(), [ 'file' => $e->getFile(), 'line' => $e->getLine(), 'periode' => $this->periode ]); throw $e; } } /** * Update log saat pembuatan CSV dimulai */ private function updateCsvLogStart() : void { $this->syncLog->update([ 'csv_notes' => 'Pembuatan file CSV untuk periode ' . $this->periode . ' dimulai', 'is_csv' => false, 'csv_at' => null, ]); Log::info('Memulai pembuatan file CSV untuk periode ' . $this->periode); } /** * Generate CSV file with ATM card data and upload to SFTP * * @return array Information about the generated file and upload status */ private function generateAtmCardCsv() : array { $cards = $this->getEligibleAtmCards(); //$filename = storage_path('app/' . $this->csvFilename); // Add date-time to filename $dateTime = now()->format('Ymd_Hi'); $filenameWithDate = pathinfo($this->csvFilename, PATHINFO_FILENAME) . '_' . $dateTime . '.' . pathinfo($this->csvFilename, PATHINFO_EXTENSION); $filename = storage_path('app/' . $filenameWithDate); $handle = fopen($filename, 'w+'); if (!$handle) { throw new RuntimeException("Tidak dapat membuat file CSV: $filename"); } try { foreach ($cards as $card) { $fee = $this->determineCardFee($card); $csvRow = $this->createCsvRow($card, $fee); fputcsv($handle, $csvRow, '|'); } } finally { fclose($handle); } $this->cleanupCsvFile($filename); // Upload file ke SFTP $uploadSuccess = $this->uploadToSftpKartu($filename); return [ 'localFilePath' => $filename, 'recordCount' => count($cards), 'uploadToSftp' => $uploadSuccess, 'timestamp' => now()->format('Y-m-d H:i:s') ]; } /** * Get eligible ATM cards from database * * @return \Illuminate\Database\Eloquent\Collection */ private function getEligibleAtmCards() { $cardTypes = array_keys($this->getDefaultFees()); return Atmcard::where('crsts', 1) ->whereNotNull('accflag') ->where('accflag', '!=', '') ->whereNotNull('branch') ->where('branch', '!=', '') ->whereNotNull('currency') ->where('currency', '!=', '') ->whereIn('ctdesc', $cardTypes) ->get(); } /** * Get default fees from JenisKartu table * * @return array */ private function getDefaultFees() : array { return JenisKartu::getDefaultFees(); } /** * Determine fee for a card based on its type * * @param Atmcard $card * * @return int */ private function determineCardFee(Atmcard $card) : int { if ($card->fee) { return $card->fee; } $defaultFees = $this->getDefaultFees(); return $defaultFees[$card->ctdesc] ?? 0; } /** * Create CSV row data for a card * * @param Atmcard $card * @param int $fee * * @return array */ private function createCsvRow(Atmcard $card, int $fee) : array { $today = date('Ymd'); return [ '', $card->accflag, $card->currency ?? 'IDR', $fee, 'PL65129', '', '', $card->branch, $today, $today, '', '', 'ADMIN FEE ATM::' . $card->crdno . '::' . $today, '', '', '', '', '', '', 'ACAT' ]; } /** * Remove double quotes from CSV file * * @param string $filename * * @return void */ private function cleanupCsvFile(string $filename) : void { $fileContent = file_get_contents($filename); if ($fileContent === false) { throw new RuntimeException("Tidak dapat membaca file CSV: $filename"); } $fileContent = str_replace('"', '', $fileContent); if (file_put_contents($filename, $fileContent) === false) { throw new RuntimeException("Tidak dapat menulis ke file CSV: $filename"); } } /** * Upload the generated CSV file to SFTP server * * @param string $localFilePath Path to the local CSV file * * @return bool True if upload successful, false otherwise */ private function uploadToSftpKartu(string $localFilePath) : bool { try { // Update status SFTP upload dimulai $this->updateSftpLogStart(); // Ambil nama file dari path $filename = basename($localFilePath); // Ambil konten file $fileContent = file_get_contents($localFilePath); if ($fileContent === false) { Log::error("Tidak dapat membaca file untuk upload: {$localFilePath}"); return false; } // Dapatkan disk SFTP $disk = Storage::disk('sftpKartu'); // Tentukan path tujuan di server SFTP $remotePath = env('BIAYA_KARTU_REMOTE_PATH', '/'); $remoteFilePath = rtrim($remotePath, '/') . '/' . $filename; // Upload file ke server SFTP $result = $disk->put($remoteFilePath, $fileContent); if ($result) { $this->updateSftpLogSuccess(); Log::info("File CSV biaya kartu ATM berhasil diunggah ke SFTP: {$remoteFilePath}"); return true; } else { $this->updateSftpLogFailed("Gagal mengunggah file CSV biaya kartu ATM ke SFTP: {$remoteFilePath}"); Log::error("Gagal mengunggah file CSV biaya kartu ATM ke SFTP: {$remoteFilePath}"); return false; } } catch (Exception $e) { $this->updateSftpLogFailed($e->getMessage()); Log::error("Error saat mengunggah file ke SFTP: " . $e->getMessage(), [ 'file' => $e->getFile(), 'line' => $e->getLine(), 'periode' => $this->periode ]); return false; } } /** * Update log saat upload SFTP dimulai */ private function updateSftpLogStart() : void { $this->syncLog->update([ 'ftp_notes' => 'Upload ke SFTP untuk file periode ' . $this->periode . ' dimulai', 'is_ftp' => false, 'ftp_at' => null, ]); Log::info('Memulai upload ke SFTP untuk periode ' . $this->periode); } /** * Update log saat upload SFTP berhasil */ private function updateSftpLogSuccess() : void { $this->syncLog->update([ 'is_ftp' => true, 'ftp_at' => Carbon::now(), 'ftp_notes' => 'File berhasil diupload ke SFTP', 'ftp_destination' => env('SFTP_KARTU_HOST', '/'), ]); Log::info('File berhasil diupload ke SFTP untuk periode ' . $this->periode); } /** * Update log saat upload SFTP gagal */ private function updateSftpLogFailed($errorMessage) : void { $this->syncLog->update([ 'is_ftp' => false, 'ftp_notes' => 'Upload ke SFTP gagal: ' . $errorMessage ]); Log::error('Upload ke SFTP gagal: ' . $errorMessage); } /** * Update log saat pembuatan CSV berhasil */ private function updateCsvLogSuccess($result) : void { // Get file info $fileInfo = pathinfo($result['localFilePath']); $fileName = $fileInfo['basename']; $this->syncLog->update([ 'is_csv' => true, 'csv_at' => Carbon::now(), 'csv_notes' => 'File CSV berhasil dibuat: ' . $fileName, 'file_path' => $result['localFilePath'], 'file_name' => $fileName, ]); Log::info('File CSV berhasil dibuat: ' . $result['localFilePath']); } /** * Update log saat pembuatan CSV gagal */ private function updateCsvLogFailed($errorMessage) : void { $this->syncLog->update([ 'is_csv' => false, 'csv_notes' => 'Pembuatan file CSV gagal: ' . $errorMessage ]); Log::error('Pembuatan file CSV gagal: ' . $errorMessage); } }