# ๐ฐ IMPLEMENTAZIONE SISTEMA CONTABILE PARTITA DOPPIA CON GESTIONI MULTIPLE ## ๐ **OVERVIEW IMPLEMENTAZIONE** Sistema contabile condominiale in partita doppia con gestioni multiple (ORDINARIA, RISCALDAMENTO, STRAORDINARIA) integrate con chiusura e riapertura contabile classica. --- ## ๐ฏ **PRINCIPI FONDAMENTALI** ### ๐ **Gestioni Multiple per Condominio** ``` ๐ข CONDOMINIO โโโ ๐ GESTIONE ORDINARIA (spese comuni) โโโ ๐ฅ GESTIONE RISCALDAMENTO (spese termiche) โโโ โก GESTIONE STRAORDINARIA (lavori straordinari) ``` ### ๐ **Partita Doppia con Gestioni** ```sql -- Ogni movimento contabile รจ collegato a: registrazione_contabile { gestione_id, -- FK alla tabella gestioni tipo_gestione, -- ENUM('ORDINARIA','RISCALDAMENTO','STRAORDINARIA') dare_totale, -- Totale DARE avere_totale -- Totale AVERE (deve essere = dare_totale) } ``` ### ๐ **Chiusura e Riapertura Contabile** 1. **CHIUSURA GESTIONE**: Movimenti di chiusura a Stato Patrimoniale e Conto Economico 2. **RIAPERTURA GESTIONE**: Riporto saldi patrimoniali alla gestione successiva --- ## ๐๏ธ **SCHEMA DATABASE AGGIORNATO** ### 1๏ธโฃ **Tabella: `gestioni_contabili` (ESTESA)** ```sql -- AGGIORNAMENTO tabella esistente ALTER TABLE gestioni_contabili ADD COLUMN IF NOT EXISTS tipo_gestione ENUM('ORDINARIA','RISCALDAMENTO','STRAORDINARIA') NOT NULL DEFAULT 'ORDINARIA'; ALTER TABLE gestioni_contabili ADD COLUMN IF NOT EXISTS gestione_precedente_id BIGINT UNSIGNED NULL; ALTER TABLE gestioni_contabili ADD COLUMN IF NOT EXISTS saldi_apertura JSON NULL; ALTER TABLE gestioni_contabili ADD COLUMN IF NOT EXISTS saldi_chiusura JSON NULL; -- Indici aggiuntivi ALTER TABLE gestioni_contabili ADD INDEX idx_tipo_gestione (tipo_gestione); ALTER TABLE gestioni_contabili ADD INDEX idx_condominio_tipo (condominio_id, tipo_gestione); ``` ### 2๏ธโฃ **Tabella: `registrazioni_contabili` (AGGIORNATA)** ```sql -- AGGIORNAMENTO per gestioni multiple ALTER TABLE registrazioni_contabili ADD COLUMN IF NOT EXISTS tipo_gestione ENUM('ORDINARIA','RISCALDAMENTO','STRAORDINARIA') NOT NULL DEFAULT 'ORDINARIA'; ALTER TABLE registrazioni_contabili ADD COLUMN IF NOT EXISTS ritenuta_acconto DECIMAL(10,4) DEFAULT 0; ALTER TABLE registrazioni_contabili ADD COLUMN IF NOT EXISTS percentuale_ritenuta DECIMAL(5,2) DEFAULT 0; ALTER TABLE registrazioni_contabili ADD COLUMN IF NOT EXISTS codice_ritenuta VARCHAR(10); ALTER TABLE registrazioni_contabili ADD COLUMN IF NOT EXISTS imponibile_ritenuta DECIMAL(12,4) DEFAULT 0; -- Indici per performance ALTER TABLE registrazioni_contabili ADD INDEX idx_gestione_tipo (gestione_id, tipo_gestione); ALTER TABLE registrazioni_contabili ADD INDEX idx_ritenuta (ritenuta_acconto); ``` ### 3๏ธโฃ **Nuova Tabella: `ripartizioni_gestioni`** ```sql CREATE TABLE ripartizioni_gestioni ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, registrazione_id BIGINT UNSIGNED NOT NULL, movimento_id BIGINT UNSIGNED NOT NULL, -- ๐ฏ COLLEGAMENTO GESTIONI gestione_ordinaria_perc DECIMAL(5,2) DEFAULT 0, -- % su gestione ordinaria gestione_riscaldamento_perc DECIMAL(5,2) DEFAULT 0, -- % su gestione riscaldamento gestione_straordinaria_perc DECIMAL(5,2) DEFAULT 0, -- % su gestione straordinaria -- ๐ฐ IMPORTI RIPARTITI importo_ordinaria DECIMAL(12,4) DEFAULT 0, importo_riscaldamento DECIMAL(12,4) DEFAULT 0, importo_straordinaria DECIMAL(12,4) DEFAULT 0, -- ๐ TABELLE MILLESIMALI tabella_ordinaria VARCHAR(50) DEFAULT 'GENERALE', tabella_riscaldamento VARCHAR(50) DEFAULT 'RISCALDAMENTO', tabella_straordinaria VARCHAR(50) DEFAULT 'GENERALE', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (registrazione_id) REFERENCES registrazioni_contabili(id) ON DELETE CASCADE, FOREIGN KEY (movimento_id) REFERENCES movimenti_contabili(id) ON DELETE CASCADE, INDEX idx_registrazione (registrazione_id), INDEX idx_movimento (movimento_id), -- CONSTRAINT: La somma delle percentuali deve essere 100% CONSTRAINT chk_percentuali_totale CHECK ( gestione_ordinaria_perc + gestione_riscaldamento_perc + gestione_straordinaria_perc = 100 ) ) ENGINE=InnoDB COMMENT='Ripartizione movimenti tra gestioni multiple'; ``` ### 4๏ธโฃ **Nuova Tabella: `chiusure_riaperture_contabili`** ```sql CREATE TABLE chiusure_riaperture_contabili ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, gestione_id BIGINT UNSIGNED NOT NULL, -- ๐ฏ TIPO OPERAZIONE tipo_operazione ENUM('CHIUSURA','RIAPERTURA') NOT NULL, data_operazione DATE NOT NULL, -- ๐ DATI CHIUSURA/RIAPERTURA saldi_conti JSON NOT NULL, -- Saldi di tutti i conti totale_stato_patrimoniale DECIMAL(12,4), -- Totale SP totale_conto_economico DECIMAL(12,4), -- Totale CE risultato_gestione DECIMAL(12,4), -- Utile/Perdita -- ๐ COLLEGAMENTO RIAPERTURA chiusura_precedente_id BIGINT UNSIGNED NULL, -- Link alla chiusura precedente -- ๐ CONTROLLI confermata BOOLEAN DEFAULT FALSE, confermata_da BIGINT UNSIGNED, confermata_il TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by BIGINT UNSIGNED NOT NULL, FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id) ON DELETE RESTRICT, FOREIGN KEY (chiusura_precedente_id) REFERENCES chiusure_riaperture_contabili(id), FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT, INDEX idx_gestione_tipo (gestione_id, tipo_operazione), INDEX idx_data (data_operazione), INDEX idx_confermata (confermata) ) ENGINE=InnoDB COMMENT='Chiusure e riaperture contabili per gestione'; ``` --- ## ๐จ **INTERFACCIA UTENTE - SPECIFICA SCHERMATA** ### ๐ **Maschera Registrazione Contabile Avanzata** ```php // STRUTTURA FORM REGISTRAZIONE [ // ๐ SEZIONE INTESTAZIONE 'data_operazione' => 'required|date', 'causale' => 'required|string|max:500', 'importo_totale' => 'required|numeric|min:0.01', // ๐ฏ GESTIONI (CHECKBOX MULTIPLE) 'gestioni' => [ 'ordinaria' => ['attiva' => true, 'percentuale' => 70], 'riscaldamento' => ['attiva' => true, 'percentuale' => 30], 'straordinaria' => ['attiva' => false, 'percentuale' => 0] ], // ๐ฐ SEZIONE RITENUTA D'ACCONTO 'ritenuta_section' => [ 'applica_ritenuta' => true, 'codice_ritenuta' => 'R001', // Select da tabella ritenute 'percentuale_ritenuta' => 20.00, 'imponibile_ritenuta' => 1000.00, 'importo_ritenuta' => 200.00 // Calcolato automaticamente ], // ๐ SEZIONE RIGHE CONTABILI (DARE/AVERE) 'righe_contabili' => [ [ 'sottoconto_id' => 1, 'descrizione' => 'Pulizie scale marzo', 'importo_dare' => 1000.00, 'importo_avere' => 0, 'ripartizione_gestioni' => [ 'ordinaria' => 70, 'riscaldamento' => 30 ] ], [ 'sottoconto_id' => 2, 'descrizione' => 'Ritenuta d\'acconto 20%', 'importo_dare' => 200.00, 'importo_avere' => 0 ], [ 'sottoconto_id' => 3, 'descrizione' => 'Pagamento bonifico', 'importo_dare' => 0, 'importo_avere' => 1200.00 ] ] ] ``` ### ๐จ **Layout Schermata HTML** ```html
``` --- ## โ๏ธ **WORKFLOW IMPLEMENTAZIONE** ### 1๏ธโฃ **Models Laravel** ```php // GestioneContabile.php (AGGIORNATO) class GestioneContabile extends Model { protected $fillable = [ 'condominio_id', 'denominazione', 'tipo_gestione', 'data_inizio', 'data_fine_prevista', 'stato', 'gestione_precedente_id', 'saldi_apertura', 'saldi_chiusura' ]; protected $casts = [ 'saldi_apertura' => 'array', 'saldi_chiusura' => 'array', 'data_inizio' => 'date', 'data_fine_prevista' => 'date' ]; // Relazione con registrazioni public function registrazioni() { return $this->hasMany(RegistrazioneContabile::class, 'gestione_id'); } // Calcolo saldi automatico public function calcolaSaldi() { // Implementazione calcolo saldi DARE/AVERE } } // RegistrazioneContabile.php (AGGIORNATO) class RegistrazioneContabile extends Model { protected $fillable = [ 'gestione_id', 'tipo_gestione', 'data_operazione', 'causale', 'importo_totale', 'ritenuta_acconto', 'percentuale_ritenuta', 'codice_ritenuta' ]; // Relazione gestioni multiple public function ripartizioniGestioni() { return $this->hasMany(RipartizioneGestione::class, 'registrazione_id'); } // Verifica quadratura public function isQuadrata() { $dare = $this->movimenti()->sum('importo_dare'); $avere = $this->movimenti()->sum('importo_avere'); return abs($dare - $avere) < 0.01; } } ``` ### 2๏ธโฃ **Controller Avanzato** ```php // ContabilitaAvanzataController.php class ContabilitaAvanzataController extends Controller { public function creaRegistrazione(Request $request) { DB::beginTransaction(); try { // 1. Validazione input $validated = $this->validateRegistrazione($request); // 2. Creazione registrazione principale $registrazione = $this->creaRegistrazionePrincipale($validated); // 3. Creazione movimenti DARE/AVERE $this->creaMovimentiContabili($registrazione, $validated['righe']); // 4. Gestione ripartizioni multiple gestioni $this->creaRipartizioniGestioni($registrazione, $validated['gestioni']); // 5. Calcolo ripartizione condomini $this->calcolaRipartizioneCondomini($registrazione); // 6. Verifica quadratura finale if (!$registrazione->isQuadrata()) { throw new Exception('Partita doppia non bilanciata'); } DB::commit(); return response()->json(['success' => true, 'id' => $registrazione->id]); } catch (Exception $e) { DB::rollback(); return response()->json(['error' => $e->getMessage()], 400); } } public function chiusuraGestione($gestioneId) { // Implementazione chiusura contabile $gestione = GestioneContabile::findOrFail($gestioneId); // 1. Calcolo saldi finali tutti i sottoconti $saldiFinali = $this->calcolaSaldiFinali($gestione); // 2. Creazione registrazioni di chiusura $this->creaRegistrazioniChiusura($gestione, $saldiFinali); // 3. Aggiornamento stato gestione $gestione->update(['stato' => 'chiusa_definitiva']); } public function riaperturaGestione($nuovaGestioneId, $precedenteGestioneId) { // Implementazione riapertura con riporto saldi } } ``` ### 3๏ธโฃ **JavaScript Frontend** ```javascript // contabilita-avanzata.js class ContabilitaAvanzata { constructor() { this.inizializzaForm(); this.bindEvents(); } inizializzaForm() { // Inizializzazione form e validazioni this.calcolaTotali(); this.verificaQuadratura(); } aggiungiRiga() { // Aggiunge una nuova riga alla tabella movimenti const nuovaRiga = this.creaNuovaRigaTemplate(); $('#righe-contabili-table tbody').append(nuovaRiga); this.bindEventsRiga(); } calcolaTotali() { let totaleDare = 0; let totaleAvere = 0; $('.importo-dare').each(function() { totaleDare += parseFloat($(this).val()) || 0; }); $('.importo-avere').each(function() { totaleAvere += parseFloat($(this).val()) || 0; }); $('#totale-dare').text(totaleDare.toFixed(2)); $('#totale-avere').text(totaleAvere.toFixed(2)); this.verificaQuadratura(totaleDare, totaleAvere); } verificaQuadratura(dare, avere) { const differenza = Math.abs(dare - avere); const status = $('#quadratura-status'); if (differenza < 0.01) { status.removeClass('badge-warning badge-danger') .addClass('badge-success') .text('โ Bilanciato'); } else { status.removeClass('badge-success badge-danger') .addClass('badge-warning') .text(`โ ๏ธ Differenza: ${differenza.toFixed(2)}`); } } calcolaRipartizione() { // Calcola la ripartizione automatica tra gestioni const formData = new FormData($('#registrazione-contabile-form')[0]); $.post('/api/calcola-ripartizione', formData) .done(function(response) { // Aggiorna la UI con i risultati this.aggiornaRipartizione(response.ripartizioni); }.bind(this)); } salvaRegistrazione() { if (!this.validaForm()) return; const formData = new FormData($('#registrazione-contabile-form')[0]); $.post('/api/registrazioni-contabili', formData) .done(function(response) { Swal.fire('Successo!', 'Registrazione salvata correttamente', 'success'); window.location.href = '/admin/contabilita'; }) .fail(function(xhr) { Swal.fire('Errore!', xhr.responseJSON.error, 'error'); }); } } // Inizializzazione $(document).ready(function() { new ContabilitaAvanzata(); }); ``` --- ## ๐ **CHECKLIST IMPLEMENTAZIONE** ### โ **Database** - [ ] Eseguire migration gestioni multiple - [ ] Aggiornare tabelle esistenti - [ ] Creare nuove tabelle ripartizioni - [ ] Implementare trigger calcolo saldi ### โ **Backend Laravel** - [ ] Aggiornare Models esistenti - [ ] Creare ContabilitaAvanzataController - [ ] Implementare API per calcoli - [ ] Creare Service per chiusura/riapertura ### โ **Frontend** - [ ] Creare form registrazione avanzato - [ ] Implementare JavaScript calcoli - [ ] Integrare con sistema esistente - [ ] Test interfaccia utente ### โ **Integrazione** - [ ] Collegare con sistema esistente stabili - [ ] Implementare ripartizione millesimale - [ ] Test con dati reali - [ ] Validazione chiusura/riapertura --- ## ๐ฏ **PROSSIMI PASSI** 1. **๐ค TRASFERIMENTO DOCUMENTAZIONE**: Copia questo file sulla VM 2. **๐พ IMPLEMENTAZIONE DATABASE**: Eseguire le migration 3. **๐จ SVILUPPO INTERFACCIA**: Creare le schermate 4. **๐ INTEGRAZIONE**: Collegare con sistema esistente 5. **๐ TEST**: Validare con dati reali Questa documentazione fornisce tutte le specifiche per implementare il sistema contabile avanzato con gestioni multiple e partita doppia classica! ๐๐ฐ