initializeErrorLog(); // Path ke file csv $filePath = realpath(__DIR__ . '/csv/detail-dokumen/mig_detail_dokument_external.csv'); if (!$filePath) { Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/detail-dokumen/mig_detail_dokument_external.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; // Ukuran batch $permohonanCache = []; $jenisJaminanCache = []; $dokumenJaminanCache = []; $provinceCache = []; $cityCache = []; $districtCache = []; $subdistrictCache = []; $totalData = 0; $errorCount = 0; $errorDebitureIds = []; $hubunganPemilikCache = []; // Menghitung total data di file CSV while (($data = fgetcsv($handle, 0, '~')) !== false) { $totalData++; } rewind($handle); // Reset pointer ke awal file fgetcsv($handle, 0, '~'); // Skip header $batchCount = 0; $currentRow = 0; // Membaca setiap baris dalam CSV while (($data = fgetcsv($handle, 0, '~')) !== false) { if (count($data) != count($header)) { Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data)); $errorCount++; $errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error continue; } $rows[] = array_combine($header, $data); $currentRow++; // print_r($rows); if (count($rows) >= $batchSize) { $errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error $this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds); $rows = []; } } // print_r($rows[0]); if (!empty($rows)) { $this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds); } fclose($handle); $this->command->info('Data debiture berhasil dimigrasikan.'); } private function processBatch( array $rows, array &$permohonanCache, array &$jenisJaminanCache, array &$dokumenJaminanCache, int $batchCount, int $currentRow, int $totalData, int &$errorCount, array &$errorDebitureIds ) { $groupedRows = $this->groupRowsByNomorLaporanAndKeterangan($rows); // print_r($groupedRows); foreach ($groupedRows as $nomorLaporan => $dataPerGrup) { // print_r($dataPerGrup); try { // Ambil salah satu baris untuk referensi (misal baris pertama dari grup) $firstRow = reset($dataPerGrup)['details'] ? reset($dataPerGrup) : reset($dataPerGrup); $debiturId = null; // Cari debitur ID dari salah satu field foreach ($rows as $row) { if ($row['mig_nomor_laporan'] == $nomorLaporan) { $debiturId = $row['mig_kd_debitur_seq'] ?? null; break; } } if (!$debiturId) { throw new \Exception('Debitur ID tidak ditemukan'); } // Ambil ID dokumen jaminan $dokumenJaminanId = $this->getDokumenJaminanId($debiturId, $dokumenJaminanCache); if (!$dokumenJaminanId) { throw new \Exception('Dokumen jaminan tidak ditemukan'); } foreach ($dataPerGrup as $groupKey => $rowData) { // Ambil legalitas jaminan ID berdasarkan grup keterangan $legalitasJaminanId = $this->getLegalitasJaminanId($groupKey, $jenisJaminanCache); if (!$legalitasJaminanId) { throw new \Exception("Legalitas jaminan tidak ditemukan untuk grup: {$groupKey}"); } // Simpan ke database DetailDokumenJaminan::updateOrCreate( [ 'name' => $groupKey, 'dokumen_jaminan_id' => $dokumenJaminanId, ], [ 'details' => json_encode($rowData['details']), 'jenis_legalitas_jaminan_id' => $legalitasJaminanId, 'dokumen_jaminan' => !empty($rowData['documents']) ? json_encode($rowData['documents']) : null, 'dokumen_nomor' => $nomorLaporan, 'keterangan' => $groupKey, ] ); } // Info progress $this->command->info("Proses data detail dokumen (Nomor Laporan: {$nomorLaporan}, batch ke: {$batchCount}, total dari: {$currentRow}/{$totalData})"); } catch (\Exception $e) { Log::error("Error pada nomor laporan {$nomorLaporan}: " . $e->getMessage()); $this->logError($debiturId ?? '-', $e->getMessage()); $errorDebitureIds[] = $debiturId ?? '-'; $errorCount++; } } } private function groupRowsByNomorLaporann(array $rows): array { $grouped = []; foreach ($rows as $row) { $nomorJaminan = $row['mig_nomor_laporan'] ?? null; if (!empty($nomorJaminan)) { $grouped[$nomorJaminan][] = $row; } } return $grouped; } // private function groupRowsByNomorLaporanAndKeterangan(array $rows): array // { // $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows); // $finalGrouped = []; // foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) { // $groupedByGrpKeterangan = []; // // Urutkan berdasarkan mig_urutan_sub (ascending) // usort($rowList, function ($a, $b) { // return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub']; // }); // foreach ($rowList as $row) { // $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP'; // if (!isset($groupedByGrpKeterangan[$grpKeterangan])) { // $groupedByGrpKeterangan[$grpKeterangan] = [ // 'details' => [], // 'documents' => [] // ]; // } // $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY'; // $value = $row['mig_nilai'] ?? null; // // Jika belum ada detail, inisialisasi sebagai array asosiatif // if (empty($groupedByGrpKeterangan[$grpKeterangan]['details'])) { // $groupedByGrpKeterangan[$grpKeterangan]['details'][] = []; // } // // Masukkan ke dalam object tunggal (bukan item baru) // if ($value !== null) { // $lastIndex = count($groupedByGrpKeterangan[$grpKeterangan]['details']) - 1; // $groupedByGrpKeterangan[$grpKeterangan]['details'][$lastIndex][$keyKeterangan] = $value; // } // // Tambahkan dokumen jika ada // $urlFile = $row['mig_url_file'] ?? null; // if (!empty($urlFile)) { // $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile; // } // } // $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan; // } // // print_r($finalGrouped); // return $finalGrouped; // } private function groupRowsByNomorLaporanAndKeterangan(array $rows): array { $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows); $finalGrouped = []; foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) { $groupedByGrpKeterangan = []; // Urutkan berdasarkan mig_urutan_sub usort($rowList, function ($a, $b) { return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub']; }); foreach ($rowList as $row) { $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP'; $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY'; $value = $row['mig_nilai'] ?? null; if (!isset($groupedByGrpKeterangan[$grpKeterangan])) { $groupedByGrpKeterangan[$grpKeterangan] = [ 'details' => [], 'documents' => [] ]; } // Masukkan sebagai object baru ke dalam details if ($value !== null) { $groupedByGrpKeterangan[$grpKeterangan]['details'][] = [ $keyKeterangan => $value ]; } // Dokumen tetap masuk sebagai array string $urlFile = $row['mig_url_file'] ?? null; if (!empty($urlFile)) { $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile; } } $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan; } return $finalGrouped; } private function getDokumenJaminanId(string $code, array &$dokumenJaminanCache) { if (isset($dokumenJaminanCache[$code])) { return $dokumenJaminanCache[$code]; } $dokumen = DokumenJaminan::where('mig_kd_debitur_seq', $code)->first(); if ($dokumen) { $dokumenJaminanCache[$code] = $dokumen->id; return $dokumen->id; } } private function getLegalitasJaminanId(string $code, array &$legalitasJaminanCache) { if (isset($legalitasJaminanCache[$code])) { return $legalitasJaminanCache[$code]; } $legalitas = JenisLegalitasJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first(); if ($legalitas) { $legalitasJaminanCache[$code] = $legalitas->id; return $legalitas->id; } return null; } private function initializeErrorLog() { $file = $this->errorLogFile; if (file_exists($file)) { unlink($file); // Hapus file lama } $handle = fopen($file, 'w'); fputcsv($handle, ['mig_kd_debitur_seq', 'Error']); fclose($handle); } private function logError(string $kode, string $message) { Log::error("Error migrasi dokumen jaminan [$kode]: $message"); $handle = fopen($this->errorLogFile, 'a'); fputcsv($handle, [$kode, $message]); fclose($handle); } }