initializeErrorLog(); $filePath = realpath(__DIR__ . '/csv/permohonan/mig_permohonan.csv'); if (!$filePath) { Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/permohonan/mig_permohonan.csv'); $this->command->error('File CSV tidak ditemukan.'); return; } if (($handle = fopen($filePath, 'r')) === false) { Log::error('Gagal membuka file CSV: ' . $filePath); $this->command->error('Gagal membuka file CSV.'); return; } $header = fgetcsv($handle, 0, '~'); $rows = []; $batchSize = 1000; $branchCache = []; $debitureCache = []; $totalData = 0; $currentRow = 0; $batchCount = 0; // Hitung total data while (fgetcsv($handle, 0, '~') !== false) { $totalData++; } rewind($handle); fgetcsv($handle, 0, '~'); // Lewati header while (($data = fgetcsv($handle, 0, '~')) !== false) { if (count($data) != count($header)) { $nomorJaminan = $data[array_search('mig_mst_jaminan_nomor_jaminan', $header)] ?? '-'; $this->logError($nomorJaminan, 'Jumlah kolom tidak sesuai'); continue; } $rows[] = array_combine($header, $data); $currentRow++; if (count($rows) >= $batchSize) { $batchCount++; $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})"); $this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount); $rows = []; } } print_r($rows[0]); if (!empty($rows)) { $batchCount++; $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})"); $this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount); } fclose($handle); $this->command->info("Migrasi selesai. Total data diproses: $totalData."); } private function processBatch(array $rows, array &$branchCache, array &$debitureCache, int $totalData, int $batchCount) { $userData = []; foreach ($rows as $index => $row) { try { $nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-'; // Cek apakah sudah diproses $existingRecord = Permohonan::where('nomor_registrasi', $row['mig_mst_jaminan_nomor_jaminan'])->first(); if ($existingRecord && $existingRecord->processed_at) { $this->command->info("Data sudah diproses: $nomorJaminan"); continue; } // Ambil branch_id $branchId = $this->getBranchId($row['mig_mst_jaminan_kd_cabang'] ?? null, $branchCache); if (!$branchId) { $this->logError($branchId, 'Cabang tidak ditemukan'); continue; } // Ambil Debitur ID $debitureId = $this->getDebiturId($row['mig_mst_jaminan_kd_debitur_seq'], $debitureCache); if (!$debitureId) { $this->logError($nomorJaminan, 'Debitur tidak ditemukan'); continue; } // Ambil User IDs $userId = $this->getUserId($row['mig_mst_jaminan_nama_ao'], $branchCache, true); $approved1Id = $this->getUserId($row['mig_mst_lpj_user_approved_1'], $branchCache, false); $approved2Id = $this->getUserId($row['mig_mst_lpj_user_approved_2'], $branchCache, false); // Ambil user IDs berdasarkan NIK $userIdUpdate = $this->getUserIdData($row['mig_mst_jaminan_user_create'] ?? null, $userData)['id']; $userIdOtorisasi = $this->getUserIdData($row['mig_mst_jaminan_user_oto'] ?? null, $userData)['id']; if (!$userIdUpdate || !$userIdOtorisasi) { $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan'); continue; } // Mapping field user $mapUser = [ 'created_by' => $userIdUpdate, 'updated_by' => $userIdUpdate, 'authorized_by' => $userIdOtorisasi, ]; if (!$userId || !$approved1Id || !$approved2Id) { $this->logError($userId, 'Salah satu user tidak ditemukan'); continue; } // Mapping data $jenisFasilitas = $this->checkJenisFasilitas($row['mig_mst_jaminan_kd_jenis_fas_seq']); $tujuanPenilaian = $this->checkTujuanPenilaian($row['mig_mst_jaminan_kd_tujuan_seq']); $regionId = $this->checkRegion($row['mig_mst_kode_kelompok_region']); // Simpan data Permohonan::create([ 'nomor_registrasi' => $nomorJaminan, 'tanggal_permohonan' => $this->parseDate($row['tanggal_permohonan']), 'user_id' => $userId['id'], 'branch_id' => $branchId, 'tujuan_penilaian_id' => $tujuanPenilaian, 'debiture_id' => $debitureId, 'jenis_fasilitas_kredit_id' => $jenisFasilitas, 'nilai_plafond_id' => 2, 'status' => 'done', 'approval_eo' => $approved2Id['id'] ?? 0, 'approval_eo_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_2']), 'approval_dd' => 0, 'approval_dd_at' => null, 'approval_so' => $approved1Id['id'] ?? 0, 'approval_so_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_1']), 'keterangan' => $row['mig_mst_jaminan_catatan'] ?? null, 'status_bayar' => 'sudah_bayar', 'created_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_create']), 'updated_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_update']), 'mig_kd_debitur_seq' => $row['mig_mst_jaminan_kd_debitur_seq'], 'nomor_lpj' => $row['mig_mst_lpj_nomor_lpj'], 'region_id' => $regionId, 'authorized_by' => $mapUser['authorized_by'], 'created_by' => $mapUser['created_by'], 'updated_by' => $mapUser['updated_by'], 'processed_at' => now(), 'is_mig' => 1 ]); $this->command->info("Proses data permohonan $nomorJaminan (" . ($index + 1) . '/' . count($rows) . " pada batch ke-$batchCount)"); } catch (\Exception $e) { $nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-'; $this->logError($nomorJaminan, "Error eksepsi: " . $e->getMessage()); continue; } } } private function getUserIdData(?string $code, array &$cache): array { if (!$code) return ['id' => null, 'branch_id' => null]; if (isset($cache[$code])) { return $cache[$code]; } $user = User::where('nik', $code)->first(); if ($user) { $cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id]; return $cache[$code]; } return ['id' => null, 'branch_id' => null]; } private function getUserId(string $value, array &$cache, bool $includeBranch = false): ?array { if (isset($cache[$value])) { return $cache[$value]; } $user = null; if ($includeBranch) { $user = User::whereRaw('LOWER(name) = ?', [strtolower($value)])->first(); } else { $user = User::where('nik', $value)->first(); } if ($user) { $result = ['id' => $user->id]; if ($includeBranch) { $result['branch_id'] = $user->branch_id; } $cache[$value] = $result; return $result; } return ['id' => null, 'branch_id' => null]; } private function getDebiturId(string $code, array &$cache): ?int { if (isset($cache[$code])) { return $cache[$code]; } $debitur = Debiture::where('mig_kd_debitur_seq', $code)->first(); if ($debitur) { $cache[$code] = $debitur->id; return $debitur->id; } return null; } private function getBranchId(?string $code, array &$cache): ?int { if (!$code) return null; if (isset($cache[$code])) { return $cache[$code]; } $branch = Branch::where('code', $code)->first(); if ($branch) { $cache[$code] = $branch->id; return $branch->id; } return null; } private function checkJenisFasilitas($code): int { $mapping = [ 161337594516 => 1, 161337598118 => 2, 155739382483 => 7, 2 => 9, 153568936592 => 10, 155737674431 => 11, 161337561199 => 12, 1 => 13, ]; return $mapping[$code] ?? 0; } private function checkTujuanPenilaian($code): int { $mapping = [ 1 => 1, 2 => 2, 3 => 9, 4 => 10, 5 => 8, 6 => 3, ]; return $mapping[$code] ?? 1; } private function checkRegion($code): int { $mapping = [ '01' => 1, '02' => 2, '04' => 3, '07' => 4, '06' => 5, ]; return $mapping[$code] ?? 1; } private function parseDate(?string $date): ?string { try { return $date ? \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString() : null; } catch (\Exception $e) { return null; } } private function parseTimestamp(?string $timestamp): ?string { try { if ($timestamp) { // Cek jika format hanya tanggal (Y-m-d) if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) { return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp) ->startOfDay() ->toDateTimeString(); } // Format lengkap (Y-m-d H:i:s) return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString(); } return null; } catch (\Exception $e) { Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage()); return null; } } private function initializeErrorLog() { $file = $this->errorLogFile; // Hapus file lama jika ada if (file_exists($file)) { unlink($file); } // Buat file baru dengan header $handle = fopen($file, 'w'); fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']); fclose($handle); } private function logError( $nomorJaminan, string $message) { Log::error("Error migrasi permohonan [$nomorJaminan]: $message"); // Tulis ke file error $handle = fopen($this->errorLogFile, 'a'); fputcsv($handle, [$nomorJaminan, $message]); fclose($handle); } }