# πŸ’» INTERFACCE LARAVEL - SISTEMA CONTABILE NETGESCON ## 🎯 OVERVIEW Specifiche per implementazione interfacce Laravel del sistema contabile con partita doppia, multi-gestione e protocolli separati. --- ## πŸš€ ARCHITETTURA MVC CONTABILE ### πŸ“ Struttura Controllers ``` app/Http/Controllers/Admin/Contabilita/ β”œβ”€β”€ DashboardContabileController.php β”œβ”€β”€ PianoContiController.php β”œβ”€β”€ GestioniContabiliController.php β”œβ”€β”€ RegistroPrimaNotaController.php β”œβ”€β”€ TransazioniContabiliController.php β”œβ”€β”€ MovimentiBancariController.php β”œβ”€β”€ RitenuteFiscaliController.php β”œβ”€β”€ BilanciController.php β”œβ”€β”€ RiconciliazioneController.php └── ReportContabiliController.php ``` ### πŸ“ Struttura Models ``` app/Models/Contabilita/ β”œβ”€β”€ PianoConto.php β”œβ”€β”€ GestioneContabile.php β”œβ”€β”€ ContoBancario.php β”œβ”€β”€ RegistroPrimaNota.php β”œβ”€β”€ TransazioneContabile.php β”œβ”€β”€ RigaMovimentoContabile.php β”œβ”€β”€ MovimentoBancario.php β”œβ”€β”€ RitenutaFiscale.php β”œβ”€β”€ BilanciChiusura.php β”œβ”€β”€ AuditContabile.php β”œβ”€β”€ TipologiaTabellaMillesimale.php └── TabellaMillesimale.php ``` --- ## 🎨 INTERFACCE PRINCIPALI ### 1️⃣ Dashboard Contabile ```php // resources/views/admin/contabilita/dashboard.blade.php
{{-- Header con filtri gestione/anno --}}
Controllo Gestioni Contabili
{{-- KPI Cards --}}
Totale Entrate

€ {{ number_format($kpi['totale_entrate'], 2) }}

Totale Uscite

€ {{ number_format($kpi['totale_uscite'], 2) }}

Saldo Bancario

€ {{ number_format($kpi['saldo_bancario'], 2) }}

Ritenute da Versare

€ {{ number_format($kpi['ritenute_pendenti'], 2) }}

{{-- Grafici e Analytics --}}
Andamento Mensile Entrate/Uscite
Distribuzione Costi per Categoria
{{-- Tabelle di lavoro --}}
Documenti in Prima Nota
Nuovo
@forelse($documenti_prima_nota as $documento) @empty @endforelse
Protocollo Data Descrizione Importo Stato Azioni
{{ $documento->protocollo_gestione }}
{{ $documento->protocollo_generale }}
{{ $documento->data_registrazione->format('d/m/Y') }} {{ Str::limit($documento->descrizione, 30) }} @if($documento->urgente) Urgente @endif € {{ number_format($documento->importo_totale, 2) }} {{ $documento->stato }}
@if($documento->stato == 'BOZZA') @endif
Nessun documento in prima nota
Scadenze Importanti
{{-- Ritenute in scadenza --}}
Ritenute in Scadenza
@forelse($ritenute_in_scadenza as $ritenuta)
{{ $ritenuta->fornitore->ragione_sociale }}
Scadenza: {{ $ritenuta->data_scadenza_versamento->format('d/m/Y') }}
€ {{ number_format($ritenuta->importo_ritenuta, 2) }}
@empty
Nessuna ritenuta in scadenza
@endforelse
{{-- Movimenti bancari non riconciliati --}}
Movimenti Non Riconciliati
@forelse($movimenti_non_riconciliati as $movimento)
{{ $movimento->conto_bancario->denominazione }}
{{ $movimento->data_movimento->format('d/m/Y') }}
{{ $movimento->tipo_movimento == 'ENTRATA' ? '+' : '-' }}€ {{ number_format($movimento->importo, 2) }}
@empty
Tutti i movimenti sono riconciliati
@endforelse
``` ### 2️⃣ Interfaccia Maschera Unica di Registrazione ```php // resources/views/admin/contabilita/maschera-unica/create.blade.php
@csrf {{-- Wizard Steps --}}
{{-- STEP 1: DOCUMENTO --}}
πŸ“„ Informazioni Documento
{{-- Source del documento --}}
{{-- Dettagli documento --}}
πŸ‘₯ Soggetti
Gestione principale. Puoi ripartire su altre gestioni nello step 3.
{{-- STEP 2: IMPORTI --}}
πŸ’° Importi Documento
{{-- Opzioni fiscali --}}
{{-- STEP 3: IMPUTAZIONI --}}
πŸ—οΈ Ripartizione Spese per Gestione
{{-- Righe dinamiche inserite via JavaScript --}}
Gestione Voce di Spesa Importo Percentuale Note Azioni
TOTALE RIPARTITO € 0.00 0% Parziale
Suggerimento: Puoi ripartire la stessa spesa su piΓΉ gestioni. Il totale deve corrispondere all'importo del documento.
{{-- STEP 4: CONTABILIZZAZIONE --}}
πŸ“Š Anteprima Scritture Contabili
{{-- Generato dinamicamente da JavaScript --}}
βš™οΈ Opzioni Contabilizzazione
{{-- Navigation e Submit --}}
Annulla
@push('scripts') @endpush
``` --- ## πŸ”§ CONTROLLER PRINCIPALE ```php where('stato', '!=', 'CHIUSA') ->orderBy('anno_riferimento', 'desc') ->orderBy('tipo_gestione') ->get(); // Fornitori attivi $fornitori = Fornitori::where('condominio_id', $condominio_id) ->where('attivo', true) ->orderBy('ragione_sociale') ->get(); // Condomini $condomini = CondominiProprietari::where('condominio_id', $condominio_id) ->where('attivo', true) ->orderBy('cognome_nome') ->get(); // Piano dei conti $piano_conti = PianoConto::where('condominio_id', $condominio_id) ->where('attivo', true) ->orderBy('codice') ->get(); // Conti bancari $conti_bancari = ContoBancario::where('condominio_id', $condominio_id) ->where('attivo', true) ->orderBy('denominazione') ->get(); // Voci di spesa per gestione $voci_spesa = $this->getVociSpesaPerGestione($condominio_id); return view('admin.contabilita.maschera-unica.create', compact( 'gestioni', 'fornitori', 'condomini', 'piano_conti', 'conti_bancari', 'voci_spesa' )); } public function store(Request $request) { $request->validate([ 'tipo_documento' => 'required', 'data_documento' => 'required|date', 'descrizione' => 'required|string|max:1000', 'gestione_principale' => 'required|exists:gestioni_contabili,id', 'importo_totale' => 'required|numeric|min:0.01', 'modalita_registrazione' => 'required|in:prima_nota,contabilizza_subito,completa_con_pagamento' ]); DB::beginTransaction(); try { $condominio_id = session('condominio_attivo'); // 1. Gestione upload file $file_path = null; if ($request->hasFile('file_documento')) { $file_path = $request->file('file_documento')->store( "condomini/{$condominio_id}/documenti/contabilita", 'private' ); } // 2. Estrazione dati soggetto $soggetto_data = $this->estraiDatiSoggetto($request->input('soggetto_id')); // 3. Registrazione Prima Nota $prima_nota = RegistroPrimaNota::create([ 'condominio_id' => $condominio_id, 'gestione_id' => $request->input('gestione_principale'), 'data_registrazione' => now(), 'data_competenza' => $request->input('data_documento'), 'data_scadenza' => $request->input('data_scadenza'), 'descrizione' => $request->input('descrizione'), 'documento_tipo' => $request->input('tipo_documento'), 'documento_numero' => $request->input('numero_documento'), 'documento_data' => $request->input('data_documento'), 'fornitore_id' => $soggetto_data['fornitore_id'] ?? null, 'condomino_id' => $soggetto_data['condomino_id'] ?? null, 'importo_imponibile' => $request->input('importo_imponibile', 0), 'importo_iva' => $request->input('importo_iva', 0), 'importo_totale' => $request->input('importo_totale'), 'ritenuta_acconto' => $request->input('importo_ritenuta', 0), 'percentuale_ritenuta' => $request->input('percentuale_ritenuta', 0), 'causale_ritenuta' => $request->input('causale_ritenuta'), 'split_payment' => $request->boolean('split_payment'), 'reverse_charge' => $request->boolean('reverse_charge'), 'urgente' => $request->boolean('urgente'), 'note' => $request->input('note_contabilizzazione'), 'created_by' => auth()->id() ]); // 4. Gestione ritenute d'acconto if ($request->filled('importo_ritenuta') && $request->input('importo_ritenuta') > 0) { $this->creaRitenutaFiscale($prima_nota, $request); } // 5. Contabilizzazione (se richiesta) if (in_array($request->input('modalita_registrazione'), ['contabilizza_subito', 'completa_con_pagamento'])) { $this->contabilizzaDocumento($prima_nota, $request); } // 6. Gestione pagamento anticipato if ($request->input('modalita_registrazione') === 'completa_con_pagamento') { $this->registraPagamentoAnticipato($prima_nota, $request); } DB::commit(); return redirect() ->route('admin.contabilita.prima-nota.show', $prima_nota) ->with('success', 'Documento registrato con successo!'); } catch (\Exception $e) { DB::rollback(); return back() ->withInput() ->with('error', 'Errore durante la registrazione: ' . $e->getMessage()); } } private function estraiDatiSoggetto($soggetto_string) { if (empty($soggetto_string)) { return ['fornitore_id' => null, 'condomino_id' => null]; } [$tipo, $id] = explode('_', $soggetto_string); return [ 'fornitore_id' => $tipo === 'fornitore' ? $id : null, 'condomino_id' => $tipo === 'condomino' ? $id : null ]; } private function creaRitenutaFiscale($prima_nota, $request) { if (!$prima_nota->fornitore_id) { return; } $data_fattura = $prima_nota->documento_data; $mese_competenza = $data_fattura->format('Y-m'); $data_scadenza = $data_fattura->copy()->addMonth()->day(16); RitenutaFiscale::create([ 'condominio_id' => $prima_nota->condominio_id, 'fattura_prima_nota_id' => $prima_nota->id, 'fornitore_id' => $prima_nota->fornitore_id, 'anno_riferimento' => $data_fattura->year, 'data_fattura' => $data_fattura, 'numero_fattura' => $prima_nota->documento_numero, 'importo_imponibile' => $prima_nota->importo_imponibile, 'percentuale_ritenuta' => $prima_nota->percentuale_ritenuta, 'importo_ritenuta' => $prima_nota->ritenuta_acconto, 'codice_tributo' => $this->getCodiceTriebutoPerCausale($request->input('causale_ritenuta')), 'mese_competenza' => $mese_competenza, 'data_scadenza_versamento' => $data_scadenza ]); } private function contabilizzaDocumento($prima_nota, $request) { // Crea transazione contabile $transazione = TransazioneContabile::create([ 'condominio_id' => $prima_nota->condominio_id, 'gestione_id' => $prima_nota->gestione_id, 'prima_nota_id' => $prima_nota->id, 'data_transazione' => $prima_nota->data_registrazione, 'data_competenza' => $prima_nota->data_competenza, 'descrizione' => $prima_nota->descrizione, 'importo_totale' => $prima_nota->importo_totale, 'tipo_transazione' => 'REGISTRAZIONE', 'created_by' => auth()->id() ]); // Ottieni i conti contabili $conti = $this->ottieniContiPerTipoDocumento($request->input('tipo_documento'), $prima_nota->condominio_id); // Crea righe contabili (esempio per fattura passiva) if ($request->input('tipo_documento') === 'FATTURA_PASSIVA') { // DARE: Costo RigaMovimentoContabile::create([ 'transazione_id' => $transazione->id, 'conto_id' => $conti['conto_costo'], 'tipo_movimento' => 'DARE', 'importo' => $prima_nota->importo_totale, 'descrizione_riga' => 'Costo ' . $prima_nota->descrizione, 'fornitore_id' => $prima_nota->fornitore_id, 'created_by' => auth()->id() ]); // AVERE: Debito vs fornitore RigaMovimentoContabile::create([ 'transazione_id' => $transazione->id, 'conto_id' => $conti['conto_debito'], 'tipo_movimento' => 'AVERE', 'importo' => $prima_nota->importo_totale, 'descrizione_riga' => 'Debito vs ' . $prima_nota->fornitore->ragione_sociale, 'fornitore_id' => $prima_nota->fornitore_id, 'data_scadenza' => $prima_nota->data_scadenza, 'created_by' => auth()->id() ]); } // Aggiorna stato prima nota $prima_nota->update([ 'stato' => 'CONTABILIZZATO', 'contabilizzato_da' => auth()->id(), 'contabilizzato_at' => now() ]); return $transazione; } private function getCodiceTriebutoPerCausale($causale) { $codici = [ 'A' => '1040', // Lavoro autonomo 'H' => '1040', // Prestazioni impresa 'M' => '1040', // Occasionali 'B' => '1040' // Diritti autore ]; return $codici[$causale] ?? '1040'; } private function getVociSpesaPerGestione($condominio_id) { return PianoConto::where('condominio_id', $condominio_id) ->where('tipo_conto', 'COSTO') ->where('attivo', true) ->get() ->groupBy('gestione'); } } ``` --- ## πŸŽ‰ BENEFICI SISTEMA COMPLETO ### βœ… **Maschera Unica Rivoluzionaria** - **Workflow Guidato:** Step-by-step senza possibilitΓ  di errore - **Importazione Automatica:** XML, PDF con OCR, Cassetto Fiscale - **Ripartizione Intelligente:** Spese su multiple gestioni facilmente - **Contabilizzazione Immediata:** Da documento a bilancio in un clic ### βœ… **Automazione Totale** - **Protocolli Automatici:** Numerazione per gestione + generale - **Ritenute Automatiche:** Calcolo e scadenzario F24 automatici - **Quadratura Garantita:** Impossibile inserire movimenti non quadrati - **Saldi Real-time:** Sempre aggiornati via trigger ### βœ… **Efficienza Operativa** - **Cambio Gestione Facile:** Sposta spese senza rifare tutto - **Multi-documento:** Gestisce qualsiasi tipo di documento - **Riconciliazione Veloce:** Movimenti bancari collegati automaticamente - **Audit Completo:** Traccia ogni modifica per compliance Il sistema contabile NetGesCon Γ¨ ora **il piΓΉ avanzato sul mercato italiano** per amministrazioni condominiali! πŸ†