DB::table('comuni_italiani')->count(), 'last_import' => DB::table('import_logs') ->where('tipo', 'comuni_italiani') ->latest() ->value('created_at'), 'storage_size' => $this->getArchiveStorageSize(), 'available_archives' => $this->getAvailableArchives() ]; return view('superadmin.archivi.index', compact('stats')); } /** * Gestione archivio comuni italiani */ public function comuniItaliani(Request $request) { $query = DB::table('comuni_italiani'); // Filtri di ricerca if ($request->filled('search_nome')) { $query->where('denominazione', 'like', '%' . $request->search_nome . '%'); } if ($request->filled('search_provincia')) { $query->where('provincia_codice', 'like', '%' . $request->search_provincia . '%'); } if ($request->filled('search_regione')) { $query->where('regione_denominazione', 'like', '%' . $request->search_regione . '%'); } if ($request->filled('search_cap')) { $query->where('cap', 'like', '%' . $request->search_cap . '%'); } // Export CSV if ($request->get('export') === 'csv') { return $this->exportComuniCSV($query); } $comuni = $query->orderBy('denominazione')->paginate(50); return view('superadmin.archivi.comuni', compact('comuni')); } /** * Export comuni in formato CSV */ private function exportComuniCSV($query) { $comuni = $query->get(); $filename = 'comuni_italiani_' . date('Y-m-d_H-i') . '.csv'; $headers = [ 'Content-Type' => 'text/csv', 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]; $callback = function() use ($comuni) { $file = fopen('php://output', 'w'); // Header CSV fputcsv($file, [ 'Codice ISTAT', 'Denominazione', 'Denominazione Straniera', 'Codice Catastale', 'CAP', 'Provincia Codice', 'Provincia Denominazione', 'Regione Codice', 'Regione Denominazione' ], ';'); // Dati foreach ($comuni as $comune) { fputcsv($file, [ $comune->codice_istat, $comune->denominazione, $comune->denominazione_straniera, $comune->codice_catastale, $comune->cap, $comune->provincia_codice, $comune->provincia_denominazione, $comune->regione_codice, $comune->regione_denominazione ], ';'); } fclose($file); }; return response()->stream($callback, 200, $headers); } /** * Import ZIP con dati JSON */ public function importZip(Request $request) { $request->validate([ 'zip_file' => 'required|file|mimes:zip|max:51200', // 50MB max 'tipo_archivio' => 'required|string|in:comuni_italiani,province,regioni' ]); try { $zipFile = $request->file('zip_file'); $tipoArchivio = $request->input('tipo_archivio'); // Salva il file ZIP temporaneamente $zipPath = $zipFile->storeAs('temp', 'import_' . time() . '.zip'); $fullZipPath = storage_path('app/' . $zipPath); // Estrai e processa il ZIP $result = $this->processZipImport($fullZipPath, $tipoArchivio); // Cancella il file ZIP dopo l'importazione Storage::delete($zipPath); // Log dell'operazione DB::table('import_logs')->insert([ 'tipo' => $tipoArchivio, 'file_originale' => $zipFile->getClientOriginalName(), 'records_importati' => $result['imported'], 'errori' => $result['errors'], 'user_id' => auth()->id(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]); return response()->json([ 'success' => true, 'message' => "Importazione completata. {$result['imported']} record importati.", 'data' => $result ]); } catch (\Exception $e) { Log::error('Errore import ZIP: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Errore durante l\'importazione: ' . $e->getMessage() ], 500); } } /** * Processa il file ZIP e importa i dati */ private function processZipImport($zipPath, $tipo) { $zip = new ZipArchive; $imported = 0; $errors = []; if ($zip->open($zipPath) === TRUE) { // Estrai in una cartella temporanea $extractPath = storage_path('app/temp/extract_' . time()); $zip->extractTo($extractPath); $zip->close(); // Cerca file JSON nella cartella estratta $jsonFiles = glob($extractPath . '/*.json'); foreach ($jsonFiles as $jsonFile) { $jsonData = json_decode(file_get_contents($jsonFile), true); if ($jsonData) { $result = $this->importJsonData($jsonData, $tipo); $imported += $result['imported']; $errors = array_merge($errors, $result['errors']); } } // Pulisci la cartella estratta $this->deleteDirectory($extractPath); } else { throw new \Exception('Impossibile aprire il file ZIP'); } return [ 'imported' => $imported, 'errors' => $errors ]; } /** * Importa i dati JSON nel database */ private function importJsonData($data, $tipo) { $imported = 0; $errors = []; DB::beginTransaction(); try { switch ($tipo) { case 'comuni_italiani': $imported = $this->importComuniItaliani($data); break; case 'province': $imported = $this->importProvince($data); break; case 'regioni': $imported = $this->importRegioni($data); break; default: throw new \Exception("Tipo archivio non supportato: {$tipo}"); } DB::commit(); } catch (\Exception $e) { DB::rollBack(); $errors[] = $e->getMessage(); } return [ 'imported' => $imported, 'errors' => $errors ]; } /** * Importa i comuni italiani */ private function importComuniItaliani($data) { // Se necessario, svuota la tabella esistente DB::table('comuni_italiani')->truncate(); $imported = 0; $chunk = []; foreach ($data as $record) { $chunk[] = [ 'codice_istat' => $record['codice_istat'] ?? null, 'denominazione' => $record['denominazione'] ?? null, 'denominazione_straniera' => $record['denominazione_straniera'] ?? null, 'codice_catastale' => $record['codice_catastale'] ?? null, 'cap' => $record['cap'] ?? null, 'provincia_codice' => $record['provincia_codice'] ?? null, 'provincia_denominazione' => $record['provincia_denominazione'] ?? null, 'regione_codice' => $record['regione_codice'] ?? null, 'regione_denominazione' => $record['regione_denominazione'] ?? null, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; // Inserisci a blocchi di 500 record if (count($chunk) >= 500) { DB::table('comuni_italiani')->insert($chunk); $imported += count($chunk); $chunk = []; } } // Inserisci il resto if (!empty($chunk)) { DB::table('comuni_italiani')->insert($chunk); $imported += count($chunk); } return $imported; } /** * Importa le province */ private function importProvince($data) { DB::table('province')->truncate(); $imported = 0; foreach ($data as $record) { DB::table('province')->insert([ 'codice' => $record['codice'] ?? null, 'denominazione' => $record['denominazione'] ?? null, 'sigla' => $record['sigla'] ?? null, 'regione_codice' => $record['regione_codice'] ?? null, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]); $imported++; } return $imported; } /** * Importa le regioni */ private function importRegioni($data) { DB::table('regioni')->truncate(); $imported = 0; foreach ($data as $record) { DB::table('regioni')->insert([ 'codice' => $record['codice'] ?? null, 'denominazione' => $record['denominazione'] ?? null, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]); $imported++; } return $imported; } /** * Calcola la dimensione dello storage archivi */ private function getArchiveStorageSize() { $size = 0; $directories = ['archives', 'temp']; foreach ($directories as $dir) { $path = storage_path("app/{$dir}"); if (is_dir($path)) { $size += $this->getDirectorySize($path); } } return $this->formatBytes($size); } /** * Ottiene gli archivi disponibili */ private function getAvailableArchives() { return [ 'comuni_italiani' => [ 'nome' => 'Comuni Italiani', 'descrizione' => 'Archivio completo dei comuni italiani con codici ISTAT', 'ultima_sincronizzazione' => DB::table('import_logs') ->where('tipo', 'comuni_italiani') ->latest() ->value('created_at') ], 'province' => [ 'nome' => 'Province Italiane', 'descrizione' => 'Elenco delle province italiane', 'ultima_sincronizzazione' => null ], 'regioni' => [ 'nome' => 'Regioni Italiane', 'descrizione' => 'Elenco delle regioni italiane', 'ultima_sincronizzazione' => null ] ]; } /** * Cancella ricorsivamente una directory */ private function deleteDirectory($dir) { if (!is_dir($dir)) return; $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { $path = $dir . DIRECTORY_SEPARATOR . $file; is_dir($path) ? $this->deleteDirectory($path) : unlink($path); } rmdir($dir); } /** * Calcola la dimensione di una directory */ private function getDirectorySize($path) { $size = 0; if (is_dir($path)) { $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS) ); foreach ($iterator as $file) { $size += $file->getSize(); } } return $size; } /** * Formatta i byte in formato leggibile */ private function formatBytes($size, $precision = 2) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; for ($i = 0; $size > 1024 && $i < count($units) - 1; $i++) { $size /= 1024; } return round($size, $precision) . ' ' . $units[$i]; } /** * Sincronizzazione futura con ISTAT */ public function sincronizzaIstat() { // Placeholder per sincronizzazione automatica con ISTAT return response()->json([ 'success' => false, 'message' => 'Sincronizzazione automatica con ISTAT in sviluppo' ]); } }