# 🏦 SISTEMA CONTABILE NETGESCON - PARTITA DOPPIA AVANZATA ## 📋 OVERVIEW Sistema contabile completo per condomini basato su partita doppia con gestione multi-esercizio, multi-gestione e protocolli separati. ## 🆕 NUOVE SPECIFICHE IMPLEMENTATE - **Maschera Unica di Registrazione:** Form unificato per tutte le tipologie di documenti - **Tabelle Millesimali Strutturate:** Gestione completa dei parametri di ripartizione - **Riconciliazione Bancaria Avanzata:** Algoritmi automatici per matching movimenti - **Triggers Automatici:** Aggiornamento saldi in real-time - **Backup Granulari:** Backup per singolo condominio con restore selettivo - **Compliance Fiscale:** Gestione automatica adempimenti fiscali e ritenute ## 🎯 PRINCIPI FONDAMENTALI ### 🔄 Partita Doppia Condominiale ``` DARE / AVERE = SEMPRE PAREGGIATO COSTI / RICAVI CREDITI / DEBITI ENTRATE / USCITE ATTIVITÀ / PASSIVITÀ ``` ### 🏢 "CEO Model" - Amministratore come CEO - **Zero Utili:** Condominio non può avere utili, solo pareggio - **Zero Sotto-Cassa:** Mai scendere sotto 0 nelle risorse - **Bilancio Sempre Quadrato:** Attività = Passività + Patrimonio - **Audit Completo:** Tracking di ogni modifica con chi/quando ### 📊 Gestione Multi-Protocollo - **Protocollo Generale:** Numerazione progressiva annuale (2025/0001, 2025/0002...) - **Protocolli per Gestione:** ORD2025/001, RISC2025/001, STR2025/001 - **Protocolli Bancari:** Separati per ogni conto corrente - **Protocolli Fiscali:** Per ritenute, F24, dichiarazioni --- ## 🗂️ STRUTTURA DATABASE CONTABILE ### 1️⃣ Piano dei Conti (3 Livelli) ```sql CREATE TABLE piano_conti ( id INT PRIMARY KEY AUTO_INCREMENT, condominio_id INT NOT NULL, codice VARCHAR(10) NOT NULL, -- 01.001.0001 (MASTRO.CONTO.SOTTOCONTO) mastro VARCHAR(2) NOT NULL, -- 01 conto VARCHAR(3) NOT NULL, -- 001 sottoconto VARCHAR(4) NOT NULL, -- 0001 denominazione VARCHAR(255) NOT NULL, tipo_conto ENUM('ATTIVO','PASSIVO','COSTO','RICAVO','PATRIMONIALE') NOT NULL, natura ENUM('DARE','AVERE') NOT NULL, gestione ENUM('TUTTE','ORDINARIA','RISCALDAMENTO','STRAORDINARIA') DEFAULT 'TUTTE', centro_costo VARCHAR(50) NULL, -- Per ripartizioni specifiche attivo BOOLEAN DEFAULT TRUE, saldo_dare DECIMAL(12,2) DEFAULT 0.00, saldo_avere DECIMAL(12,2) DEFAULT 0.00, saldo_finale DECIMAL(12,2) GENERATED ALWAYS AS (saldo_dare - saldo_avere) STORED, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, created_by INT, updated_by INT, UNIQUE KEY unique_conto_condominio (condominio_id, codice), FOREIGN KEY (condominio_id) REFERENCES condomini(id), INDEX idx_tipo_natura (tipo_conto, natura), INDEX idx_gestione (gestione), INDEX idx_centro_costo (centro_costo) ); ``` ### 🆕 2️⃣ Tabelle Millesimali Strutturate ```sql CREATE TABLE tabelle_millesimali ( id INT PRIMARY KEY AUTO_INCREMENT, condominio_id INT NOT NULL, denominazione VARCHAR(255) NOT NULL, -- "Millesimi Generali", "Riscaldamento", "Ascensore Piano 1-3" tipo_tabella ENUM('GENERALE','RISCALDAMENTO','ASCENSORE','SCALE','CORTILE','SPECIFICO') NOT NULL, descrizione TEXT, data_approvazione DATE NULL, verbale_assemblea VARCHAR(255) NULL, attiva BOOLEAN DEFAULT TRUE, formula_calcolo TEXT NULL, -- Formula matematica per calcolo automatico parametri_calcolo JSON NULL, -- {"metri_quadri": true, "vani": true, "piano": {"peso": 0.8}} totale_millesimi DECIMAL(8,3) DEFAULT 1000.000, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (condominio_id) REFERENCES condomini(id), INDEX idx_tipo_attiva (tipo_tabella, attiva) ); CREATE TABLE righe_millesimali ( id INT PRIMARY KEY AUTO_INCREMENT, tabella_id INT NOT NULL, unita_immobiliare_id INT NOT NULL, millesimi DECIMAL(8,3) NOT NULL, percentuale DECIMAL(6,3) GENERATED ALWAYS AS (millesimi / 1000 * 100) STORED, metri_quadri DECIMAL(8,2) NULL, vani DECIMAL(4,1) NULL, piano INT NULL, categoria_catastale VARCHAR(10) NULL, note TEXT, FOREIGN KEY (tabella_id) REFERENCES tabelle_millesimali(id) ON DELETE CASCADE, FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id), UNIQUE KEY unique_tabella_unita (tabella_id, unita_immobiliare_id), INDEX idx_millesimi (millesimi), INDEX idx_piano_categoria (piano, categoria_catastale) ); ``` ### 🆕 3️⃣ Sistema Ripartizioni Automatiche ```sql CREATE TABLE regole_ripartizione ( id INT PRIMARY KEY AUTO_INCREMENT, condominio_id INT NOT NULL, codice_regola VARCHAR(50) NOT NULL, -- "SPESE_GENERALI", "RISCALDAMENTO_CENTRALE", etc. denominazione VARCHAR(255) NOT NULL, conto_id INT NOT NULL, -- Conto del piano dei conti a cui applicare tabella_millesimale_id INT NOT NULL, tipo_ripartizione ENUM('MILLESIMI','TESTE','UNITA','METRI_QUADRI','CUSTOM') NOT NULL, formula_custom TEXT NULL, -- Formula personalizzata se tipo=CUSTOM soglia_minima DECIMAL(10,2) DEFAULT 0.00, -- Sotto questa soglia non ripartire attiva BOOLEAN DEFAULT TRUE, FOREIGN KEY (condominio_id) REFERENCES condomini(id), FOREIGN KEY (conto_id) REFERENCES piano_conti(id), FOREIGN KEY (tabella_millesimale_id) REFERENCES tabelle_millesimali(id), UNIQUE KEY unique_conto_regola (condominio_id, conto_id), INDEX idx_attiva (attiva) ); ``` ### 🆕 4️⃣ Maschera Unica di Registrazione ```sql CREATE TABLE documenti_contabili ( id INT PRIMARY KEY AUTO_INCREMENT, condominio_id INT NOT NULL, gestione_id INT NOT NULL, numero_protocollo VARCHAR(20) NOT NULL, -- Protocollo unificato data_documento DATE NOT NULL, data_registrazione DATE NOT NULL, data_competenza_da DATE NOT NULL, data_competenza_a DATE NOT NULL, data_scadenza DATE NULL, -- TIPO DOCUMENTO tipo_documento ENUM('FATTURA_ATTIVA','FATTURA_PASSIVA','RICEVUTA','BONIFICO', 'VERSAMENTO','NOTA_CREDITO','NOTA_DEBITO','GIROCONTO', 'REGISTRAZIONE_MANUALE','STORNO') NOT NULL, categoria_documento VARCHAR(100) NULL, -- "Manutenzione", "Utenze", "Assicurazioni" -- SOGGETTI fornitore_id INT NULL, condomino_id INT NULL, descrizione_soggetto VARCHAR(255) NULL, -- Per soggetti occasionali -- IMPORTI E FISCALE importo_imponibile DECIMAL(10,2) DEFAULT 0.00, importo_iva DECIMAL(10,2) DEFAULT 0.00, importo_totale DECIMAL(10,2) NOT NULL, ritenuta_acconto DECIMAL(10,2) DEFAULT 0.00, percentuale_ritenuta DECIMAL(5,2) DEFAULT 0.00, causale_ritenuta VARCHAR(100) NULL, codice_iva VARCHAR(20) NULL, split_payment BOOLEAN DEFAULT FALSE, reverse_charge BOOLEAN DEFAULT FALSE, -- DOCUMENTO ORIGINALE numero_documento VARCHAR(100) NULL, serie_documento VARCHAR(20) NULL, data_documento_originale DATE NULL, -- WORKFLOW E STATO stato ENUM('BOZZA','VALIDATO','CONTABILIZZATO','PAGATO','INCASSATO','ANNULLATO') DEFAULT 'BOZZA', workflow_step ENUM('INSERIMENTO','VALIDAZIONE','CONTABILIZZAZIONE','PAGAMENTO','CHIUSURA') DEFAULT 'INSERIMENTO', -- RIPARTIZIONE AUTOMATICA ripartizione_automatica BOOLEAN DEFAULT TRUE, regola_ripartizione_id INT NULL, tabella_millesimale_id INT NULL, -- TRACKING E AUDIT note TEXT, urgente BOOLEAN DEFAULT FALSE, validato_da INT NULL, validato_at TIMESTAMP NULL, contabilizzato_da INT NULL, contabilizzato_at TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, created_by INT NOT NULL, updated_by INT, FOREIGN KEY (condominio_id) REFERENCES condomini(id), FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id), FOREIGN KEY (fornitore_id) REFERENCES fornitori(id), FOREIGN KEY (condomino_id) REFERENCES condomini_proprietari(id), FOREIGN KEY (regola_ripartizione_id) REFERENCES regole_ripartizione(id), FOREIGN KEY (tabella_millesimale_id) REFERENCES tabelle_millesimali(id), INDEX idx_protocollo (numero_protocollo), INDEX idx_stato_workflow (stato, workflow_step), INDEX idx_competenza (data_competenza_da, data_competenza_a), INDEX idx_scadenze (data_scadenza, stato) ); ``` ### 🆕 5️⃣ Riconciliazione Bancaria Avanzata ```sql CREATE TABLE riconciliazioni_bancarie ( id INT PRIMARY KEY AUTO_INCREMENT, conto_bancario_id INT NOT NULL, periodo_da DATE NOT NULL, periodo_a DATE NOT NULL, saldo_estratto_conto DECIMAL(12,2) NOT NULL, saldo_contabile DECIMAL(12,2) NOT NULL, differenza DECIMAL(12,2) GENERATED ALWAYS AS (saldo_estratto_conto - saldo_contabile) STORED, stato ENUM('APERTA','RICONCILIATA','CHIUSA','SOSPESA') DEFAULT 'APERTA', algoritmo_matching ENUM('AUTOMATICO','MANUALE','MISTO') DEFAULT 'AUTOMATICO', soglia_matching DECIMAL(10,2) DEFAULT 0.01, -- Tolleranza per matching automatico movimenti_non_riconciliati INT DEFAULT 0, note TEXT, riconciliata_da INT NULL, riconciliata_at TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (conto_bancario_id) REFERENCES conti_bancari(id), FOREIGN KEY (riconciliata_da) REFERENCES users(id), INDEX idx_periodo (periodo_da, periodo_a), INDEX idx_stato (stato) ); CREATE TABLE movimenti_riconciliazione ( id INT PRIMARY KEY AUTO_INCREMENT, riconciliazione_id INT NOT NULL, movimento_bancario_id INT NULL, -- Movimento da estratto conto transazione_contabile_id INT NULL, -- Movimento da contabilità tipo_matching ENUM('ESATTO','APPROSSIMATO','MANUALE','AUTOMATICO') NOT NULL, confidence_score DECIMAL(3,2) DEFAULT 1.00, -- Punteggio di affidabilità match differenza_importo DECIMAL(10,2) DEFAULT 0.00, differenza_data INT DEFAULT 0, -- Giorni di differenza note_riconciliazione TEXT, validato BOOLEAN DEFAULT FALSE, FOREIGN KEY (riconciliazione_id) REFERENCES riconciliazioni_bancarie(id) ON DELETE CASCADE, FOREIGN KEY (movimento_bancario_id) REFERENCES movimenti_bancari(id), FOREIGN KEY (transazione_contabile_id) REFERENCES transazioni_contabili(id), INDEX idx_matching (tipo_matching, confidence_score), INDEX idx_validato (validato) ); ``` ### 🆕 6️⃣ Sistema Backup Granulari ```sql CREATE TABLE backup_snapshot ( id INT PRIMARY KEY AUTO_INCREMENT, condominio_id INT NULL, -- NULL = backup completo sistema tipo_backup ENUM('COMPLETO','INCREMENTALE','CONDOMINIO','GESTIONE','TABELLA') NOT NULL, tabella_target VARCHAR(100) NULL, -- Per backup di singola tabella gestione_id INT NULL, -- Per backup di singola gestione descrizione VARCHAR(255) NOT NULL, dimensione_bytes BIGINT DEFAULT 0, percorso_file VARCHAR(500) NOT NULL, hash_integrità VARCHAR(64) NOT NULL, -- SHA-256 del file compresso BOOLEAN DEFAULT TRUE, crittografato BOOLEAN DEFAULT TRUE, password_hash VARCHAR(255) NULL, stato ENUM('IN_CORSO','COMPLETATO','FALLITO','CORROTTO') DEFAULT 'IN_CORSO', data_inizio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, data_fine TIMESTAMP NULL, durata_secondi INT NULL, created_by INT NOT NULL, FOREIGN KEY (condominio_id) REFERENCES condomini(id), FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id), FOREIGN KEY (created_by) REFERENCES users(id), INDEX idx_tipo_stato (tipo_backup, stato), INDEX idx_condominio_data (condominio_id, data_inizio) ); CREATE TABLE restore_log ( id INT PRIMARY KEY AUTO_INCREMENT, backup_snapshot_id INT NOT NULL, tipo_restore ENUM('COMPLETO','PARZIALE','TABELLA','RECORD') NOT NULL, target_condominio_id INT NULL, target_gestione_id INT NULL, filtri_restore JSON NULL, -- Filtri applicati durante restore records_processati INT DEFAULT 0, records_restaurati INT DEFAULT 0, records_saltati INT DEFAULT 0, errori_riscontrati INT DEFAULT 0, log_dettaglio LONGTEXT NULL, stato ENUM('IN_CORSO','COMPLETATO','FALLITO','ANNULLATO') DEFAULT 'IN_CORSO', data_inizio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, data_fine TIMESTAMP NULL, restaurato_da INT NOT NULL, FOREIGN KEY (backup_snapshot_id) REFERENCES backup_snapshot(id), FOREIGN KEY (target_condominio_id) REFERENCES condomini(id), FOREIGN KEY (target_gestione_id) REFERENCES gestioni_contabili(id), FOREIGN KEY (restaurato_da) REFERENCES users(id), INDEX idx_stato_data (stato, data_inizio) ); ``` --- ## 🆕 TRIGGERS AUTOMATICI AVANZATI ### 📊 Trigger Aggiornamento Saldi Real-Time ```sql DELIMITER // -- Trigger per aggiornamento saldi piano conti CREATE TRIGGER tr_aggiorna_saldi_piano_conti_insert AFTER INSERT ON righe_movimenti_contabili FOR EACH ROW BEGIN IF NEW.tipo_movimento = 'DARE' THEN UPDATE piano_conti SET saldo_dare = saldo_dare + NEW.importo, updated_at = CURRENT_TIMESTAMP, updated_by = NEW.created_by WHERE id = NEW.conto_id; ELSE UPDATE piano_conti SET saldo_avere = saldo_avere + NEW.importo, updated_at = CURRENT_TIMESTAMP, updated_by = NEW.created_by WHERE id = NEW.conto_id; END IF; END// -- Trigger per aggiornamento saldi bancari CREATE TRIGGER tr_aggiorna_saldi_bancari AFTER INSERT ON movimenti_bancari FOR EACH ROW BEGIN DECLARE delta_importo DECIMAL(12,2); IF NEW.tipo_movimento = 'ENTRATA' THEN SET delta_importo = NEW.importo; ELSE SET delta_importo = -NEW.importo; END IF; UPDATE conti_bancari SET saldo_attuale = saldo_attuale + delta_importo, data_ultimo_movimento = NEW.data_movimento, updated_at = CURRENT_TIMESTAMP WHERE id = NEW.conto_bancario_id; END// -- Trigger controllo quadratura automatica CREATE TRIGGER tr_verifica_quadratura AFTER INSERT ON righe_movimenti_contabili FOR EACH ROW BEGIN DECLARE totale_dare DECIMAL(12,2) DEFAULT 0; DECLARE totale_avere DECIMAL(12,2) DEFAULT 0; SELECT COALESCE(SUM(CASE WHEN tipo_movimento = 'DARE' THEN importo ELSE 0 END), 0), COALESCE(SUM(CASE WHEN tipo_movimento = 'AVERE' THEN importo ELSE 0 END), 0) INTO totale_dare, totale_avere FROM righe_movimenti_contabili WHERE transazione_id = NEW.transazione_id; UPDATE transazioni_contabili SET quadratura_ok = (totale_dare = totale_avere), importo_totale = totale_dare, updated_at = CURRENT_TIMESTAMP WHERE id = NEW.transazione_id; END// -- Trigger per ripartizione automatica CREATE TRIGGER tr_ripartizione_automatica AFTER UPDATE ON documenti_contabili FOR EACH ROW BEGIN DECLARE done INT DEFAULT FALSE; DECLARE v_unita_id INT; DECLARE v_millesimi DECIMAL(8,3); DECLARE v_importo_ripartito DECIMAL(10,2); DECLARE cur_unita CURSOR FOR SELECT ui.id, rm.millesimi FROM unita_immobiliari ui JOIN righe_millesimali rm ON ui.id = rm.unita_immobiliare_id WHERE rm.tabella_id = NEW.tabella_millesimale_id AND ui.condominio_id = NEW.condominio_id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- Esegui ripartizione solo se documento validato e ripartizione automatica abilitata IF NEW.stato = 'VALIDATO' AND NEW.ripartizione_automatica = TRUE AND OLD.stato != 'VALIDATO' AND NEW.tabella_millesimale_id IS NOT NULL THEN OPEN cur_unita; read_loop: LOOP FETCH cur_unita INTO v_unita_id, v_millesimi; IF done THEN LEAVE read_loop; END IF; SET v_importo_ripartito = (NEW.importo_totale * v_millesimi / 1000); -- Inserisci riga di ripartizione per ogni unità immobiliare INSERT INTO ripartizioni_spese ( documento_id, unita_immobiliare_id, importo_ripartito, millesimi_applicati, created_at ) VALUES ( NEW.id, v_unita_id, v_importo_ripartito, v_millesimi, CURRENT_TIMESTAMP ); END LOOP; CLOSE cur_unita; END IF; END// DELIMITER ; ``` ### 🆕 Stored Procedures per Operazioni Complesse ```sql DELIMITER // -- Procedura per chiusura gestione contabile CREATE PROCEDURE sp_chiudi_gestione_contabile( IN p_gestione_id INT, IN p_user_id INT, OUT p_result VARCHAR(255) ) BEGIN DECLARE v_totale_costi DECIMAL(12,2) DEFAULT 0; DECLARE v_totale_ricavi DECIMAL(12,2) DEFAULT 0; DECLARE v_conguaglio DECIMAL(12,2) DEFAULT 0; DECLARE v_stato_attuale VARCHAR(20); DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SET p_result = 'ERRORE: Impossibile chiudere la gestione'; END; START TRANSACTION; -- Verifica stato gestione SELECT stato INTO v_stato_attuale FROM gestioni_contabili WHERE id = p_gestione_id; IF v_stato_attuale != 'APERTA' THEN SET p_result = 'ERRORE: La gestione non è in stato APERTA'; ROLLBACK; ELSE -- Calcola totali SELECT COALESCE(SUM(CASE WHEN pc.tipo_conto = 'COSTO' THEN pc.saldo_finale ELSE 0 END), 0), COALESCE(SUM(CASE WHEN pc.tipo_conto = 'RICAVO' THEN pc.saldo_finale ELSE 0 END), 0) INTO v_totale_costi, v_totale_ricavi FROM piano_conti pc JOIN gestioni_contabili gc ON pc.condominio_id = gc.condominio_id WHERE gc.id = p_gestione_id AND (pc.gestione = gc.tipo_gestione OR pc.gestione = 'TUTTE'); SET v_conguaglio = v_totale_ricavi - v_totale_costi; -- Aggiorna gestione UPDATE gestioni_contabili SET stato = 'CHIUSA', data_chiusura = CURRENT_DATE, totale_costi = v_totale_costi, totale_ricavi = v_totale_ricavi, conguaglio = v_conguaglio, saldo_finale = v_conguaglio, updated_at = CURRENT_TIMESTAMP, updated_by = p_user_id WHERE id = p_gestione_id; -- Crea bilancio di chiusura INSERT INTO bilanci_chiusura ( condominio_id, gestione_id, data_chiusura, totale_costi, totale_ricavi, conguaglio_gestione ) SELECT condominio_id, id, CURRENT_DATE, v_totale_costi, v_totale_ricavi, v_conguaglio FROM gestioni_contabili WHERE id = p_gestione_id; COMMIT; SET p_result = CONCAT('SUCCESS: Gestione chiusa. Conguaglio: €', v_conguaglio); END IF; END// -- Procedura per riconciliazione bancaria automatica CREATE PROCEDURE sp_riconciliazione_automatica( IN p_conto_bancario_id INT, IN p_periodo_da DATE, IN p_periodo_a DATE, IN p_soglia_matching DECIMAL(10,2), OUT p_movimenti_riconciliati INT ) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE v_mov_bancario_id INT; DECLARE v_mov_importo DECIMAL(10,2); DECLARE v_mov_data DATE; DECLARE v_mov_descrizione TEXT; DECLARE v_transazione_id INT; DECLARE v_confidence DECIMAL(3,2); DECLARE cur_movimenti CURSOR FOR SELECT id, importo, data_movimento, descrizione FROM movimenti_bancari WHERE conto_bancario_id = p_conto_bancario_id AND data_movimento BETWEEN p_periodo_da AND p_periodo_a AND riconciliato = FALSE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; SET p_movimenti_riconciliati = 0; OPEN cur_movimenti; riconcilia_loop: LOOP FETCH cur_movimenti INTO v_mov_bancario_id, v_mov_importo, v_mov_data, v_mov_descrizione; IF done THEN LEAVE riconcilia_loop; END IF; -- Cerca corrispondenza nelle transazioni contabili SELECT tc.id, 1.00 INTO v_transazione_id, v_confidence FROM transazioni_contabili tc JOIN righe_movimenti_contabili rmc ON tc.id = rmc.transazione_id JOIN piano_conti pc ON rmc.conto_id = pc.id JOIN conti_bancari cb ON pc.id = cb.conto_piano_conti_id WHERE cb.id = p_conto_bancario_id AND ABS(rmc.importo - ABS(v_mov_importo)) <= p_soglia_matching AND ABS(DATEDIFF(tc.data_transazione, v_mov_data)) <= 3 AND tc.id NOT IN ( SELECT transazione_contabile_id FROM movimenti_riconciliazione WHERE transazione_contabile_id IS NOT NULL ) ORDER BY ABS(rmc.importo - ABS(v_mov_importo)), ABS(DATEDIFF(tc.data_transazione, v_mov_data)) LIMIT 1; -- Se trovata corrispondenza, crea record di riconciliazione IF v_transazione_id IS NOT NULL THEN INSERT INTO movimenti_riconciliazione ( riconciliazione_id, movimento_bancario_id, transazione_contabile_id, tipo_matching, confidence_score, validato ) VALUES ( (SELECT id FROM riconciliazioni_bancarie WHERE conto_bancario_id = p_conto_bancario_id AND periodo_da = p_periodo_da AND periodo_a = p_periodo_a LIMIT 1), v_mov_bancario_id, v_transazione_id, 'AUTOMATICO', v_confidence, TRUE ); UPDATE movimenti_bancari SET riconciliato = TRUE, riconciliato_at = CURRENT_TIMESTAMP WHERE id = v_mov_bancario_id; SET p_movimenti_riconciliati = p_movimenti_riconciliati + 1; END IF; SET v_transazione_id = NULL; END LOOP; CLOSE cur_movimenti; END// DELIMITER ; ``` --- ## 🆕 VISTE AVANZATE PER REPORTING ### 📊 Vista Situazione Contabile Generale ```sql CREATE VIEW v_situazione_contabile AS SELECT c.id as condominio_id, c.denominazione as condominio, gc.anno_riferimento, gc.tipo_gestione, gc.stato as stato_gestione, -- Totali per tipo conto SUM(CASE WHEN pc.tipo_conto = 'ATTIVO' THEN pc.saldo_finale ELSE 0 END) as totale_attivo, SUM(CASE WHEN pc.tipo_conto = 'PASSIVO' THEN pc.saldo_finale ELSE 0 END) as totale_passivo, SUM(CASE WHEN pc.tipo_conto = 'COSTO' THEN pc.saldo_finale ELSE 0 END) as totale_costi, SUM(CASE WHEN pc.tipo_conto = 'RICAVO' THEN pc.saldo_finale ELSE 0 END) as totale_ricavi, -- Indicatori (SUM(CASE WHEN pc.tipo_conto = 'ATTIVO' THEN pc.saldo_finale ELSE 0 END) - SUM(CASE WHEN pc.tipo_conto = 'PASSIVO' THEN pc.saldo_finale ELSE 0 END)) as patrimonio_netto, (SUM(CASE WHEN pc.tipo_conto = 'RICAVO' THEN pc.saldo_finale ELSE 0 END) - SUM(CASE WHEN pc.tipo_conto = 'COSTO' THEN pc.saldo_finale ELSE 0 END)) as risultato_gestione, gc.budget_preventivo, gc.saldo_finale as saldo_effettivo, -- Liquidità SUM(CASE WHEN cb.tipo_conto IN ('BANCARIO','POSTALE','CASSA') THEN cb.saldo_attuale ELSE 0 END) as liquidita_totale FROM condomini c JOIN gestioni_contabili gc ON c.id = gc.condominio_id JOIN piano_conti pc ON c.id = pc.condominio_id LEFT JOIN conti_bancari cb ON c.id = cb.condominio_id AND cb.attivo = TRUE WHERE pc.attivo = TRUE GROUP BY c.id, gc.id; ``` ### 📊 Vista Scadenzario Completo ```sql CREATE VIEW v_scadenzario_completo AS SELECT 'DOCUMENTO' as tipo_scadenza, dc.id as riferimento_id, dc.condominio_id, dc.descrizione_soggetto as descrizione, dc.data_scadenza, dc.importo_totale as importo, dc.stato, 'PAGAMENTO' as azione_richiesta, DATEDIFF(dc.data_scadenza, CURRENT_DATE) as giorni_scadenza, CASE WHEN dc.data_scadenza < CURRENT_DATE THEN 'SCADUTO' WHEN DATEDIFF(dc.data_scadenza, CURRENT_DATE) <= 7 THEN 'IN_SCADENZA' ELSE 'OK' END as urgenza FROM documenti_contabili dc WHERE dc.data_scadenza IS NOT NULL AND dc.stato NOT IN ('PAGATO','INCASSATO','ANNULLATO') UNION ALL SELECT 'RITENUTA' as tipo_scadenza, rf.id as riferimento_id, rf.condominio_id, CONCAT('Ritenuta ', rf.mese_competenza, ' - ', f.ragione_sociale) as descrizione, rf.data_scadenza_versamento as data_scadenza, rf.importo_ritenuta as importo, CASE WHEN rf.versata THEN 'VERSATA' ELSE 'DA_VERSARE' END as stato, 'VERSAMENTO_F24' as azione_richiesta, DATEDIFF(rf.data_scadenza_versamento, CURRENT_DATE) as giorni_scadenza, CASE WHEN rf.data_scadenza_versamento < CURRENT_DATE AND NOT rf.versata THEN 'SCADUTO' WHEN DATEDIFF(rf.data_scadenza_versamento, CURRENT_DATE) <= 3 AND NOT rf.versata THEN 'IN_SCADENZA' ELSE 'OK' END as urgenza FROM ritenute_fiscali rf JOIN fornitori f ON rf.fornitore_id = f.id WHERE rf.versata = FALSE ORDER BY data_scadenza ASC; ``` --- ## 🚀 IMPLEMENTAZIONE LARAVEL ### 🎨 Form Unico di Registrazione Il sistema implementa una maschera unica che si adatta dinamicamente al tipo di documento: ```php // Controller per maschera unica class DocumentoContabileController extends Controller { public function create(Request $request) { $tipoDocumento = $request->get('tipo', 'FATTURA_PASSIVA'); $gestioni = GestioneContabile::where('condominio_id', auth()->user()->condominio_id) ->where('stato', 'APERTA')->get(); $fornitori = Fornitore::where('condominio_id', auth()->user()->condominio_id)->get(); $tabelleMillesimali = TabellaMillesimale::where('condominio_id', auth()->user()->condominio_id) ->where('attiva', true)->get(); return view('contabilita.documenti.create', compact( 'tipoDocumento', 'gestioni', 'fornitori', 'tabelleMillesimali' )); } public function store(StoreDocumentoRequest $request) { DB::transaction(function() use ($request) { // Crea documento $documento = DocumentoContabile::create($request->validated()); // Se ripartizione automatica abilitata, eseguila if ($request->ripartizione_automatica) { $this->eseguiRipartizioneAutomatica($documento); } // Crea movimenti contabili se stato = VALIDATO if ($request->stato === 'VALIDATO') { $this->creaMovimentiContabili($documento); } }); return redirect()->route('contabilita.documenti.index') ->with('success', 'Documento registrato con successo'); } } ``` ### 🏦 Dashboard Contabile ```php class ContabilitaController extends Controller { public function dashboard() { $condominioId = auth()->user()->condominio_id; $situazioneContabile = DB::table('v_situazione_contabile') ->where('condominio_id', $condominioId) ->first(); $scadenzario = DB::table('v_scadenzario_completo') ->where('condominio_id', $condominioId) ->where('urgenza', '!=', 'OK') ->orderBy('giorni_scadenza') ->limit(10) ->get(); $liquidita = ContoBancario::where('condominio_id', $condominioId) ->where('attivo', true) ->sum('saldo_attuale'); return view('contabilita.dashboard', compact( 'situazioneContabile', 'scadenzario', 'liquidita' )); } } ``` --- ## 📱 ESEMPI PRATICI WORKFLOW ### 💡 Workflow Completo: Fattura ENEL ```sql -- 1. Registrazione in maschera unica INSERT INTO documenti_contabili ( condominio_id, gestione_id, numero_protocollo, tipo_documento, data_documento, data_registrazione, data_competenza_da, data_competenza_a, fornitore_id, importo_totale, descrizione_soggetto, ripartizione_automatica, tabella_millesimale_id, created_by ) VALUES ( 1, 1, 'DOC2025/001', 'FATTURA_PASSIVA', '2025-01-31', '2025-02-01', '2025-01-01', '2025-01-31', 15, 100.00, 'Fattura energia elettrica gennaio', TRUE, 1, 1 ); -- 2. Trigger automatico crea ripartizioni -- (Eseguito automaticamente al cambio stato in VALIDATO) -- 3. Creazione transazione contabile automatica INSERT INTO transazioni_contabili ( condominio_id, gestione_id, documento_id, numero_transazione, data_transazione, data_competenza, descrizione, importo_totale, tipo_transazione, created_by ) VALUES ( 1, 1, 1, 'TC2025/001', '2025-02-01', '2025-01-31', 'Registrazione fattura ENEL', 100.00, 'REGISTRAZIONE', 1 ); -- 4. Righe contabili partita doppia INSERT INTO righe_movimenti_contabili (transazione_id, conto_id, tipo_movimento, importo) VALUES (1, 45, 'DARE', 100.00), -- Costo Energia Elettrica (1, 78, 'AVERE', 100.00); -- Debito vs ENEL -- 5. Pagamento successivo INSERT INTO transazioni_contabili ( condominio_id, gestione_id, numero_transazione, data_transazione, descrizione, importo_totale, tipo_transazione, created_by ) VALUES ( 1, 1, 'TC2025/002', '2025-03-31', 'Pagamento fattura ENEL', 100.00, 'PAGAMENTO', 1 ); INSERT INTO righe_movimenti_contabili (transazione_id, conto_id, tipo_movimento, importo) VALUES (2, 78, 'DARE', 100.00), -- Chiusura debito ENEL (2, 12, 'AVERE', 100.00); -- Uscita da C/C bancario -- 6. Riconciliazione bancaria automatica CALL sp_riconciliazione_automatica(1, '2025-03-01', '2025-03-31', 0.01, @riconciliati); ``` --- ## 🚀 BENEFICI DEL SISTEMA AVANZATO ### ✅ **Vantaggi Operativi** - **Maschera Unica:** Un solo form per tutti i tipi di documento - **Ripartizione Automatica:** Calcolo millesimale istantaneo - **Quadratura Real-Time:** Bilancio sempre controllato - **Workflow Guidato:** Processo step-by-step assistito ### ✅ **Vantaggi Fiscali** - **Compliance Automatica:** Adempimenti fiscali automatizzati - **Scadenzario Intelligente:** Alert preventivi su scadenze - **F24 Automatici:** Generazione modelli precompilati - **Controllo Ritenute:** Gestione completa ritenute d'acconto ### ✅ **Vantaggi Audit e Sicurezza** - **Backup Granulari:** Restore selettivo per condominio - **Audit Completo:** Tracciabilità totale ogni modifica - **Riconciliazione Automatica:** Controllo movimenti bancari - **Integrità Garantita:** Hash e controlli di integrità ### ✅ **Vantaggi Analitici** - **Reportistica Avanzata:** Viste preconfigurate per analisi - **Dashboard Real-Time:** Situazione sempre aggiornata - **KPI Automatici:** Indicatori di performance calcolati - **Drill-Down Completo:** Da sintesi a dettaglio in un click --- *Sistema Contabile NetGesCon v3.0* *Implementazione Avanzata: Gennaio 2025* *🚀 Ready for Production*