initializeErrorLog(); // Path ke file csv $filePath = realpath(__DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012.csv'); if (!$filePath) { Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012.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 = 500; // Ukuran batch $userDataChace = []; $nomorRegisCahce = []; $errorCount = 0; // Inisialisasi variabel errorCount $errorDebitureIds = []; // Inisialisasi array errorDebitureIds $totalData = 0; // 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; while (($data = fgetcsv($handle, 0, ',')) !== false) { if (count($data) != count($header)) { Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data)); continue; } $rows[] = array_combine($header, $data); $currentRow++; // Jika sudah mencapai batch size, proses batch if (count($rows) >= $batchSize) { $batchCount++; $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})"); $this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow); $rows = []; } } // Proses sisa data jika ada // print_r($rows[0]); if (!empty($rows)) { $batchCount++; $this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})"); $this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow); } fclose($handle); $this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}, Total error: {$errorCount}"); } private function processBatch( array $rows, array &$userDataChace, array &$nomorRegisCahce, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow ) { $userData = []; foreach ($rows as $index => $row) { try { // Jalankan setiap baris dengan transaksi sendiri //DB::beginTransaction(); // Cek apakah sudah diproses $existingRecord = Penilaian::where('nomor_registrasi', $row['mig_nomor_registrasi'])->first(); if ($existingRecord && $existingRecord->created_at) { $this->command->info('Data sudah diproses sebelumnya: ' . $row['mig_nomor_registrasi']); //continue; } // Ambil nomor registrasi $nomor_registrasi = $this->getNomorRegistrasiPermohonan($row['mig_nomor_registrasi'], $nomorRegisCahce); if (!$nomor_registrasi) { throw new \Exception($row['mig_nomor_registrasi']."Nomor registrasi tidak valid"); } // Ambil user ID $userId = $this->getUserId($row['mig_user_id'], $userDataChace); if (!$userId) { // $this->logError($row['mig_user_id'], 'Salah satu user tidak ditemukan'); throw new \Exception($row['mig_user_id'] . " User tidak ditemukan"); continue; } $userIdUpdate = $this->getUserIdData($row['mig_created_by'] ?? null, $userData)['id']; $userIdOtorisasi = $this->getUserIdData($row['mig_authorized_by'] ?? 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, ]; // Ambil team ID $teamId = $this->checkTeams($row['mig_team_id']); if (!$teamId) { throw new \Exception("Team tidak ditemukan"); } $idPenilaian = Penilaian::orderBy('id', 'desc')->first()->id; $data = [ 'id' => $idPenilaian+1, 'nomor_registrasi' => $nomor_registrasi, 'jenis_penilaian_id' => 1, 'tanggal_kunjungan' => $this->parseTimestamp($row['mig_tanggal_kunjungan']) ?? now(), 'waktu_penilaian' => $this->parseTimestamp($row['mig_waktu_penilaian']), 'status' => 'done', 'keterangan' => null, 'created_at' => $this->parseTimestamp($row['mig_created_at']), 'updated_at' => $this->parseTimestamp($row['mig_updated_at']), 'authorized_by' => $mapUser['authorized_by'], 'created_by' => $mapUser['created_by'], 'updated_by' => $mapUser['updated_by'] ]; if($nomor_registrasi=='251722'){ Log::info("Data penilaian 251722 : ",$data); } // Buat penilaian $penilaian = Penilaian::updateOrCreate([ 'nomor_registrasi' => $nomor_registrasi ],[ 'id' => $idPenilaian+1, 'nomor_registrasi' => $nomor_registrasi, 'jenis_penilaian_id' => 1, 'tanggal_kunjungan' => $this->parseTimestamp($row['mig_tanggal_kunjungan']) ?? now(), 'waktu_penilaian' => $this->parseTimestamp($row['mig_waktu_penilaian']), 'status' => 'done', 'keterangan' => null, 'created_at' => $this->parseTimestamp($row['mig_created_at']), 'updated_at' => $this->parseTimestamp($row['mig_updated_at']), 'authorized_by' => $mapUser['authorized_by'], 'created_by' => $mapUser['created_by'], 'updated_by' => $mapUser['updated_by'], ]); //DB::commit(); // Buat tim penilaian $roles = ['surveyor', 'penilai']; foreach ($roles as $role) { $idPenilaianTeam = PenilaianTeam::orderBy('id', 'desc')->first()->id; PenilaianTeam::updateOrCreate([ 'penilaian_id' => $penilaian->id ],[ 'id' => $idPenilaianTeam+1, 'penilaian_id' => $penilaian->id, 'user_id' => $userId, 'role' => $role, 'team_id' => $teamId, 'created_at' => $this->parseTimestamp($row['mig_created_at']), 'updated_at' => $this->parseTimestamp($row['mig_updated_at']), ]); } // Commit transaksi //DB::commit(); $this->command->info('Proses data penilaian ' . $row['mig_nomor_lpj'] . ' (' . ($index + 1) . '/' . count($rows) . ')'); } catch (\Exception $e) { // Rollback jika ada error //DB::rollBack(); Log::error('Error pada baris: ' . json_encode($row) . '. Pesan: ' . $e->getMessage()); $errorCount++; $errorDebitureIds[] = $row['mig_team_id'] ?? '-'; $this->logError($row['mig_team_id'] ?? '-', $e->getMessage()); continue; } } $this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds)); } private function getNomorRegistrasiPermohonan($nomor_registrasi_id, $nomorRegisCahce) { if (isset($nomorRegisCahce[$nomor_registrasi_id])) { return $nomorRegisCahce[$nomor_registrasi_id]; } $nomorRegis = Permohonan::where('nomor_registrasi', $nomor_registrasi_id)->first(); if (!$nomorRegis) { return null; } $nomorRegisCahce[$nomor_registrasi_id] = $nomorRegis->nomor_registrasi; return $nomorRegis->nomor_registrasi; } 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($mig_user_id, $userDataChace) { if (isset($userDataChace[$mig_user_id])) { return $userDataChace[$mig_user_id]; } $userId = User::where('nik', $mig_user_id)->first(); if (!$userId) { return null; } $userDataChace[$mig_user_id] = $userId->id; return $userId->id; } private function checkTeams($code): int { $mapping = [ '01' => 1, '02' => 2, '04' => 4, '07' => 5, '06' => 3, ]; return $mapping[(string)$code] ?? 1; } 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) if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) { return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString(); } // Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43) if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) { return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString(); } } return null; } catch (\Exception $e) { Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage()); return null; } } private function initializeErrorLog() { // Jika file lama ada, hapus if (file_exists($this->errorLogFile)) { unlink($this->errorLogFile); } // Buat file baru dengan header $handle = fopen($this->errorLogFile, 'w'); fputcsv($handle, ['mig_kd_debitur_seq', 'Error']); fclose($handle); } private function logError(string $kode, string $message) { // Catat ke log Log::error("Error migrasi debiture [$kode]: $message"); // Tulis ke file error $handle = fopen($this->errorLogFile, 'a'); fputcsv($handle, [$kode, $message]); fclose($handle); } }