hasRole('collaboratore')) { $stabili = $user->stabiliAssegnati()->paginate(10); } else { // Amministratore: mostra solo i propri stabili $amministratore = $user->amministratore ?? null; $amministratore_id = $amministratore ? $amministratore->id : null; if (!$amministratore_id) { $stabili = Stabile::whereRaw('1=0')->paginate(10); } else { $stabili = Stabile::where('amministratore_id', $amministratore_id)->paginate(10); } } return view('admin.stabili.index', compact('stabili')); } /** * Show the form for creating a new resource. */ public function create() { if (Auth::user()->hasRole('collaboratore')) { abort(403, 'I collaboratori non possono creare nuovi stabili'); } return view('admin.stabili.create'); } /** * Store a newly created resource in storage. */ public function store(Request $request) { if (Auth::user()->hasRole('collaboratore')) { abort(403, 'I collaboratori non possono creare nuovi stabili'); } $request->validate([ 'denominazione' => 'required|string|max:255', 'codice_fiscale' => 'nullable|string|max:20|unique:stabili,codice_fiscale', 'cod_fisc_amministratore' => 'nullable|string|max:20', 'indirizzo' => 'required|string|max:255', 'citta' => 'required|string|max:255', 'cap' => 'required|string|max:10', 'provincia' => 'nullable|string|max:2', 'stato' => 'required|in:attivo,inattivo', 'note' => 'nullable|string', 'old_id' => 'nullable|integer|unique:stabili,old_id', ]); $stabile = Stabile::create([ 'amministratore_id' => (Auth::user()->amministratore->id ?? null), 'denominazione' => $request->denominazione, 'codice_fiscale' => $request->codice_fiscale, 'cod_fisc_amministratore' => $request->cod_fisc_amministratore, 'indirizzo' => $request->indirizzo, 'citta' => $request->citta, 'cap' => $request->cap, 'provincia' => $request->provincia, 'stato' => $request->stato, 'note' => $request->note, 'old_id' => $request->old_id, ]); return redirect()->route('admin.stabili.index') ->with('success', 'Stabile creato con successo.'); } /** * Display the specified resource. */ public function show(Stabile $stabile) { $user = Auth::user(); // Autorizzazione: amministratore proprietario o collaboratore assegnato $allowed = false; if ($user->hasRole('collaboratore')) { $allowed = $user->stabiliAssegnati()->where('stabili.id', $stabile->id)->exists(); } else { $amministratore = $user->amministratore ?? null; $allowed = $amministratore && $stabile->amministratore_id === $amministratore->id; } if (!$allowed) { abort(403, 'Non hai i permessi per visualizzare questo stabile'); } // Caricamento minimale – le altre relazioni sono lazy via endpoints tab $stabile->load(['amministratore']); return view('admin.stabili.show', compact('stabile')); } /** * Show the form for editing the specified resource. */ public function edit(Stabile $stabile) { // I collaboratori non possono modificare if (Auth::user()->hasRole('collaboratore')) { abort(403, 'I collaboratori non possono modificare gli stabili'); } // Verifica che l'utente possa modificare questo stabile $amministratore = Auth::user()->amministratore ?? null; $amministratore_id = $amministratore ? $amministratore->id : null; if ($stabile->amministratore_id !== $amministratore_id) { abort(403, 'Non hai i permessi per modificare questo stabile'); } return view('admin.stabili.edit', compact('stabile')); } /** * Update the specified resource in storage. */ public function update(Request $request, Stabile $stabile) { // I collaboratori non possono modificare if (Auth::user()->hasRole('collaboratore')) { abort(403, 'I collaboratori non possono modificare gli stabili'); } // Verifica che l'utente possa modificare questo stabile $amministratore = Auth::user()->amministratore ?? null; $amministratore_id = $amministratore ? $amministratore->id : null; if ($stabile->amministratore_id !== $amministratore_id) { abort(403, 'Non hai i permessi per modificare questo stabile'); } $request->validate([ 'denominazione' => 'required|string|max:255', 'codice_fiscale' => 'nullable|string|max:20|unique:stabili,codice_fiscale,' . $stabile->id, 'cod_fisc_amministratore' => 'nullable|string|max:20', 'indirizzo' => 'required|string|max:255', 'citta' => 'required|string|max:255', 'cap' => 'required|string|max:10', 'provincia' => 'nullable|string|max:2', 'stato' => 'required|in:attivo,inattivo', 'note' => 'nullable|string', 'old_id' => 'nullable|integer|unique:stabili,old_id,' . $stabile->id, ]); $stabile->update($request->all()); return redirect()->route('admin.stabili.index') ->with('success', 'Stabile aggiornato con successo.'); } /** * Remove the specified resource from storage. */ public function destroy(Stabile $stabile) { // I collaboratori non possono eliminare if (Auth::user()->hasRole('collaboratore')) { abort(403, 'I collaboratori non possono eliminare gli stabili'); } // Verifica che l'utente possa eliminare questo stabile $amministratore = Auth::user()->amministratore ?? null; $amministratore_id = $amministratore ? $amministratore->id : null; if ($stabile->amministratore_id !== $amministratore_id) { abort(403); } $stabile->delete(); return redirect()->route('admin.stabili.index') ->with('success', 'Stabile eliminato con successo.'); } /** * Get tabella millesimali details for Excel-like view (API) */ public function getTabellaMillesimaliDettagli(Stabile $stabile, $tabellaId) { if (!$this->canAccessStabile($stabile)) { return response()->json(['error' => 'Unauthorized'], 403); } $tabella = $stabile->tabelleMillesimali()->with('dettagli.unitaImmobiliare')->findOrFail($tabellaId); $dettagli = $tabella->dettagli->map(function ($dettaglio) { return [ 'id' => $dettaglio->id, 'scala' => $dettaglio->unitaImmobiliare->scala ?? 'N/A', 'interno' => $dettaglio->unitaImmobiliare->interno ?? 'N/A', 'descrizione' => $dettaglio->unitaImmobiliare->descrizione ?? $dettaglio->descrizione_unita, 'millesimi' => (float)$dettaglio->millesimi, 'proprietario' => $dettaglio->unitaImmobiliare->getNomeProprietarioAttribute() ?? 'N/A' ]; }); $totaleMillesimi = $dettagli->sum('millesimi'); $bilanciato = abs($totaleMillesimi - 1000) < 0.01; return response()->json([ 'success' => true, 'tabella' => [ 'id' => $tabella->id, 'codice' => $tabella->codice_tabella, 'denominazione' => $tabella->denominazione ?: $tabella->nome_tabella, 'tipo' => $tabella->tipo_tabella ?: $tabella->tipo, 'totale_millesimi' => $totaleMillesimi, 'bilanciata' => $bilanciato, 'differenza' => $totaleMillesimi - 1000 ], 'dettagli' => $dettagli, 'statistiche' => [ 'unita_count' => $dettagli->count(), 'millesimo_medio' => $dettagli->count() > 0 ? $dettagli->avg('millesimi') : 0, 'millesimo_max' => $dettagli->max('millesimi') ?? 0, 'millesimo_min' => $dettagli->min('millesimi') ?? 0 ] ]); } /** * Update a single millesimo value (API) */ public function aggiornaMillesimo(Request $request, Stabile $stabile, $tabellaId) { // Solo amministratore proprietario può modificare millesimi if (!$this->isOwnerAmministratore($stabile)) { return response()->json(['error' => 'Unauthorized'], 403); } $request->validate([ 'dettaglio_id' => 'required|integer', 'nuovo_valore' => 'required|numeric|min:0' ]); $tabella = $stabile->tabelleMillesimali()->findOrFail($tabellaId); $dettaglio = $tabella->dettagli()->findOrFail($request->dettaglio_id); $vecchioValore = $dettaglio->millesimi; $dettaglio->update([ 'millesimi' => $request->nuovo_valore, 'modificato_da' => Auth::id() ]); // Ricalcola il totale della tabella $nuovoTotale = $tabella->dettagli()->sum('millesimi'); $tabella->update([ 'totale_millesimi' => $nuovoTotale, 'modificato_da' => Auth::id() ]); return response()->json([ 'success' => true, 'message' => 'Millesimo aggiornato con successo', 'vecchio_valore' => $vecchioValore, 'nuovo_valore' => $request->nuovo_valore, 'nuovo_totale' => $nuovoTotale, 'bilanciata' => abs($nuovoTotale - 1000) < 0.01 ]); } /** * Verify tabella millesimali balance (API) */ public function verificaBilanciamento(Stabile $stabile, $tabellaId) { if (!$this->canAccessStabile($stabile)) { return response()->json(['error' => 'Unauthorized'], 403); } $tabella = $stabile->tabelleMillesimali()->findOrFail($tabellaId); $totaleMillesimi = $tabella->dettagli()->sum('millesimi'); $differenza = $totaleMillesimi - 1000; $bilanciata = abs($differenza) < 0.01; // Aggiorna il totale nella tabella $tabella->update([ 'totale_millesimi' => $totaleMillesimi, 'modificato_da' => Auth::id() ]); return response()->json([ 'success' => true, 'bilanciata' => $bilanciata, 'totale_millesimi' => $totaleMillesimi, 'differenza' => $differenza, 'messaggio' => $bilanciata ? 'La tabella è correttamente bilanciata!' : "La tabella non è bilanciata. Differenza: " . ($differenza > 0 ? '+' : '') . number_format($differenza, 4) ]); } /** * Get Unità Immobiliari for AJAX tab loading */ public function getUnitaImmobiliari(Stabile $stabile) { // Verifica autorizzazione if (!$this->canAccessStabile($stabile)) { return response()->json(['error' => 'Unauthorized'], 403); } // Carica le unità immobiliari dello stabile $unitaImmobiliari = $stabile->unitaImmobiliari() ->orderBy('codice_interno') ->orderBy('piano') ->orderBy('appartamento') ->get(); // Genera l'HTML della tabella $html = view('admin.stabili.partials.unita-immobiliari-tab', compact('unitaImmobiliari', 'stabile'))->render(); return response()->json([ 'success' => true, 'html' => $html ]); } /** * Tab: Dati Generali (lightweight – basic relations only) */ public function tabDatiGenerali(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('amministratore')) { $stabile->load('amministratore'); } $html = \view('admin.stabili.tabs.dati-generali', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Palazzine */ public function tabPalazzine(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('palazzine')) { $stabile->load('palazzine'); } $html = \view('admin.stabili.tabs.palazzine', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Dati Bancari */ public function tabDatiBancari(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('datiBancari')) { $stabile->load(['datiBancari.contatto']); } $html = \view('admin.stabili.tabs.dati-bancari', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Tabelle Millesimali */ public function tabTabelleMillesimali(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('tabelleMillesimali')) { $stabile->load(['tabelleMillesimali' => function ($q) { $q->orderBy('ordinamento')->orderBy('nome_tabella'); }]); } if (!$stabile->relationLoaded('vociSpesa')) { $stabile->load(['vociSpesa' => function ($q) { $q->orderBy('ordinamento')->orderBy('descrizione'); }]); } $html = \view('admin.stabili.tabs.tabelle-millesimali', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Gestioni */ public function tabGestioni(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('gestioniContabili')) { $stabile->load('gestioniContabili'); } $html = \view('admin.stabili.tabs.gestioni', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Unita Immobiliari (wrapper – riusa endpoint esistente per lista) */ public function tabUnitaImmobiliari(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } // Carica count base; dettagli verranno fetchati da JS esistente (getUnitaImmobiliari) $count = $stabile->unitaImmobiliari()->count(); $html = \view('admin.stabili.tabs.unita-immobiliari', compact('stabile', 'count'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Tab: Gestione Documentale */ public function tabGestioneDocumentale(Stabile $stabile) { if (!$this->canAccessStabile($stabile)) { return \response()->json(['error' => 'Unauthorized'], 403); } if (!$stabile->relationLoaded('documentiCollegati')) { $stabile->load('documentiCollegati'); } $html = \view('admin.stabili.tabs.gestione-documentale', compact('stabile'))->render(); return \response()->json(['success' => true, 'html' => $html]); } /** * Carica appartamenti filtrati per il tab palazzine */ public function getAppartamenti(Request $request, $id) { $stabile = Stabile::findOrFail($id); if (!$this->canAccessStabile($stabile)) { abort(403); } $query = $stabile->unitaImmobiliari()->with(['soggetti' => function ($q) { $q->withPivot('tipo_diritto'); }]); // Filtro per scala if ($request->scala) { $query->where('scala', $request->scala); } // Filtro per presenza soggetti if ($request->filtro == 'con-soggetti') { $query->whereHas('soggetti'); } elseif ($request->filtro == 'senza-soggetti') { $query->whereDoesntHave('soggetti'); } $unita = $query->orderBy('piano')->orderBy('interno')->get(); return view('admin.stabili.tabs.partials.lista-appartamenti', compact('unita'))->render(); } /** * Helpers autorizzazione */ private function canAccessStabile(Stabile $stabile): bool { $user = Auth::user(); if ($user->hasRole('collaboratore')) { return $user->stabiliAssegnati()->where('stabili.id', $stabile->id)->exists(); } $amministratore = $user->amministratore ?? null; return $amministratore && $stabile->amministratore_id === $amministratore->id; } private function isOwnerAmministratore(Stabile $stabile): bool { $user = Auth::user(); $amministratore = $user->amministratore ?? null; return !$user->hasRole('collaboratore') && $amministratore && $stabile->amministratore_id === $amministratore->id; } }