# 📋 LOG SVILUPPO NETGESCON - 22 LUGLIO 2025 ## Sistema Seeder Documenti Demo Persistenti --- ### 📅 NAVIGAZIONE LOG - **📁 Log Precedente**: [`LOG-SVILUPPO-LUGLIO-2025.md`](./LOG-SVILUPPO-LUGLIO-2025.md) - Sessione 21/07/2025 - **📁 Log Successivo**: `LOG-SVILUPPO-23-LUGLIO-2025.md` - Prossima sessione - **📁 Documentazione Master**: [`00-COPILOT-MASTER-GUIDE.md`](./00-COPILOT-MASTER-GUIDE.md) - **📁 Manuale Tecnico**: [`MANUALE-TECNICO-RISOLUZIONE-PROBLEMI.md`](./MANUALE-TECNICO-RISOLUZIONE-PROBLEMI.md) --- ## 🎯 OBIETTIVO SESSIONE **Implementare sistema seeder per documenti demo persistenti** che non si cancellino al refresh della pagina, permettendo una gestione documentale continua e realistica. ### 📋 RICHIESTA UTENTE > "utilizza l'account di netgescon User: netgescon_user e PW:NetGescon2024!" > "Continue to iterate?" **Problema Identificato**: I documenti demo erano hardcoded in JavaScript e si perdevano ad ogni refresh della pagina. --- ## 🚀 IMPLEMENTAZIONI REALIZZATE ### 1. **SEEDER DOCUMENTI DEMO PERSISTENTI** #### File Creato: `/database/seeders/DocumentiDemoSeeder.php` ```php where('is_demo', true)->exists()) { if (isset($this->command)) { $this->command->info('Documenti demo già esistenti. Skip...'); } return; } // Ottieni primo stabile per collegamento $stabileId = DB::table('stabili')->first()?->id ?? 1; $documenti = [ [ 'stabile_id' => $stabileId, 'nome' => 'Contratto Assicurazione Multirischi 2025', 'nome_file' => 'contratto_assicurazione_2025.pdf', 'path_file' => 'demo/contratti/assicurazione_2025.pdf', 'tipologia' => 'contratto', 'fornitore' => 'Assicurazioni Generali SpA', 'data_documento' => '2025-01-15', 'data_scadenza' => '2025-12-31', 'importo_collegato' => 2450.00, 'categoria_spesa' => 'spese_ordinarie', 'tags' => 'assicurazione,multirischi,annuale,importante', 'note' => 'Contratto assicurativo per copertura responsabilità civile...', 'numero_protocollo' => 'ASS-2025-001', 'numero_pagine' => 15, 'estensione' => 'pdf', 'contenuto_ocr' => 'CONTRATTO DI ASSICURAZIONE MULTIRISCHI...', 'urgente' => false, 'is_demo' => true, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now(), ], // ... altri 7 documenti demo ]; // Inserisci documenti in batch per performance DB::table('documenti')->insert($documenti); } } ``` **💡 APPUNTI IMPORTANTI**: - Usa `DB::table()` invece di Eloquent per performance migliori con inserimenti di massa - Campo `is_demo` per distinguere dati demo da dati reali - Controllo esistenza documenti per evitare duplicati - Compatibilità con command line interface tramite `isset($this->command)` ### 2. **COMANDO ARTISAN PERSONALIZZATO** #### File Creato: `/app/Console/Commands/DocumentiDemoCommand.php` ```php info('🚀 NetGescon - Creazione Documenti Demo Persistenti'); $this->info('================================================'); if ($this->option('force')) { $this->warn('⚠️ Modalità FORCE attivata - ricreo tutti i documenti demo'); \DB::table('documenti')->where('is_demo', true)->delete(); \DB::table('etichette_protocollo')->truncate(); } try { $seeder = new DocumentiDemoSeeder(); $seeder->run(); $count = \DB::table('documenti')->where('is_demo', true)->count(); $this->info("✅ Operazione completata con successo!"); $this->info("📄 Documenti demo creati: {$count}"); return Command::SUCCESS; } catch (\Exception $e) { $this->error("❌ Errore durante la creazione dei documenti demo:"); $this->error($e->getMessage()); return Command::FAILURE; } } } ``` **📝 USO DEL COMANDO**: ```bash # Crea documenti demo (se non esistono già) php artisan netgescon:demo-documenti # Forza ricreazione (cancella e ricrea tutto) php artisan netgescon:demo-documenti --force ``` ### 3. **MIGRATION COLONNE AVANZATE DOCUMENTI** #### File Creato: `/database/migrations/2025_07_22_075105_add_advanced_columns_to_documenti_table.php` ```php public function up() { Schema::table('documenti', function (Blueprint $table) { // Verifica se le colonne non esistono già if (!Schema::hasColumn('documenti', 'stabile_id')) { $table->foreignId('stabile_id')->nullable()->constrained('stabili')->onDelete('cascade'); } if (!Schema::hasColumn('documenti', 'tipologia')) { $table->enum('tipologia', [ 'fattura', 'ricevuta', 'contratto', 'preventivo', 'verbale', 'comunicazione', 'relazione_tecnica', 'certificato', 'planimetria', 'foto', 'altro' ])->nullable(); } // ... altre colonne if (!Schema::hasColumn('documenti', 'is_demo')) { $table->boolean('is_demo')->default(false); } }); // Aggiungi indici per performance Schema::table('documenti', function (Blueprint $table) { $indexNames = collect(\DB::select("SHOW INDEX FROM documenti"))->pluck('Key_name'); if (!$indexNames->contains('documenti_stabile_tipologia_index')) { $table->index(['stabile_id', 'tipologia'], 'documenti_stabile_tipologia_index'); } if (!$indexNames->contains('documenti_is_demo_index')) { $table->index(['is_demo']); } }); } ``` **⚠️ PROBLEMI RISOLTI**: 1. **Tabella esistente**: La migration `create_documenti_table` falliva perché la tabella esisteva già - **Soluzione**: Rimossa la migration di creazione, tenuta solo quella di aggiornamento 2. **Colonna mancante**: `dimensione_file` non era presente nello schema esistente - **Soluzione**: Rimossa dal seeder per compatibilità con schema attuale ### 4. **MODEL DOCUMENTO ESTESO** #### File Modificato: `/app/Models/Documento.php` ```php class Documento extends Model { protected $fillable = [ // Campi legacy per compatibilità 'documentable_id', 'documentable_type', 'nome_file', 'path_file', 'tipo_documento', 'mime_type', 'descrizione', 'xml_data', 'hash_file', // Nuovi campi per sistema avanzato 'stabile_id', 'unita_id', 'utente_id', 'nome', 'tipologia', 'fornitore', 'data_documento', 'data_scadenza', 'importo_collegato', 'categoria_spesa', 'tags', 'note', 'numero_protocollo', // ... altri campi ]; protected $casts = [ 'xml_data' => 'array', 'metadati_ocr' => 'array', 'data_documento' => 'date', 'data_scadenza' => 'date', 'importo_collegato' => 'decimal:2', 'approvato' => 'boolean', 'urgente' => 'boolean', 'is_demo' => 'boolean', ]; // Scopes avanzati public function scopeDemo($query) { return $query->where('is_demo', true); } public function scopeUrgenti($query) { return $query->where('urgente', true); } public function scopeInScadenza($query, $giorni = 30) { return $query->whereNotNull('data_scadenza') ->where('data_scadenza', '<=', Carbon::now()->addDays($giorni)); } // Accessor per tags array public function getTagsArrayAttribute() { return $this->tags ? explode(',', $this->tags) : []; } // Metodi utilità public function generaNumeroProtocollo() { $prefisso = strtoupper(substr($this->tipologia ?? 'DOC', 0, 4)); $anno = Carbon::now()->year; $ultimoNumero = static::where('numero_protocollo', 'like', "{$prefisso}-{$anno}-%") ->orderBy('numero_protocollo', 'desc') ->first(); if ($ultimoNumero && preg_match("/{$prefisso}-{$anno}-(\d+)/", $ultimoNumero->numero_protocollo, $matches)) { $progressivo = intval($matches[1]) + 1; } else { $progressivo = 1; } return "{$prefisso}-{$anno}-" . str_pad($progressivo, 3, '0', STR_PAD_LEFT); } } ``` **🔧 CARATTERISTICHE IMPLEMENTATE**: - **Dual-Mode**: Supporta sia campi legacy che nuovi - **Scopes**: Query predefinite per casi d'uso comuni - **Accessors**: Conversione automatica dati (es. tags array) - **Metodi Utilità**: Generazione protocolli automatica ### 5. **AGGIORNAMENTO VISTA GESTIONE DOCUMENTALE** #### File Modificato: `/resources/views/admin/stabili/tabs/gestione-documentale.blade.php` ```php
{{ $documento->note ?? $documento->descrizione }}
@endifCarica il primo documento per iniziare la gestione documentale del condominio.