# 📊 MANUALE 07 - DATABASE NETGESCON **Versione: 1.0 - Data: 03 Agosto 2025** **Database di Riferimento: netgescon con credenziali unificate** --- ## 🎯 **INTRODUZIONE** Questo manuale fornisce la documentazione completa della struttura database NetGescon, compresi schemi, tabelle, relazioni e best practices per lo sviluppo di moduli. ### **🔑 CREDENZIALI UNIFICATE** ```env DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=netgescon DB_USERNAME=netgescon_user DB_PASSWORD=NetGescon2024! ``` **⚠️ IMPORTANTE**: Utilizzare sempre queste credenziali per tutti i moduli e connessioni database. --- ## �️ **ARCHIVI LEGACY GESCON (SOLO LETTURA)** Per tutte le attività di import legacy utilizziamo direttamente gli archivi storici residenti sul NAS Windows montato in `/mnt/gescon-archives/gescon`. L'accesso deve rimanere **in sola lettura**: eventuali correzioni o riconciliazioni vanno gestite copiando i dataset in uno staging MySQL (`gescon_import` schema) dove possiamo applicare patch e controlli senza contaminare l'originale. ### 🔐 Policy di accesso - Percorso principale: `/mnt/gescon-archives/gescon///`. - Il montaggio è permanente sul server Linux; non serve rsyncare nella repo. - Quando servono snapshot per test locali si possono esportare le tabelle direttamente in MySQL o CSV, ma **mai** scrivere sui file Access originali. ### 🗂️ Struttura cartelle per stabile/gestione 1. Ogni stabile è identificato da una cartella numerica a quattro cifre (es. `0021` corrisponde a **Viale delle Milizie 3**). 2. All'interno troviamo: - Sottocartelle numeriche (`0001`, `0003`, …) che corrispondono ai singoli anni di gestione; ciascuna contiene `singolo_anno.mdb`. - File trasversali come `generale_stabile.mdb`, `generale_stabile_sf.mdb`, allegati, documenti, ecc. 3. Il file `generale_stabile.mdb` → tabella `anni` fornisce il mapping fra gestione e cartella: - `nome_dir`: contiene il codice cartella (`0001`, `0003`, …). - `anno_o` / `anno_r`: indicano periodo di ordinaria e riscaldamento. - Campi `ordinarie_dal`, `ordinarie_al`, `riscald_dal`, `riscald_al` definiscono l'intervallo temporale da salvare dentro le nostre tabelle `gestioni`. ### 📑 Tabelle principali da importare (singolo_anno.mdb) | Tabella legacy | Contenuto | Uso nel nuovo schema | | --- | --- | --- | | `condomine` / `condomini_totali` | Anagrafiche complete delle unità con scala, interno, soggetto, riferimenti catastali, flag di attivazione e preferenze di invio | Popola `unita_immobiliari`, `soggetti` e la pivot `proprieta` / `diritti_reali`. Campi chiave: `id_cond` (ID unità), `cod_cond` (codice interno), `scala`, `int`, `nom_cond`, `subentrato_dal`, `attivo_fino_al`, `Internet_cod`/`pw` (eventuali accessi), `E_lostesso_di` (link pertinenze). | | `tabelle` | Definizione delle tabelle millesimali: `cod_tab`, `descr`, `calcolo`, `tipo` (O=Ordinaria, R=Riscaldamento, S=Straordinaria), `Tot_mm`, `inte_col` (colonna stampata), `un_mis`, `nord` (posizionamento su prospetto), `Num_decimali`, `Is_Detr` | Mappa su `tabelle_millesimali` del dominio NetGescon. Conserviamo `cod_tab` come `codice_tabella`, `descr` come `denominazione`, `tipo`→`gestione` (O/R/S) e `nord`/`nord2` per la futura generazione di prospetti. | | `dett_tab` | Dettaglio millesimi per singola unità (`cod_tab` + `id_cond`). Campi `mm`, `prev`, `cons`, `cond_inquil` (C condomini / I inquilini), `n_stra`, `Proviene_*` | Alimenta `dettaglio_millesimi` collegando `cod_tab` (tabella) e `id_cond` (unità). Il flag `cond_inquil` serve per distinguere quote condominiali vs. inquilini durante il riparto. | | `condomin`, `cond_detr`, `rendite_condominiali` | Informazioni aggiuntive su soggetti e catasto (rendite, diritti reali, detrazioni fiscali) | Servono alle prossime iterazioni del modulo `gescon-import` per completare Rubrica Unica e i collegamenti con tabelle fiscali. | ### 🧩 Processo di import (modulo `gescon-import`) 1. **Identificazione gestione**: leggere `generale_stabile.mdb` → `anni` per sapere quale cartella (`nome_dir`) usare per ordinaria/riscaldamento/straz. 2. **Estrazione Access ➜ staging**: esportare da `singolo_anno.mdb` le tabelle `condomini_totali`, `tabelle`, `dett_tab` (tramite `mdb-export`, `mdb-sql` o ODBC) e caricarle in tabelle temporanee MySQL (`gescon_import.`). 3. **Normalizzazione unità**: trasformare i record di `condomini_totali` nei nostri modelli `stabili`, `unita_immobiliari`, `soggetti` rispettando mapping scala/piano/interno e mantenendo ID legacy (`id_cond`) per i join successivi. 4. **Creazione tabelle millesimali**: per ogni record di `tabelle` creare/aggiornare `tabelle_millesimali` con: - `codice_tabella = cod_tab` - `denominazione = descr` - `tipo_tabella` derivato da `tipo` (`O`→`ordinaria`, `R`→`riscaldamento`, `S`→`straordinaria`) - `nord`/`nord2` conservati per mantenere l'ordinamento nei prospetti. 5. **Assegnazione millesimi**: usare `dett_tab` per compilare `dettaglio_millesimi`, facendo il join su `id_cond` → nuova `unita_immobiliare.id`. Il campo `mm` va salvato come valore principale; `prev`/`cons` possono andare in colonne di audit o JSON per mantenere gli storici. 6. **Gestione read-only continuity**: dopo l'import, aggiornamenti e controlli avvengono nella copia MySQL; per riallineare con il legacy si riesegue l'estrazione mantenendo il mapping su `id_cond`/`cod_tab`. > **Nota operativa:** le informazioni appena censite (per esempio lo stabile `0021` di Viale delle Milizie 3) vanno documentate anche dentro il modulo `gescon-import` così da riusare lo stesso flusso sulle prossime installazioni senza dover esplorare manualmente i file Access. --- ## �🗄️ **SCHEMA PRINCIPALE DATABASE** ### **Tabelle Core Sistema** #### **1. Utenti e Autenticazione** ```sql -- Tabella utenti principale CREATE TABLE users ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, email_verified_at TIMESTAMP NULL, password VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT TRUE, last_login_at TIMESTAMP NULL, profile_photo_path VARCHAR(2048) NULL, phone VARCHAR(20) NULL, address TEXT NULL, remember_token VARCHAR(100) NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, INDEX idx_email (email), INDEX idx_active (is_active), INDEX idx_last_login (last_login_at) ); -- Sistema permessi Spatie CREATE TABLE roles ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, guard_name VARCHAR(255) NOT NULL DEFAULT 'web', created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, UNIQUE KEY unique_role_guard (name, guard_name) ); CREATE TABLE permissions ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, guard_name VARCHAR(255) NOT NULL DEFAULT 'web', created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, UNIQUE KEY unique_permission_guard (name, guard_name) ); CREATE TABLE model_has_roles ( role_id BIGINT UNSIGNED NOT NULL, model_type VARCHAR(255) NOT NULL, model_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (role_id, model_id, model_type), FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE, INDEX idx_model_type (model_type), INDEX idx_model_id (model_id) ); CREATE TABLE model_has_permissions ( permission_id BIGINT UNSIGNED NOT NULL, model_type VARCHAR(255) NOT NULL, model_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (permission_id, model_id, model_type), FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE, INDEX idx_model_type (model_type), INDEX idx_model_id (model_id) ); CREATE TABLE role_has_permissions ( permission_id BIGINT UNSIGNED NOT NULL, role_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (permission_id, role_id), FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE, FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE ); ``` #### **2. Anagrafica Territoriale** ```sql -- Comuni italiani (database completo) CREATE TABLE comuni_italiani ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, codice_catastale VARCHAR(4) NOT NULL UNIQUE, denominazione VARCHAR(255) NOT NULL, denominazione_tedesca VARCHAR(255) NULL, denominazione_altra VARCHAR(255) NULL, codice_provincia VARCHAR(2) NOT NULL, provincia VARCHAR(255) NOT NULL, regione VARCHAR(255) NOT NULL, cap VARCHAR(5) NULL, prefisso VARCHAR(10) NULL, email_pec VARCHAR(255) NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, INDEX idx_codice_catastale (codice_catastale), INDEX idx_provincia (codice_provincia), INDEX idx_denominazione (denominazione), INDEX idx_cap (cap) ); ``` #### **3. Strutture Immobiliari** ```sql -- Stabili/Condomini CREATE TABLE stabili ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, denominazione VARCHAR(255) NOT NULL, indirizzo VARCHAR(255) NOT NULL, comune_id BIGINT UNSIGNED NULL, cap VARCHAR(10) NULL, codice_fiscale VARCHAR(16) NULL, partita_iva VARCHAR(11) NULL, amministratore_id BIGINT UNSIGNED NULL, is_active BOOLEAN DEFAULT TRUE, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (comune_id) REFERENCES comuni_italiani(id) ON DELETE SET NULL, FOREIGN KEY (amministratore_id) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_denominazione (denominazione), INDEX idx_amministratore (amministratore_id), INDEX idx_comune (comune_id), INDEX idx_active (is_active), INDEX idx_codice_fiscale (codice_fiscale) ); -- Unità immobiliari CREATE TABLE unita_immobiliari ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, stabile_id BIGINT UNSIGNED NOT NULL, numero VARCHAR(50) NOT NULL, piano VARCHAR(20) NULL, scala VARCHAR(20) NULL, interno VARCHAR(20) NULL, tipo ENUM('appartamento', 'negozio', 'garage', 'cantina', 'altro') NOT NULL DEFAULT 'appartamento', categoria_catastale VARCHAR(10) NULL, classe_catastale VARCHAR(10) NULL, consistenza VARCHAR(20) NULL, superficie_catastale DECIMAL(8,2) NULL, superficie_commerciale DECIMAL(8,2) NULL, rendita_catastale DECIMAL(10,2) NULL, millesimi_proprieta DECIMAL(8,4) NULL, millesimi_riscaldamento DECIMAL(8,4) NULL, millesimi_acqua DECIMAL(8,4) NULL, millesimi_ascensore DECIMAL(8,4) NULL, is_active BOOLEAN DEFAULT TRUE, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE, INDEX idx_stabile (stabile_id), INDEX idx_numero (numero), INDEX idx_tipo (tipo), INDEX idx_active (is_active), UNIQUE KEY unique_stabile_numero (stabile_id, numero) ); ``` #### **4. Anagrafica Soggetti** ```sql -- Soggetti (persone fisiche e giuridiche) CREATE TABLE soggetti ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, tipo_soggetto ENUM('persona_fisica', 'persona_giuridica') NOT NULL, nome VARCHAR(255) NULL, cognome VARCHAR(255) NULL, ragione_sociale VARCHAR(255) NULL, codice_fiscale VARCHAR(16) NULL, partita_iva VARCHAR(11) NULL, data_nascita DATE NULL, luogo_nascita VARCHAR(255) NULL, indirizzo VARCHAR(255) NULL, comune_id BIGINT UNSIGNED NULL, cap VARCHAR(10) NULL, telefono VARCHAR(20) NULL, email VARCHAR(255) NULL, is_active BOOLEAN DEFAULT TRUE, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (comune_id) REFERENCES comuni_italiani(id) ON DELETE SET NULL, INDEX idx_codice_fiscale (codice_fiscale), INDEX idx_partita_iva (partita_iva), INDEX idx_tipo_soggetto (tipo_soggetto), INDEX idx_cognome_nome (cognome, nome), INDEX idx_ragione_sociale (ragione_sociale), INDEX idx_active (is_active) ); -- Relazioni soggetti-unità immobiliari CREATE TABLE diritti_reali ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, soggetto_id BIGINT UNSIGNED NOT NULL, unita_immobiliare_id BIGINT UNSIGNED NOT NULL, tipo_diritto ENUM('proprietario', 'nudo_proprietario', 'usufruttuario', 'inquilino', 'comodatario') NOT NULL, quota_proprieta DECIMAL(8,4) NULL, data_inizio DATE NULL, data_fine DATE NULL, is_active BOOLEAN DEFAULT TRUE, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (soggetto_id) REFERENCES soggetti(id) ON DELETE CASCADE, FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id) ON DELETE CASCADE, INDEX idx_soggetto (soggetto_id), INDEX idx_unita (unita_immobiliare_id), INDEX idx_tipo_diritto (tipo_diritto), INDEX idx_active (is_active), INDEX idx_data_inizio (data_inizio), INDEX idx_data_fine (data_fine) ); ``` --- ## 💰 **MODULO CONTABILITÀ - SCHEMA IMPLEMENTATO** ### **Tabelle Contabili** ```sql -- Piano dei conti CREATE TABLE piano_conti ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, mastro VARCHAR(10) NOT NULL, conto VARCHAR(10) NOT NULL, sottoconto VARCHAR(10) NOT NULL, descrizione VARCHAR(255) NOT NULL, tipo ENUM('attivo', 'passivo', 'costo', 'ricavo') NOT NULL, attivo BOOLEAN DEFAULT TRUE, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, INDEX idx_mastro_conto (mastro, conto, sottoconto), INDEX idx_tipo (tipo), INDEX idx_attivo (attivo), INDEX idx_descrizione (descrizione) ); -- Gestioni contabili CREATE TABLE gestioni ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, denominazione VARCHAR(255) NOT NULL, anno INT NOT NULL, data_inizio DATE NOT NULL, data_fine DATE NOT NULL, attivo BOOLEAN DEFAULT TRUE, stabile_id BIGINT UNSIGNED NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE SET NULL, INDEX idx_anno (anno), INDEX idx_attivo (attivo), INDEX idx_stabile (stabile_id), UNIQUE KEY unique_stabile_anno (stabile_id, anno) ); -- Registrazioni contabili CREATE TABLE registrazioni_contabili ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, data_registrazione DATE NOT NULL, numero_registrazione VARCHAR(20) NULL, descrizione TEXT NOT NULL, importo_dare DECIMAL(12,2) DEFAULT 0.00, importo_avere DECIMAL(12,2) DEFAULT 0.00, piano_conti_id BIGINT UNSIGNED NOT NULL, gestione_id BIGINT UNSIGNED NOT NULL, user_id BIGINT UNSIGNED NOT NULL, documento_riferimento VARCHAR(255) NULL, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (piano_conti_id) REFERENCES piano_conti(id) ON DELETE RESTRICT, FOREIGN KEY (gestione_id) REFERENCES gestioni(id) ON DELETE RESTRICT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT, INDEX idx_data_registrazione (data_registrazione), INDEX idx_piano_conti (piano_conti_id), INDEX idx_gestione (gestione_id), INDEX idx_user (user_id), INDEX idx_numero (numero_registrazione) ); ``` ### **Dati Base Piano dei Conti** ```sql -- Piano dei conti standard per condomini INSERT INTO piano_conti (mastro, conto, sottoconto, descrizione, tipo, attivo) VALUES -- CLASSE 1 - CONTI FINANZIARI ('1', '01', '01', 'Cassa contanti', 'attivo', TRUE), ('1', '01', '02', 'Banca c/c ordinario', 'attivo', TRUE), ('1', '01', '03', 'Banca c/c vincolato', 'attivo', TRUE), ('1', '01', '04', 'Poste c/c', 'attivo', TRUE), -- CLASSE 2 - CREDITI E DEBITI ('2', '01', '01', 'Crediti vs condomini', 'attivo', TRUE), ('2', '01', '02', 'Crediti vs inquilini', 'attivo', TRUE), ('2', '02', '01', 'Debiti vs fornitori', 'passivo', TRUE), ('2', '02', '02', 'Debiti tributari', 'passivo', TRUE), ('2', '02', '03', 'Debiti previdenziali', 'passivo', TRUE), -- CLASSE 5 - COSTI ('5', '01', '01', 'Spese per energia elettrica', 'costo', TRUE), ('5', '01', '02', 'Spese per riscaldamento', 'costo', TRUE), ('5', '01', '03', 'Spese per acqua', 'costo', TRUE), ('5', '02', '01', 'Spese pulizie', 'costo', TRUE), ('5', '02', '02', 'Spese manutenzione ordinaria', 'costo', TRUE), ('5', '02', '03', 'Spese manutenzione straordinaria', 'costo', TRUE), ('5', '03', '01', 'Compensi amministratore', 'costo', TRUE), ('5', '03', '02', 'Spese legali', 'costo', TRUE), -- CLASSE 7 - RICAVI ('7', '01', '01', 'Quote condominiali ordinarie', 'ricavo', TRUE), ('7', '01', '02', 'Quote condominiali straordinarie', 'ricavo', TRUE), ('7', '02', '01', 'Interessi attivi bancari', 'ricavo', TRUE), ('7', '02', '02', 'Altri ricavi', 'ricavo', TRUE); ``` --- ## 📋 **MODULI AGGIUNTIVI - STRUTTURE PREVISTE** ### **Modulo Documenti** ```sql -- Gestione documenti CREATE TABLE documenti ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, stabile_id BIGINT UNSIGNED NOT NULL, unita_immobiliare_id BIGINT UNSIGNED NULL, soggetto_id BIGINT UNSIGNED NULL, user_id BIGINT UNSIGNED NOT NULL, titolo VARCHAR(255) NOT NULL, descrizione TEXT NULL, tipo_documento VARCHAR(100) NULL, categoria ENUM('generale', 'amministrativo', 'contabile', 'tecnico', 'legale') NOT NULL DEFAULT 'generale', nome_file VARCHAR(255) NOT NULL, path_file VARCHAR(500) NOT NULL, dimensione_file BIGINT UNSIGNED NULL, mime_type VARCHAR(100) NULL, is_public BOOLEAN DEFAULT FALSE, data_documento DATE NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE, FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id) ON DELETE CASCADE, FOREIGN KEY (soggetto_id) REFERENCES soggetti(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, INDEX idx_stabile (stabile_id), INDEX idx_unita (unita_immobiliare_id), INDEX idx_soggetto (soggetto_id), INDEX idx_categoria (categoria), INDEX idx_public (is_public), INDEX idx_data_documento (data_documento), INDEX idx_created_at (created_at), FULLTEXT idx_titolo_descrizione (titolo, descrizione) ); ``` ### **Modulo Assemblee** ```sql -- Assemblee condominiali CREATE TABLE assemblee ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, stabile_id BIGINT UNSIGNED NOT NULL, titolo VARCHAR(255) NOT NULL, data_assemblea DATETIME NOT NULL, luogo VARCHAR(255) NULL, tipo ENUM('ordinaria', 'straordinaria', 'urgente') NOT NULL DEFAULT 'ordinaria', stato ENUM('programmata', 'convocata', 'svolta', 'annullata') NOT NULL DEFAULT 'programmata', data_convocazione DATE NULL, data_seconda_convocazione DATETIME NULL, presidente_assemblea VARCHAR(255) NULL, segretario_assemblea VARCHAR(255) NULL, note TEXT NULL, verbale TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE, INDEX idx_stabile (stabile_id), INDEX idx_data_assemblea (data_assemblea), INDEX idx_stato (stato), INDEX idx_tipo (tipo) ); -- Ordine del giorno CREATE TABLE ordine_giorno ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, assemblea_id BIGINT UNSIGNED NOT NULL, numero_punto INT NOT NULL, argomento TEXT NOT NULL, relatore VARCHAR(255) NULL, proposta TEXT NULL, esito ENUM('approvato', 'respinto', 'rinviato', 'non_discusso') NULL, note_discussione TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (assemblea_id) REFERENCES assemblee(id) ON DELETE CASCADE, INDEX idx_assemblea (assemblea_id), INDEX idx_numero_punto (numero_punto), UNIQUE KEY unique_assemblea_punto (assemblea_id, numero_punto) ); -- Partecipazioni assemblee CREATE TABLE partecipazioni_assemblea ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, assemblea_id BIGINT UNSIGNED NOT NULL, soggetto_id BIGINT UNSIGNED NOT NULL, unita_immobiliare_id BIGINT UNSIGNED NOT NULL, presente BOOLEAN DEFAULT FALSE, delegato_a BIGINT UNSIGNED NULL, millesimi_rappresentati DECIMAL(8,4) NOT NULL, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (assemblea_id) REFERENCES assemblee(id) ON DELETE CASCADE, FOREIGN KEY (soggetto_id) REFERENCES soggetti(id) ON DELETE CASCADE, FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id) ON DELETE CASCADE, FOREIGN KEY (delegato_a) REFERENCES soggetti(id) ON DELETE SET NULL, INDEX idx_assemblea (assemblea_id), INDEX idx_soggetto (soggetto_id), INDEX idx_unita (unita_immobiliare_id), UNIQUE KEY unique_assemblea_unita (assemblea_id, unita_immobiliare_id) ); -- Votazioni CREATE TABLE votazioni ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ordine_giorno_id BIGINT UNSIGNED NOT NULL, soggetto_id BIGINT UNSIGNED NOT NULL, voto ENUM('favorevole', 'contrario', 'astenuto', 'non_partecipa') NOT NULL, millesimi_voto DECIMAL(8,4) NOT NULL, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (ordine_giorno_id) REFERENCES ordine_giorno(id) ON DELETE CASCADE, FOREIGN KEY (soggetto_id) REFERENCES soggetti(id) ON DELETE CASCADE, INDEX idx_ordine_giorno (ordine_giorno_id), INDEX idx_soggetto (soggetto_id), INDEX idx_voto (voto), UNIQUE KEY unique_voto_soggetto (ordine_giorno_id, soggetto_id) ); ``` ### **Modulo Manutenzioni** ```sql -- Fornitori CREATE TABLE fornitori ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ragione_sociale VARCHAR(255) NOT NULL, codice_fiscale VARCHAR(16) NULL, partita_iva VARCHAR(11) NULL, indirizzo VARCHAR(255) NULL, comune_id BIGINT UNSIGNED NULL, cap VARCHAR(10) NULL, telefono VARCHAR(20) NULL, email VARCHAR(255) NULL, email_pec VARCHAR(255) NULL, settore VARCHAR(100) NULL, specializzazioni TEXT NULL, is_active BOOLEAN DEFAULT TRUE, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (comune_id) REFERENCES comuni_italiani(id) ON DELETE SET NULL, INDEX idx_ragione_sociale (ragione_sociale), INDEX idx_partita_iva (partita_iva), INDEX idx_settore (settore), INDEX idx_active (is_active) ); -- Manutenzioni programmate CREATE TABLE manutenzioni ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, stabile_id BIGINT UNSIGNED NOT NULL, unita_immobiliare_id BIGINT UNSIGNED NULL, fornitore_id BIGINT UNSIGNED NULL, titolo VARCHAR(255) NOT NULL, descrizione TEXT NOT NULL, tipo ENUM('ordinaria', 'straordinaria', 'urgente', 'preventiva') NOT NULL DEFAULT 'ordinaria', stato ENUM('programmata', 'in_corso', 'completata', 'annullata', 'sospesa') NOT NULL DEFAULT 'programmata', priorita ENUM('bassa', 'media', 'alta', 'urgente') NOT NULL DEFAULT 'media', data_programmata DATE NOT NULL, data_inizio DATE NULL, data_completamento DATE NULL, costo_preventivato DECIMAL(10,2) NULL, costo_effettivo DECIMAL(10,2) NULL, responsabile_id BIGINT UNSIGNED NULL, note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE, FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id) ON DELETE CASCADE, FOREIGN KEY (fornitore_id) REFERENCES fornitori(id) ON DELETE SET NULL, FOREIGN KEY (responsabile_id) REFERENCES users(id) ON DELETE SET NULL, INDEX idx_stabile (stabile_id), INDEX idx_unita (unita_immobiliare_id), INDEX idx_fornitore (fornitore_id), INDEX idx_stato (stato), INDEX idx_tipo (tipo), INDEX idx_priorita (priorita), INDEX idx_data_programmata (data_programmata), INDEX idx_responsabile (responsabile_id) ); -- Interventi su manutenzioni CREATE TABLE interventi_manutenzione ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, manutenzione_id BIGINT UNSIGNED NOT NULL, data_intervento DATE NOT NULL, ora_inizio TIME NULL, ora_fine TIME NULL, tecnico_nome VARCHAR(255) NULL, tecnico_telefono VARCHAR(20) NULL, descrizione_intervento TEXT NOT NULL, materiali_utilizzati TEXT NULL, costo_intervento DECIMAL(10,2) NULL, stato ENUM('programmato', 'in_corso', 'completato', 'sospeso') NOT NULL DEFAULT 'programmato', note TEXT NULL, created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL, FOREIGN KEY (manutenzione_id) REFERENCES manutenzioni(id) ON DELETE CASCADE, INDEX idx_manutenzione (manutenzione_id), INDEX idx_data_intervento (data_intervento), INDEX idx_stato (stato) ); ``` --- ## 🔧 **BEST PRACTICES DATABASE** ### **1. Naming Convention** ```sql -- ✅ CORRETTO: Nomi italiani senza accenti CREATE TABLE registrazioni_contabili (...); CREATE TABLE piano_conti (...); CREATE TABLE unita_immobiliari (...); -- ❌ EVITARE: Nomi inglesi o con accenti CREATE TABLE accounting_records (...); CREATE TABLE unità_immobiliari (...); ``` ### **2. Indici per Performance** ```sql -- Indici su foreign keys ALTER TABLE registrazioni_contabili ADD INDEX idx_piano_conti (piano_conti_id); -- Indici su campi di ricerca ALTER TABLE soggetti ADD INDEX idx_codice_fiscale (codice_fiscale); -- Indici compositi per query frequenti ALTER TABLE piano_conti ADD INDEX idx_mastro_conto (mastro, conto, sottoconto); -- Fulltext per ricerche testuali ALTER TABLE documenti ADD FULLTEXT idx_titolo_descrizione (titolo, descrizione); ``` ### **3. Constraint e Validazione** ```sql -- Foreign keys con azioni appropriate FOREIGN KEY (stabile_id) REFERENCES stabili(id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT, FOREIGN KEY (comune_id) REFERENCES comuni_italiani(id) ON DELETE SET NULL, -- Check constraints per validazione ALTER TABLE registrazioni_contabili ADD CONSTRAINT chk_importi CHECK (importo_dare >= 0 AND importo_avere >= 0); -- Unique constraints per integrità UNIQUE KEY unique_stabile_numero (stabile_id, numero) ``` ### **4. Tipi di Dati Corretti** ```sql -- Importi: DECIMAL per precisione importo_dare DECIMAL(12,2) DEFAULT 0.00, -- Date: DATE per solo data, DATETIME per data+ora data_registrazione DATE NOT NULL, created_at TIMESTAMP NULL, -- Testi: VARCHAR per lunghezza fissa, TEXT per variabile codice_fiscale VARCHAR(16) NULL, descrizione TEXT NOT NULL, -- Boolean: BOOLEAN o TINYINT(1) is_active BOOLEAN DEFAULT TRUE, ``` --- ## 📊 **QUERY OTTIMIZZATE COMUNI** ### **1. Contabilità - Bilancio** ```sql -- Calcolo totali DARE/AVERE per gestione SELECT g.denominazione, g.anno, SUM(rc.importo_dare) as totale_dare, SUM(rc.importo_avere) as totale_avere, (SUM(rc.importo_dare) - SUM(rc.importo_avere)) as saldo FROM gestioni g LEFT JOIN registrazioni_contabili rc ON g.id = rc.gestione_id WHERE g.attivo = TRUE GROUP BY g.id, g.denominazione, g.anno ORDER BY g.anno DESC; ``` ### **2. Stabili - Statistiche Unità** ```sql -- Statistiche unità per stabile SELECT s.denominazione, COUNT(ui.id) as totale_unita, SUM(ui.millesimi_proprieta) as totale_millesimi, AVG(ui.superficie_catastale) as superficie_media FROM stabili s LEFT JOIN unita_immobiliari ui ON s.id = ui.stabile_id WHERE s.is_active = TRUE GROUP BY s.id, s.denominazione ORDER BY s.denominazione; ``` ### **3. Soggetti - Proprietari per Stabile** ```sql -- Lista proprietari attivi per stabile SELECT s.denominazione as stabile, ui.numero as unita, COALESCE( CONCAT(so.cognome, ' ', so.nome), so.ragione_sociale ) as proprietario, dr.quota_proprieta, ui.millesimi_proprieta FROM stabili s JOIN unita_immobiliari ui ON s.id = ui.stabile_id JOIN diritti_reali dr ON ui.id = dr.unita_immobiliare_id JOIN soggetti so ON dr.soggetto_id = so.id WHERE s.is_active = TRUE AND ui.is_active = TRUE AND dr.is_active = TRUE AND dr.tipo_diritto = 'proprietario' ORDER BY s.denominazione, ui.numero; ``` --- ## 🗂️ **MIGRATIONS LARAVEL** ### **Migration Base Contabilità** ```php id(); $table->string('mastro', 10); $table->string('conto', 10); $table->string('sottoconto', 10); $table->string('descrizione'); $table->enum('tipo', ['attivo', 'passivo', 'costo', 'ricavo']); $table->boolean('attivo')->default(true); $table->timestamps(); $table->index(['mastro', 'conto', 'sottoconto']); $table->index(['tipo']); $table->index(['attivo']); $table->index(['descrizione']); }); // Gestioni Schema::create('gestioni', function (Blueprint $table) { $table->id(); $table->string('denominazione'); $table->integer('anno'); $table->date('data_inizio'); $table->date('data_fine'); $table->boolean('attivo')->default(true); $table->foreignId('stabile_id')->nullable()->constrained('stabili')->onDelete('set null'); $table->timestamps(); $table->index(['anno']); $table->index(['attivo']); $table->index(['stabile_id']); $table->unique(['stabile_id', 'anno']); }); // Registrazioni contabili Schema::create('registrazioni_contabili', function (Blueprint $table) { $table->id(); $table->date('data_registrazione'); $table->string('numero_registrazione', 20)->nullable(); $table->text('descrizione'); $table->decimal('importo_dare', 12, 2)->default(0.00); $table->decimal('importo_avere', 12, 2)->default(0.00); $table->foreignId('piano_conti_id')->constrained('piano_conti')->onDelete('restrict'); $table->foreignId('gestione_id')->constrained('gestioni')->onDelete('restrict'); $table->foreignId('user_id')->constrained('users')->onDelete('restrict'); $table->string('documento_riferimento')->nullable(); $table->text('note')->nullable(); $table->timestamps(); $table->index(['data_registrazione']); $table->index(['piano_conti_id']); $table->index(['gestione_id']); $table->index(['user_id']); $table->index(['numero_registrazione']); }); } public function down(): void { Schema::dropIfExists('registrazioni_contabili'); Schema::dropIfExists('gestioni'); Schema::dropIfExists('piano_conti'); } }; ``` ### **Seeder Piano dei Conti** ```php insert([ 'mastro' => $mastro, 'conto' => $conto, 'sottoconto' => $sottoconto, 'descrizione' => $descrizione, 'tipo' => $tipo, 'attivo' => true, 'created_at' => now(), 'updated_at' => now(), ]); } $this->command->info('Piano dei conti standard caricato: ' . count($piano_conti) . ' conti'); } } ``` --- ## 🔍 **TROUBLESHOOTING DATABASE** ### **1. Errori di Connessione** ```bash # Test connessione database mysql -h 127.0.0.1 -u netgescon_user -p netgescon # Verifica privilegi utente SHOW GRANTS FOR 'netgescon_user'@'localhost'; # Reset password se necessario ALTER USER 'netgescon_user'@'localhost' IDENTIFIED BY 'NetGescon2024!'; FLUSH PRIVILEGES; ``` ### **2. Problemi Performance** ```sql -- Verifica indici mancanti SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'netgescon' AND COLUMN_NAME LIKE '%_id' AND TABLE_NAME NOT IN ( SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'netgescon' ); -- Analizza query lente SHOW PROCESSLIST; SELECT * FROM performance_schema.events_statements_summary_by_digest ORDER BY SUM_TIMER_WAIT DESC LIMIT 10; ``` ### **3. Problemi Integrità** ```sql -- Verifica foreign keys orfane SELECT rc.id, rc.piano_conti_id FROM registrazioni_contabili rc LEFT JOIN piano_conti pc ON rc.piano_conti_id = pc.id WHERE pc.id IS NULL; -- Ripristina integrità referenziale SET FOREIGN_KEY_CHECKS = 0; -- Operazioni di pulizia SET FOREIGN_KEY_CHECKS = 1; ``` --- ## 💾 **BACKUP E MANUTENZIONE** ### **Script Backup Strutturale** ```bash #!/bin/bash # backup-netgescon-structure.sh DB_NAME="netgescon" DB_USER="netgescon_user" DB_PASS="NetGescon2024!" BACKUP_DIR="/var/backups/netgescon" DATE=$(date +%Y%m%d_%H%M%S) mkdir -p $BACKUP_DIR # Backup solo struttura (per sviluppo) mysqldump -h 127.0.0.1 -u $DB_USER -p$DB_PASS \ --no-data \ --routines \ --triggers \ $DB_NAME > $BACKUP_DIR/netgescon_structure_$DATE.sql # Backup dati base (lookup tables) mysqldump -h 127.0.0.1 -u $DB_USER -p$DB_PASS \ --no-create-info \ --where="1=1" \ $DB_NAME \ comuni_italiani \ piano_conti \ roles \ permissions > $BACKUP_DIR/netgescon_base_data_$DATE.sql echo "✅ Backup strutturale completato:" echo " - Struttura: $BACKUP_DIR/netgescon_structure_$DATE.sql" echo " - Dati base: $BACKUP_DIR/netgescon_base_data_$DATE.sql" ``` ### **Manutenzione Routine** ```sql -- Ottimizzazione tabelle OPTIMIZE TABLE registrazioni_contabili; OPTIMIZE TABLE piano_conti; OPTIMIZE TABLE gestioni; -- Analisi statistiche per optimizer ANALYZE TABLE registrazioni_contabili; ANALYZE TABLE piano_conti; -- Pulizia log binari (attenzione in produzione!) PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 7 DAY); ``` --- ## 📈 **MONITORAGGIO E STATISTICHE** ### **Query Statistiche Sistema** ```sql -- Statistiche generali database SELECT TABLE_NAME, TABLE_ROWS, ROUND(DATA_LENGTH/1024/1024, 2) as 'Dimensione_MB', ROUND(INDEX_LENGTH/1024/1024, 2) as 'Indici_MB' FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'netgescon' ORDER BY DATA_LENGTH DESC; -- Conteggi record principali SELECT 'stabili' as tabella, COUNT(*) as records FROM stabili UNION ALL SELECT 'unita_immobiliari', COUNT(*) FROM unita_immobiliari UNION ALL SELECT 'soggetti', COUNT(*) FROM soggetti UNION ALL SELECT 'registrazioni_contabili', COUNT(*) FROM registrazioni_contabili UNION ALL SELECT 'users', COUNT(*) FROM users; ``` --- ## ✅ **CHECKLIST IMPLEMENTAZIONE DATABASE** ### **Setup Iniziale** - [ ] Database 'netgescon' creato - [ ] Utente 'netgescon_user' configurato - [ ] Privilegi assegnati correttamente - [ ] Connessione testata da Laravel ### **Tabelle Core** - [ ] users, roles, permissions (Spatie) - [ ] comuni_italiani caricati - [ ] stabili, unita_immobiliari - [ ] soggetti, diritti_reali ### **Modulo Contabilità** - [ ] piano_conti con dati standard - [ ] gestioni configurate - [ ] registrazioni_contabili funzionanti - [ ] Query bilancio testate ### **Indici e Performance** - [ ] Indici su foreign keys - [ ] Indici su campi di ricerca - [ ] Query ottimizzate per pagine principali - [ ] Performance monitoring attivo ### **Backup e Sicurezza** - [ ] Script backup automatico - [ ] Restore procedure testate - [ ] Accessi database limitati - [ ] Log delle modifiche attivato --- **🎯 QUESTO MANUALE È BASATO SULL'IMPLEMENTAZIONE REALE** Tutte le strutture database documentate sono state testate e validate nell'implementazione del modulo Contabilità. Le credenziali unificate garantiscono compatibilità tra tutti i moduli NetGescon. **📞 SUPPORTO DATABASE** - Utilizzare sempre le credenziali unificate documentate - Seguire le naming conventions italiane - Implementare indici per performance - Mantenere integrità referenziale **🔄 PROSSIMI AGGIORNAMENTI** - Strutture moduli Assemblee e Manutenzioni - Ottimizzazioni performance avanzate - Procedure stored per operazioni complesse - Replica e alta disponibilità