netgescon-day0/docs/91-database/02-tabelle-collegate/README.md

321 lines
10 KiB
Markdown

# 🔗 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**