argument('file') ?? 'public/templates/Data_2025___Estimasi_Jumlah_Lantai.csv'; $fullPath = storage_path('app/' . $filePath); // Check if file exists if (!file_exists($fullPath)) { $this->error("File not found: {$fullPath}"); $this->info("Available files in templates:"); $this->listAvailableFiles(); return 1; } // Confirm truncate if requested if ($this->option('truncate')) { if ($this->confirm('This will delete all existing spatial planning data. Continue?')) { $this->info('Truncating spatial_plannings table...'); DB::table('spatial_plannings')->truncate(); $this->info('Table truncated successfully.'); } else { $this->info('Operation cancelled.'); return 0; } } $this->info("Starting import from: {$filePath}"); $this->info("Full path: {$fullPath}"); try { DB::beginTransaction(); $data = Excel::toArray([], $fullPath); if (empty($data) || empty($data[0])) { $this->error('No data found in the file.'); return 1; } $rows = $data[0]; // Get first sheet $headers = array_shift($rows); // Remove header row $this->info("Found " . count($rows) . " data rows to import."); $this->info("Headers: " . implode(', ', $headers)); $progressBar = $this->output->createProgressBar(count($rows)); $progressBar->start(); $imported = 0; $skipped = 0; foreach ($rows as $index => $row) { try { // Skip empty rows if (empty(array_filter($row))) { $skipped++; $progressBar->advance(); continue; } // Map CSV columns to model attributes $spatialData = [ 'name' => $this->cleanString($row[1] ?? ''), // pemohon 'location' => $this->cleanString($row[2] ?? ''), // alamat 'activities' => $this->cleanString($row[3] ?? ''), // activities 'land_area' => $this->cleanNumber($row[4] ?? 0), // luas_lahan 'site_bcr' => $this->cleanNumber($row[5] ?? 0), // bcr_kawasan 'area' => $this->cleanNumber($row[6] ?? 0), // area 'no_tapak' => $this->cleanString($row[7] ?? ''), // no_tapak 'no_skkl' => $this->cleanString($row[8] ?? ''), // no_skkl 'no_ukl' => $this->cleanString($row[9] ?? ''), // no_ukl 'building_function' => $this->cleanString($row[10] ?? ''), // fungsi_bangunan 'sub_building_function' => $this->cleanString($row[11] ?? ''), // sub_fungsi_bangunan 'number_of_floors' => $this->cleanNumber($row[12] ?? 1), // jumlah_lantai 'number' => $this->cleanString($row[0] ?? ''), // no 'date' => now(), // Set current date 'kbli' => null, // Not in CSV, set as null ]; // Validate required fields if (empty($spatialData['name']) && empty($spatialData['activities'])) { $skipped++; $progressBar->advance(); continue; } SpatialPlanning::create($spatialData); $imported++; } catch (Exception $e) { $this->newLine(); $this->error("Error importing row " . ($index + 2) . ": " . $e->getMessage()); $skipped++; } $progressBar->advance(); } $progressBar->finish(); $this->newLine(2); DB::commit(); $this->info("Import completed successfully!"); $this->info("Imported: {$imported} records"); $this->info("Skipped: {$skipped} records"); return 0; } catch (Exception $e) { DB::rollBack(); $this->error("Import failed: " . $e->getMessage()); return 1; } } /** * Clean string data */ private function cleanString($value) { if (is_null($value)) return null; return trim(str_replace(["\n", "\r", "\t"], ' ', $value)); } /** * Clean numeric data */ private function cleanNumber($value) { if (is_null($value) || $value === '') return 0; // Remove non-numeric characters except decimal point $cleaned = preg_replace('/[^0-9.]/', '', $value); return is_numeric($cleaned) ? (float) $cleaned : 0; } /** * List available template files */ private function listAvailableFiles() { $templatesPath = storage_path('app/public/templates'); if (is_dir($templatesPath)) { $files = glob($templatesPath . '/*.{csv,xlsx,xls}', GLOB_BRACE); foreach ($files as $file) { $this->line(' - ' . basename($file)); } } $publicTemplatesPath = public_path('templates'); if (is_dir($publicTemplatesPath)) { $this->info("Files in public/templates:"); $files = glob($publicTemplatesPath . '/*.{csv,xlsx,xls}', GLOB_BRACE); foreach ($files as $file) { $this->line(' - ' . basename($file)); } } } }