validate([ 'documenti.*' => 'required|file|max:10240|mimes:pdf,doc,docx,xls,xlsx,jpg,jpeg,png,gif', 'categoria_documento' => 'required|string|in:' . implode(',', array_keys(DocumentoStabile::categorie())) ]); $documentiCaricati = []; $errori = []; if ($request->hasFile('documenti')) { foreach ($request->file('documenti') as $file) { try { // Genera nome unico per il file $nomeOriginale = $file->getClientOriginalName(); $estensione = $file->getClientOriginalExtension(); $nomeFile = Str::slug(pathinfo($nomeOriginale, PATHINFO_FILENAME)) . '_' . time() . '.' . $estensione; // Percorso di salvataggio: documenti/stabili/{stabile_id}/ $percorso = "documenti/stabili/{$stabile->id}"; $percorsoCompleto = $file->storeAs($percorso, $nomeFile, 'public'); // Crea record nel database $documento = DocumentoStabile::create([ 'stabile_id' => $stabile->id, 'nome_file' => $nomeFile, 'nome_originale' => $nomeOriginale, 'percorso_file' => $percorsoCompleto, 'categoria' => $request->categoria_documento, 'tipo_mime' => $file->getMimeType(), 'dimensione' => $file->getSize(), 'descrizione' => $request->descrizione_documento, 'data_scadenza' => $request->data_scadenza_documento, 'tags' => $request->tags_documento, 'pubblico' => $request->has('pubblico_documento'), 'caricato_da' => Auth::id() ]); $documentiCaricati[] = $documento; } catch (\Exception $e) { $errori[] = "Errore nel caricamento di {$nomeOriginale}: " . $e->getMessage(); } } } if (count($documentiCaricati) > 0) { return response()->json([ 'success' => true, 'message' => count($documentiCaricati) . ' documento/i caricato/i con successo', 'documenti' => $documentiCaricati, 'errori' => $errori ]); } else { return response()->json([ 'success' => false, 'message' => 'Nessun documento caricato', 'errori' => $errori ], 400); } } /** * Lista documenti di uno stabile */ public function index(Stabile $stabile) { $documenti = $stabile->documenti() ->with('caricatore') ->orderBy('created_at', 'desc') ->get(); return response()->json([ 'success' => true, 'documenti' => $documenti ]); } /** * Download di un documento */ public function download(DocumentoStabile $documento) { if (!$documento->fileEsiste()) { abort(404, 'File non trovato'); } // Incrementa contatore download $documento->incrementaDownload(); return Storage::disk('public')->download( $documento->percorso_file, $documento->nome_originale ); } /** * Visualizza un documento nel browser */ public function view(DocumentoStabile $documento) { if (!$documento->fileEsiste()) { abort(404, 'File non trovato'); } // Incrementa contatore accessi $documento->update(['ultimo_accesso' => now()]); $path = Storage::disk('public')->path($documento->percorso_file); return response()->file($path, [ 'Content-Type' => $documento->tipo_mime, 'Content-Disposition' => 'inline; filename="' . $documento->nome_originale . '"' ]); } /** * Elimina un documento */ public function destroy(DocumentoStabile $documento) { try { $documento->delete(); // Il boot() del model si occuperà di eliminare il file fisico return response()->json([ 'success' => true, 'message' => 'Documento eliminato con successo' ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Errore nell\'eliminazione del documento: ' . $e->getMessage() ], 500); } } /** * Download multiplo di documenti */ public function downloadMultiple(Request $request) { $request->validate([ 'documento_ids' => 'required|array', 'documento_ids.*' => 'exists:documenti_stabili,id' ]); $documenti = DocumentoStabile::whereIn('id', $request->documento_ids)->get(); if ($documenti->isEmpty()) { return response()->json(['success' => false, 'message' => 'Nessun documento trovato'], 404); } // Crea un file ZIP temporaneo $zipFileName = 'documenti_' . time() . '.zip'; $zipPath = storage_path('app/temp/' . $zipFileName); // Assicurati che la directory temp esista if (!file_exists(dirname($zipPath))) { mkdir(dirname($zipPath), 0755, true); } $zip = new ZipArchive; if ($zip->open($zipPath, ZipArchive::CREATE) === TRUE) { foreach ($documenti as $documento) { if ($documento->fileEsiste()) { $filePath = Storage::disk('public')->path($documento->percorso_file); $zip->addFile($filePath, $documento->nome_originale); $documento->incrementaDownload(); } } $zip->close(); return response()->download($zipPath, $zipFileName)->deleteFileAfterSend(true); } return response()->json(['success' => false, 'message' => 'Errore nella creazione dell\'archivio'], 500); } /** * Eliminazione multipla di documenti */ public function deleteMultiple(Request $request) { $request->validate([ 'documento_ids' => 'required|array', 'documento_ids.*' => 'exists:documenti_stabili,id' ]); try { $documenti = DocumentoStabile::whereIn('id', $request->documento_ids)->get(); $deletedCount = 0; foreach ($documenti as $documento) { $documento->delete(); $deletedCount++; } return response()->json([ 'success' => true, 'message' => "{$deletedCount} documento/i eliminato/i con successo", 'deleted_count' => $deletedCount ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Errore nell\'eliminazione dei documenti: ' . $e->getMessage() ], 500); } } /** * Stampa elenco documenti */ public function printList(Stabile $stabile) { $documenti = $stabile->documenti() ->with('caricatore') ->orderBy('categoria') ->orderBy('created_at', 'desc') ->get() ->groupBy('categoria'); return view('admin.documenti.print-list', compact('stabile', 'documenti')); } /** * Aggiorna i metadati di un documento */ public function updateMetadata(Request $request, DocumentoStabile $documento) { $request->validate([ 'categoria' => 'required|string|in:' . implode(',', array_keys(DocumentoStabile::categorie())), 'descrizione' => 'nullable|string|max:1000', 'data_scadenza' => 'nullable|date', 'tags' => 'nullable|string', 'pubblico' => 'boolean' ]); $documento->update($request->only([ 'categoria', 'descrizione', 'data_scadenza', 'tags', 'pubblico' ])); return response()->json([ 'success' => true, 'message' => 'Metadati documento aggiornati con successo', 'documento' => $documento->fresh() ]); } /** * Ricerca documenti */ public function search(Request $request, Stabile $stabile) { $query = $stabile->documenti(); if ($request->filled('categoria')) { $query->where('categoria', $request->categoria); } if ($request->filled('search')) { $search = $request->search; $query->where(function($q) use ($search) { $q->where('nome_originale', 'like', "%{$search}%") ->orWhere('descrizione', 'like', "%{$search}%") ->orWhere('tags', 'like', "%{$search}%"); }); } if ($request->filled('scadenza')) { switch ($request->scadenza) { case 'scaduti': $query->scaduti(); break; case 'in_scadenza': $query->inScadenza(30); break; } } $documenti = $query->with('caricatore') ->orderBy('created_at', 'desc') ->get(); return response()->json([ 'success' => true, 'documenti' => $documenti ]); } }