# 📊 CONTROLLER STANDARD E DATABASE ## Pattern controller per moduli NetGescon --- ## 🎯 **CONTROLLER TEMPLATE BASE** ### **File**: `app/Http/Controllers/Admin/{Modulo}Controller.php` ```php calculateStats(); // Dati principale per listing con filtri $items = $this->getMainData($request); // Menu configuration $menuTabs = $this->getMenuTabs(); return view('admin.modulo.index', compact('stats', 'items', 'menuTabs')); } /** * Show detail with sub-tabs */ public function show($id) { $item = $this->findItem($id); $detailTabs = $this->getDetailTabs($item); $tabContent = $this->getTabContent($item); return view('admin.modulo.show', compact('item', 'detailTabs', 'tabContent')); } /** * Show create form */ public function create() { $formData = $this->getFormData(); return view('admin.modulo.create', compact('formData')); } /** * Store new item */ public function store(Request $request) { $validatedData = $request->validate($this->getValidationRules()); // Add audit fields $validatedData['created_by'] = Auth::id(); $validatedData['amministratore_id'] = Auth::user()->amministratore_id; $item = DB::table('modulo_table')->insertGetId($validatedData); return redirect()->route('admin.modulo.index') ->with('success', 'Item creato con successo'); } /** * Show edit form */ public function edit($id) { $item = $this->findItem($id); $formData = $this->getFormData(); return view('admin.modulo.edit', compact('item', 'formData')); } /** * Update item */ public function update(Request $request, $id) { $validatedData = $request->validate($this->getValidationRules()); // Add audit fields $validatedData['updated_by'] = Auth::id(); $validatedData['updated_at'] = now(); DB::table('modulo_table') ->where('id', $id) ->where('amministratore_id', Auth::user()->amministratore_id) ->update($validatedData); return redirect()->route('admin.modulo.index') ->with('success', 'Item aggiornato con successo'); } /** * Delete item */ public function destroy($id) { DB::table('modulo_table') ->where('id', $id) ->where('amministratore_id', Auth::user()->amministratore_id) ->delete(); return redirect()->route('admin.modulo.index') ->with('success', 'Item eliminato con successo'); } /** * Reports page */ public function reports() { $reportData = $this->getReportData(); return view('admin.modulo.reports', compact('reportData')); } /** * Configuration page */ public function config() { $configData = $this->getConfigData(); return view('admin.modulo.config', compact('configData')); } // ============ PRIVATE METHODS ============ /** * Calculate statistics for cards */ private function calculateStats() { $baseQuery = DB::table('modulo_table') ->when(Auth::user()->amministratore_id, function($query) { return $query->where('amministratore_id', Auth::user()->amministratore_id); }); return [ 'totale' => (clone $baseQuery)->count(), 'attivi' => (clone $baseQuery)->where('stato', 'attivo')->count(), 'pending' => (clone $baseQuery)->where('stato', 'pending')->count(), 'questo_mese' => (clone $baseQuery) ->whereMonth('created_at', now()->month) ->whereYear('created_at', now()->year) ->count(), ]; } /** * Get main data with relations and filters */ private function getMainData(Request $request) { $query = DB::table('modulo_table') ->leftJoin('stabili', 'modulo_table.stabile_id', '=', 'stabili.id') ->leftJoin('gestioni', 'modulo_table.gestione_id', '=', 'gestioni.id_gestione') ->select([ 'modulo_table.*', 'stabili.denominazione as stabile_nome', 'gestioni.anno_gestione', 'gestioni.tipo_gestione' ]) ->when(Auth::user()->amministratore_id, function($query) { return $query->where('stabili.amministratore_id', Auth::user()->amministratore_id); }); // Apply filters if ($request->filled('search')) { $query->where(function($q) use ($request) { $q->where('modulo_table.denominazione', 'like', '%' . $request->search . '%') ->orWhere('stabili.denominazione', 'like', '%' . $request->search . '%'); }); } if ($request->filled('stato')) { $query->where('modulo_table.stato', $request->stato); } if ($request->filled('stabile_id')) { $query->where('modulo_table.stabile_id', $request->stabile_id); } return $query->orderBy('modulo_table.created_at', 'desc')->paginate(20); } /** * Find single item with security check */ private function findItem($id) { $item = DB::table('modulo_table') ->leftJoin('stabili', 'modulo_table.stabile_id', '=', 'stabili.id') ->select([ 'modulo_table.*', 'stabili.denominazione as stabile_nome' ]) ->where('modulo_table.id', $id) ->when(Auth::user()->amministratore_id, function($query) { return $query->where('stabili.amministratore_id', Auth::user()->amministratore_id); }) ->first(); if (!$item) { abort(404, 'Item non trovato'); } return $item; } /** * Get menu tabs configuration */ private function getMenuTabs() { return [ [ 'label' => 'Lista', 'route' => 'admin.modulo.index', 'icon' => 'fas fa-list', 'active' => request()->routeIs('admin.modulo.index') ], [ 'label' => 'Nuovo', 'route' => 'admin.modulo.create', 'icon' => 'fas fa-plus', 'active' => request()->routeIs('admin.modulo.create') ], [ 'label' => 'Reports', 'route' => 'admin.modulo.reports', 'icon' => 'fas fa-chart-bar', 'active' => request()->routeIs('admin.modulo.reports') ], [ 'label' => 'Config', 'route' => 'admin.modulo.config', 'icon' => 'fas fa-cog', 'active' => request()->routeIs('admin.modulo.config') ], ]; } /** * Get detail tabs for show page */ private function getDetailTabs($item) { return [ [ 'id' => 'dati-generali', 'label' => 'Dati Generali', 'icon' => 'fas fa-info-circle', 'active' => true ], [ 'id' => 'dettagli', 'label' => 'Dettagli', 'icon' => 'fas fa-list', 'active' => false ], [ 'id' => 'documenti', 'label' => 'Documenti', 'icon' => 'fas fa-file', 'active' => false ], ]; } /** * Get validation rules */ private function getValidationRules() { return [ 'denominazione' => 'required|string|max:255', 'descrizione' => 'nullable|string', 'stato' => 'required|in:attivo,inattivo,sospeso', 'stabile_id' => 'nullable|exists:stabili,id', 'gestione_id' => 'nullable|exists:gestioni,id_gestione', ]; } /** * Get form data for create/edit */ private function getFormData() { return [ 'stabili' => DB::table('stabili') ->when(Auth::user()->amministratore_id, function($query) { return $query->where('amministratore_id', Auth::user()->amministratore_id); }) ->select('id', 'denominazione') ->orderBy('denominazione') ->get(), 'gestioni' => DB::table('gestioni') ->join('stabili', 'gestioni.stabile_id', '=', 'stabili.id') ->when(Auth::user()->amministratore_id, function($query) { return $query->where('stabili.amministratore_id', Auth::user()->amministratore_id); }) ->select('gestioni.id_gestione', 'gestioni.anno_gestione', 'stabili.denominazione as stabile_nome') ->orderBy('gestioni.anno_gestione', 'desc') ->get(), 'stati' => [ 'attivo' => 'Attivo', 'inattivo' => 'Inattivo', 'sospeso' => 'Sospeso' ] ]; } /** * Get tab content for show page */ private function getTabContent($item) { return [ 'dati_generali' => $item, 'dettagli' => $this->getDetailData($item->id), 'documenti' => $this->getDocumenti($item->id), ]; } /** * Get additional detail data */ private function getDetailData($itemId) { // Get related data for details tab return []; } /** * Get documents for item */ private function getDocumenti($itemId) { // Get documents related to this item return []; } /** * Get report data */ private function getReportData() { // Generate report data return []; } /** * Get configuration data */ private function getConfigData() { // Get configuration settings return []; } } ``` --- ## 🔐 **SECURITY PATTERNS** ### **Filtro Amministratore Obbligatorio**: ```php // SEMPRE filtrare per amministratore private function getBaseQuery() { return DB::table('modulo_table') ->when(Auth::user()->amministratore_id, function($query) { return $query->where('amministratore_id', Auth::user()->amministratore_id); }); } // Per super admin senza filtro private function isSuperAdmin() { return Auth::user()->is_super_admin ?? false; } ``` ### **Validation con Security**: ```php private function getValidationRules($id = null) { return [ 'denominazione' => 'required|string|max:255', 'stabile_id' => [ 'nullable', 'exists:stabili,id', // Verifica che lo stabile appartenga all'amministratore function ($attribute, $value, $fail) { if ($value && Auth::user()->amministratore_id) { $exists = DB::table('stabili') ->where('id', $value) ->where('amministratore_id', Auth::user()->amministratore_id) ->exists(); if (!$exists) { $fail('Stabile non autorizzato.'); } } }, ], ]; } ``` --- ## 📊 **DATABASE QUERY PATTERNS** ### **Query con Relazioni Standard**: ```php // Pattern base per listing private function getItemsWithRelations() { return DB::table('modulo_table as m') ->leftJoin('stabili as s', 'm.stabile_id', '=', 's.id') ->leftJoin('gestioni as g', 'm.gestione_id', '=', 'g.id_gestione') ->leftJoin('unita_immobiliari as ui', 'm.unita_id', '=', 'ui.id') ->select([ 'm.*', 's.denominazione as stabile_nome', 's.indirizzo as stabile_indirizzo', 'g.anno_gestione', 'g.tipo_gestione', 'ui.denominazione as unita_nome' ]) ->where('s.amministratore_id', Auth::user()->amministratore_id); } ``` ### **Stats Query Ottimizzate**: ```php private function calculateAdvancedStats() { $amministratore_id = Auth::user()->amministratore_id; // Single query con aggregazione $stats = DB::table('modulo_table as m') ->join('stabili as s', 'm.stabile_id', '=', 's.id') ->where('s.amministratore_id', $amministratore_id) ->selectRaw(' COUNT(*) as totale, SUM(CASE WHEN m.stato = "attivo" THEN 1 ELSE 0 END) as attivi, SUM(CASE WHEN m.stato = "pending" THEN 1 ELSE 0 END) as pending, SUM(CASE WHEN MONTH(m.created_at) = MONTH(NOW()) AND YEAR(m.created_at) = YEAR(NOW()) THEN 1 ELSE 0 END) as questo_mese, AVG(m.importo) as importo_medio, SUM(m.importo) as importo_totale ') ->first(); return (array) $stats; } ``` --- ## 🚀 **ROUTE CONFIGURATION** ### **File**: `routes/admin.php` ```php Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () { // Standard RESTful routes Route::resource('modulo', 'ModuloController'); // Additional custom routes Route::get('modulo/{id}/detail', ['ModuloController', 'detail'])->name('modulo.detail'); Route::get('modulo/reports/index', ['ModuloController', 'reports'])->name('modulo.reports'); Route::get('modulo/config/index', ['ModuloController', 'config'])->name('modulo.config'); // AJAX routes Route::post('modulo/{id}/toggle-status', ['ModuloController', 'toggleStatus'])->name('modulo.toggle-status'); Route::get('modulo/search/autocomplete', ['ModuloController', 'autocomplete'])->name('modulo.autocomplete'); }); ``` --- ## 📝 **EXAMPLE IMPLEMENTATIONS** ### **Fornitori Controller**: ```php class FornitoriController extends Controller { private function calculateStats() { return [ 'totale_fornitori' => DB::table('fornitori')->count(), 'attivi' => DB::table('fornitori')->where('stato', 'attivo')->count(), 'questo_mese' => DB::table('fornitori') ->whereMonth('created_at', now()->month)->count(), 'fatture_pending' => DB::table('fatture_fornitori') ->where('stato', 'pending')->count(), ]; } private function getValidationRules() { return [ 'denominazione' => 'required|string|max:255', 'partita_iva' => 'required|string|max:20', 'codice_fiscale' => 'nullable|string|max:16', 'email' => 'nullable|email', 'telefono' => 'nullable|string|max:20', 'indirizzo' => 'nullable|string', 'categoria' => 'required|in:manutenzione,pulizie,servizi,altro', 'stato' => 'required|in:attivo,inattivo,sospeso', ]; } } ``` ### **Gestioni Controller**: ```php class GestioniController extends Controller { private function calculateStats() { return [ 'totale_gestioni' => DB::table('gestioni')->count(), 'aperte' => DB::table('gestioni')->where('stato', 'aperta')->count(), 'da_chiudere' => DB::table('gestioni') ->where('data_fine', '<=', now()) ->where('stato', 'aperta')->count(), 'archiviate' => DB::table('gestioni')->where('stato', 'archiviata')->count(), ]; } } ``` --- ## ⚡ **PERFORMANCE TIPS** ### **Query Optimization**: ```php // Use indexes private function addIndexes() { // In migration $table->index(['amministratore_id', 'stato']); $table->index(['stabile_id', 'created_at']); $table->index('stato'); } // Limit data private function getMainData($request) { return $this->getBaseQuery() ->select([ 'm.id', 'm.denominazione', 'm.stato', 'm.created_at', 's.denominazione as stabile_nome' ]) // Solo campi necessari ->paginate(20); // Limitare risultati } ``` ### **Caching Stats**: ```php private function calculateStats() { return Cache::remember( 'stats_modulo_' . Auth::user()->amministratore_id, now()->addMinutes(5), function () { return $this->getStatsFromDatabase(); } ); } ``` --- **📖 Prossimo file: `05-css-javascript.md`**