# 🔗 TABELLE COLLEGATE ## Tabelle business collegate agli stabili e amministratori --- ## 🎯 **PRINCIPIO ARCHITETTURALE** ### **Isolamento Multi-Tenant**: Tutte le tabelle in questa sezione sono **filtrate per amministratore** tramite: - **Collegamento diretto** → `amministratore_id` - **Collegamento indiretto** → tramite `stabile_id` → `stabili.amministratore_id` ### **Catena di Isolamento**: ``` amministratori (codice 8 cifre) ↓ stabili (amministratore_id) ↓ gestioni (stabile_id) ↓ unita_immobiliari (stabile_id) soggetti (stabile_id) contabilita (gestione_id) documenti (stabile_id) ``` --- ## 📂 **TABELLE IN QUESTA SEZIONE** ### **🏢 `stabili.md`** - ✅ COMPLETATO - **Scopo**: Edifici e condomini gestiti - **Collegamento**: `amministratore_id` diretto - **Funzionalità**: Dati catastali, mandati, configurazioni - **File**: `/02-tabelle-collegate/stabili.md` ### **📅 `gestioni.md`** - 🚧 DA CREARE - **Scopo**: Periodi amministrativi per stabile - **Collegamento**: `stabile_id` → isolamento automatico - **Funzionalità**: Anno gestione, budget, chiusura conti - **File**: `/02-tabelle-collegate/gestioni.md` ### **🏠 `unita-immobiliari.md`** - 📋 DA CREARE - **Scopo**: Appartamenti e locali per stabile - **Collegamento**: `stabile_id` → isolamento automatico - **Funzionalità**: Dati catastali, millesimi, proprietari - **File**: `/02-tabelle-collegate/unita-immobiliari.md` ### **👤 `soggetti.md`** - 📋 DA CREARE - **Scopo**: Anagrafica persone e aziende per stabile - **Collegamento**: `stabile_id` → isolamento automatico - **Funzionalità**: Proprietari, inquilini, fornitori - **File**: `/02-tabelle-collegate/soggetti.md` ### **💰 `contabilita.md`** - 📋 DA CREARE - **Scopo**: Movimenti contabili per gestione - **Collegamento**: `gestione_id` → `stabile_id` → isolamento automatico - **Funzionalità**: Piano conti, registrazioni, bilanci - **File**: `/02-tabelle-collegate/contabilita.md` ### **📄 `documenti.md`** - 📋 DA CREARE - **Scopo**: Sistema documentale per stabile - **Collegamento**: `stabile_id` → isolamento automatico - **Funzionalità**: Upload, categorizzazione, versioning - **File**: `/02-tabelle-collegate/documenti.md` --- ## 🔄 **FLUSSO CREAZIONE DATI** ### **Step 1: Crea Stabile** ```php // Amministratore crea nuovo stabile $stabile = Stabile::create([ 'amministratore_id' => auth()->user()->amministratore_id, // Auto-assegnato 'denominazione' => 'Condominio Rosa', 'indirizzo' => 'Via Roma 123', // ... altri campi ]); ``` ### **Step 2: Crea Gestione** ```php // Stabile ha gestioni annuali $gestione = $stabile->gestioni()->create([ 'anno_gestione' => 2024, 'data_inizio' => '2024-01-01', 'data_fine' => '2024-12-31', // ... amministratore_id automaticamente ereditato ]); ``` ### **Step 3: Crea Unità** ```php // Stabile ha unità immobiliari $unita = $stabile->unitaImmobiliari()->create([ 'interno' => 'A1', 'piano' => 1, 'categoria' => 'A/2', // ... amministratore_id automaticamente ereditato ]); ``` ### **Step 4: Collega Soggetti** ```php // Unità ha proprietari/inquilini $proprietario = $stabile->soggetti()->create([ 'nome' => 'Mario', 'cognome' => 'Rossi', 'tipo_soggetto' => 'proprietario', // ... amministratore_id automaticamente ereditato ]); $unita->soggetti()->attach($proprietario->id, [ 'tipo_rapporto' => 'proprietario', 'quota_proprieta' => 100.00 ]); ``` --- ## 🔍 **QUERY PATTERNS COMUNI** ### **Dati per Dashboard Amministratore**: ```php $amministratore = auth()->user()->amministratore; $stats = [ // Stabili 'stabili_totali' => $amministratore->stabili()->count(), 'stabili_attivi' => $amministratore->stabili()->active()->count(), // Unità aggregate da tutti gli stabili 'unita_totali' => DB::table('unita_immobiliari') ->join('stabili', 'unita_immobiliari.stabile_id', '=', 'stabili.id') ->where('stabili.amministratore_id', $amministratore->id) ->count(), // Gestioni attive 'gestioni_attive' => DB::table('gestioni') ->join('stabili', 'gestioni.stabile_id', '=', 'stabili.id') ->where('stabili.amministratore_id', $amministratore->id) ->where('gestioni.is_active', true) ->count(), // Incassi mensili (ultimo mese) 'incassi_ultimo_mese' => DB::table('contabilita_registrazioni') ->join('gestioni', 'contabilita_registrazioni.gestione_id', '=', 'gestioni.id') ->join('stabili', 'gestioni.stabile_id', '=', 'stabili.id') ->where('stabili.amministratore_id', $amministratore->id) ->where('contabilita_registrazioni.tipo_movimento', 'entrata') ->whereBetween('contabilita_registrazioni.data_registrazione', [ now()->subMonth()->startOfMonth(), now()->subMonth()->endOfMonth() ]) ->sum('contabilita_registrazioni.importo'), ]; ``` ### **Ricerca Cross-Tabelle**: ```php // Cerca in tutti i dati dell'amministratore public function searchGlobale(Request $request) { $term = $request->input('search'); $amministratore = auth()->user()->amministratore; $results = [ 'stabili' => $amministratore->stabili() ->where('denominazione', 'like', "%{$term}%") ->limit(5) ->get(), 'unita' => DB::table('unita_immobiliari') ->join('stabili', 'unita_immobiliari.stabile_id', '=', 'stabili.id') ->where('stabili.amministratore_id', $amministratore->id) ->where('unita_immobiliari.interno', 'like', "%{$term}%") ->limit(5) ->get(), 'soggetti' => DB::table('soggetti') ->join('stabili', 'soggetti.stabile_id', '=', 'stabili.id') ->where('stabili.amministratore_id', $amministratore->id) ->where(function($query) use ($term) { $query->where('soggetti.nome', 'like', "%{$term}%") ->orWhere('soggetti.cognome', 'like', "%{$term}%"); }) ->limit(5) ->get(), ]; return response()->json($results); } ``` --- ## 🗄️ **BACKUP PER AMMINISTRATORE** ### **Script Backup Completo**: ```bash #!/bin/bash # Backup completo dati amministratore ADMIN_CODE="A1B2C3D4" BACKUP_DATE=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="backup_${ADMIN_CODE}_${BACKUP_DATE}.sql" # Header del backup echo "-- Backup NetGescon Amministratore: $ADMIN_CODE" > $BACKUP_FILE echo "-- Data: $(date)" >> $BACKUP_FILE echo "-- ====================================" >> $BACKUP_FILE # Backup amministratore mysqldump -u netgescon_user -p netgescon amministratori \ --where="codice_univoco='$ADMIN_CODE'" >> $BACKUP_FILE # Backup stabili mysqldump -u netgescon_user -p netgescon stabili \ --where="amministratore_id IN (SELECT id FROM amministratori WHERE codice_univoco='$ADMIN_CODE')" \ --no-create-info >> $BACKUP_FILE # Backup gestioni mysqldump -u netgescon_user -p netgescon gestioni \ --where="stabile_id IN (SELECT id FROM stabili WHERE amministratore_id IN (SELECT id FROM amministratori WHERE codice_univoco='$ADMIN_CODE'))" \ --no-create-info >> $BACKUP_FILE # Backup unità immobiliari mysqldump -u netgescon_user -p netgescon unita_immobiliari \ --where="stabile_id IN (SELECT id FROM stabili WHERE amministratore_id IN (SELECT id FROM amministratori WHERE codice_univoco='$ADMIN_CODE'))" \ --no-create-info >> $BACKUP_FILE echo "✅ Backup completato: $BACKUP_FILE" ``` --- ## 🔧 **MIDDLEWARE GLOBALE** ### **TenantScope per tutte le tabelle**: ```php // Nel AppServiceProvider o TenantServiceProvider public function boot() { // Scope automatico per tutte le tabelle collegate if (auth()->check() && auth()->user()->amministratore_id) { $amministratoreId = auth()->user()->amministratore_id; // Tabelle con amministratore_id diretto Stabile::addGlobalScope('tenant', function ($query) use ($amministratoreId) { $query->where('amministratore_id', $amministratoreId); }); // Tabelle con collegamento indiretto via stabili Gestione::addGlobalScope('tenant', function ($query) use ($amministratoreId) { $query->whereHas('stabile', function($q) use ($amministratoreId) { $q->where('amministratore_id', $amministratoreId); }); }); UnitaImmobiliare::addGlobalScope('tenant', function ($query) use ($amministratoreId) { $query->whereHas('stabile', function($q) use ($amministratoreId) { $q->where('amministratore_id', $amministratoreId); }); }); // ... altri scope } } ``` --- ## 📊 **FOREIGN KEY CONSTRAINTS** ### **Integrità Referenziale**: ```sql -- Tutte le tabelle collegate hanno cascade appropriato ALTER TABLE gestioni ADD CONSTRAINT fk_gestioni_stabile FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE; ALTER TABLE unita_immobiliari ADD CONSTRAINT fk_unita_stabile FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE; ALTER TABLE soggetti ADD CONSTRAINT fk_soggetti_stabile FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE; -- Eliminando uno stabile = tutti i dati collegati vengono eliminati -- Eliminando un amministratore = tutti i suoi stabili + dati vengono eliminati ``` --- ## 🎯 **ORDINE DI LETTURA CONSIGLIATO** ### **Per Implementazione Completa**: 1. **✅ `stabili.md`** → Già completato, base per tutto 2. **🚧 `gestioni.md`** → Prossimo, periodi amministrativi 3. **📋 `unita-immobiliari.md`** → Appartamenti/locali 4. **📋 `soggetti.md`** → Anagrafica persone 5. **📋 `contabilita.md`** → Movimenti contabili 6. **📋 `documenti.md`** → Sistema documentale ### **Ogni file contiene**: - ✅ **Struttura SQL** completa - ✅ **Migration Laravel** pronta - ✅ **Model Eloquent** con relazioni - ✅ **Seeder** con dati demo - ✅ **Query patterns** e esempi - ✅ **Validation** e form requests --- **🎯 TABELLE COLLEGATE ORGANIZZATE** **Tutte filtrate per amministratore - isolamento dati garantito** **📖 Prossimo step: Creare `gestioni.md` per periodi amministrativi**