argument('action'); switch ($action) { case 'create': $this->createTempDatabase(); break; case 'import': $this->importGesconData(); break; case 'view': $this->viewTempData(); break; case 'cleanup': $this->cleanupTempDatabase(); break; default: $this->error("❌ Azione non valida. Usa: create, import, view, cleanup"); } return 0; } private function createTempDatabase() { $this->info("πŸ”§ CREAZIONE DATABASE TEMPORANEO GESCON"); $this->warn("⚠️ ATTENZIONE: Database solo per sviluppo, sarΓ  eliminato!"); try { // Crea database temporaneo DB::statement("CREATE DATABASE IF NOT EXISTS {$this->tempDbName} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); // Configura connessione temporanea config(['database.connections.gescon_temp' => [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'database' => $this->tempDbName, 'username' => 'netgescon_user', 'password' => 'NetGescon2024!', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', ]]); $this->createTempTables(); $this->info("βœ… Database temporaneo creato: {$this->tempDbName}"); } catch (\Exception $e) { $this->error("❌ Errore creazione database: " . $e->getMessage()); } } private function createTempTables() { $this->info("πŸ“Š Creazione tabelle temporanee..."); // Tabella stabili GESCON DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_stabili ( id INT AUTO_INCREMENT PRIMARY KEY, codice_stabile VARCHAR(20), denominazione VARCHAR(255), indirizzo TEXT, citta VARCHAR(100), amministratore VARCHAR(255), note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB '); // Tabella voci spesa DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_voci_spesa ( id INT AUTO_INCREMENT PRIMARY KEY, stabile_codice VARCHAR(20), cod_spe VARCHAR(10), descrizione VARCHAR(255), categoria VARCHAR(100), tipo_voce VARCHAR(50), preventivo_euro DECIMAL(15,2), consuntivo_euro DECIMAL(15,2), ordinamento INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_stabile_cod (stabile_codice, cod_spe) ) ENGINE=InnoDB '); // Tabella fornitori completa DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_fornitori ( id INT AUTO_INCREMENT PRIMARY KEY, cod_forn INT, ragione_sociale VARCHAR(255), cognome VARCHAR(100), nome VARCHAR(100), codice_fiscale VARCHAR(20), partita_iva VARCHAR(20), indirizzo VARCHAR(255), cap VARCHAR(10), citta VARCHAR(100), provincia VARCHAR(10), telefono VARCHAR(50), cellulare VARCHAR(50), fax VARCHAR(50), email VARCHAR(255), pec VARCHAR(255), note TEXT, categoria_attivita VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_cod_forn (cod_forn) ) ENGINE=InnoDB '); // Tabella operazioni complete DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_operazioni ( id BIGINT AUTO_INCREMENT PRIMARY KEY, stabile_codice VARCHAR(20), id_operazione_gescon BIGINT, numero_spesa INT, data_spesa DATE, cod_spe VARCHAR(10), cod_for INT, importo_euro DECIMAL(15,2), beneficiario VARCHAR(255), numero_fattura VARCHAR(50), data_fattura DATE, note TEXT, natura VARCHAR(10), competenza CHAR(1), anno_gestione VARCHAR(20), -- Campi risolti per visualizzazione descrizione_spesa VARCHAR(255), ragione_sociale_fornitore VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_stabile (stabile_codice), INDEX idx_data (data_spesa), INDEX idx_cod_spe (cod_spe), INDEX idx_cod_for (cod_for) ) ENGINE=InnoDB '); // Tabella incassi DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_incassi ( id BIGINT AUTO_INCREMENT PRIMARY KEY, stabile_codice VARCHAR(20), numero_rata INT, data_incasso DATE, importo_euro DECIMAL(15,2), cod_spe VARCHAR(10), unita_immobiliare VARCHAR(20), note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_stabile (stabile_codice), INDEX idx_rata (numero_rata) ) ENGINE=InnoDB '); // Tabella log import per tracciabilitΓ  DB::connection('gescon_temp')->statement(' CREATE TABLE IF NOT EXISTS temp_import_log ( id INT AUTO_INCREMENT PRIMARY KEY, stabile_codice VARCHAR(20), anno VARCHAR(10), tabella VARCHAR(50), records_imported INT, status VARCHAR(20), note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB '); $this->info("βœ… Tabelle temporanee create"); } private function importGesconData() { $stabilePath = $this->option('stabile-path'); $annoPath = $this->option('anno-path'); $limit = $this->option('limit'); $this->info("πŸ“‚ IMPORT DATI GESCON TEMPORANEO"); $this->info("Stabile: {$stabilePath} Anno: {$annoPath}"); $this->warn("πŸ§ͺ Database temporaneo - Solo per sviluppo!"); // Verifica connessione temp if (!$this->verifyTempConnection()) { $this->error("❌ Database temporaneo non trovato. Esegui prima 'create'"); return; } // Import sequenziale $this->importFornitori(); $this->importVociSpesa($stabilePath, $annoPath); $this->importOperazioni($stabilePath, $annoPath, $limit); $this->info("βœ… Import completato in database temporaneo"); $this->showImportSummary(); } private function importFornitori() { $this->info("πŸ‘₯ Import fornitori da DBC..."); $fornitoriFile = '/home/michele/netgescon/docs/02-architettura-laravel/Gescon/dbc/Fornitori.mdb'; if (!file_exists($fornitoriFile)) { $this->warn("⚠️ File fornitori non trovato"); return; } $tempCsv = '/tmp/temp_fornitori_' . time() . '.csv'; exec("mdb-export '{$fornitoriFile}' Fornitori > {$tempCsv}"); if (!file_exists($tempCsv) || filesize($tempCsv) < 100) { $this->warn("⚠️ Export fornitori fallito"); return; } $imported = $this->processFornitori($tempCsv); unlink($tempCsv); $this->info("βœ… Fornitori importati: {$imported}"); $this->logImport('ALL', 'ALL', 'temp_fornitori', $imported, 'SUCCESS'); } private function importVociSpesa($stabilePath, $annoPath) { $this->info("πŸ“‹ Import voci spesa..."); $vociFile = "/home/michele/netgescon/docs/02-architettura-laravel/Gescon/{$stabilePath}/{$annoPath}/singolo_anno.mdb"; if (!file_exists($vociFile)) { $this->warn("⚠️ File voci spesa non trovato"); return; } $tempCsv = '/tmp/temp_voci_' . time() . '.csv'; exec("mdb-export '{$vociFile}' voc_spe > {$tempCsv}"); if (!file_exists($tempCsv) || filesize($tempCsv) < 50) { $this->warn("⚠️ Export voci spesa fallito"); return; } $imported = $this->processVociSpesa($tempCsv, $stabilePath); unlink($tempCsv); $this->info("βœ… Voci spesa importate: {$imported}"); $this->logImport($stabilePath, $annoPath, 'temp_voci_spesa', $imported, 'SUCCESS'); } private function importOperazioni($stabilePath, $annoPath, $limit) { $this->info("πŸ“Š Import operazioni..."); $operazioniFile = "/home/michele/netgescon/docs/02-architettura-laravel/Gescon/{$stabilePath}/{$annoPath}/singolo_anno.mdb"; if (!file_exists($operazioniFile)) { $this->warn("⚠️ File operazioni non trovato"); return; } $tempCsv = '/tmp/temp_operazioni_' . time() . '.csv'; exec("timeout 60s mdb-export '{$operazioniFile}' Operazioni > {$tempCsv}"); if (!file_exists($tempCsv) || filesize($tempCsv) < 100) { $this->warn("⚠️ Export operazioni fallito"); return; } $imported = $this->processOperazioni($tempCsv, $stabilePath, $limit); unlink($tempCsv); $this->info("βœ… Operazioni importate: {$imported}"); $this->logImport($stabilePath, $annoPath, 'temp_operazioni', $imported, 'SUCCESS'); } private function processFornitori($csvFile) { $handle = fopen($csvFile, 'r'); $headers = fgetcsv($handle); $fieldMap = $this->createFieldMap($headers); $batch = []; $imported = 0; while (($row = fgetcsv($handle)) !== false) { $data = [ 'cod_forn' => $this->getFieldValue($row, $fieldMap, 'cod_forn'), 'ragione_sociale' => $this->cleanString($this->getFieldValue($row, $fieldMap, 'cognome') . ' ' . $this->getFieldValue($row, $fieldMap, 'nome')), 'cognome' => $this->getFieldValue($row, $fieldMap, 'cognome'), 'nome' => $this->getFieldValue($row, $fieldMap, 'nome'), 'codice_fiscale' => $this->getFieldValue($row, $fieldMap, 'cod_fisc'), 'partita_iva' => $this->getFieldValue($row, $fieldMap, 'p_iva'), 'indirizzo' => $this->getFieldValue($row, $fieldMap, 'indirizzo'), 'cap' => $this->getFieldValue($row, $fieldMap, 'cap'), 'citta' => $this->getFieldValue($row, $fieldMap, 'citta'), 'provincia' => $this->getFieldValue($row, $fieldMap, 'pr'), 'telefono' => $this->getFieldValue($row, $fieldMap, 'telef_1'), 'cellulare' => $this->getFieldValue($row, $fieldMap, 'cellulare'), 'fax' => $this->getFieldValue($row, $fieldMap, 'fax'), 'email' => $this->getFieldValue($row, $fieldMap, 'indir_email'), 'pec' => $this->getFieldValue($row, $fieldMap, 'pec_fornitore'), 'note' => $this->getFieldValue($row, $fieldMap, 'note'), 'categoria_attivita' => $this->getFieldValue($row, $fieldMap, 'descrizione') ]; if (!empty($data['cod_forn'])) { $batch[] = $data; $imported++; if (count($batch) >= 100) { DB::connection('gescon_temp')->table('temp_fornitori')->insert($batch); $batch = []; } } } if (!empty($batch)) { DB::connection('gescon_temp')->table('temp_fornitori')->insert($batch); } fclose($handle); return $imported; } private function processVociSpesa($csvFile, $stabilePath) { $handle = fopen($csvFile, 'r'); $headers = fgetcsv($handle); $fieldMap = $this->createFieldMap($headers); $batch = []; $imported = 0; while (($row = fgetcsv($handle)) !== false) { $data = [ 'stabile_codice' => $stabilePath, 'cod_spe' => $this->getFieldValue($row, $fieldMap, 'cod'), 'descrizione' => substr($this->getFieldValue($row, $fieldMap, 'descriz'), 0, 255), 'categoria' => 'Standard', 'tipo_voce' => $this->getFieldValue($row, $fieldMap, 't_spese') == 'O' ? 'Ordinaria' : 'Straordinaria', 'preventivo_euro' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'preventivo_euro')), 'consuntivo_euro' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'consuntivo_euro')), 'ordinamento' => $this->getFieldValue($row, $fieldMap, 'id_vocspe') ]; if (!empty($data['cod_spe'])) { $batch[] = $data; $imported++; if (count($batch) >= 100) { DB::connection('gescon_temp')->table('temp_voci_spesa')->insert($batch); $batch = []; } } } if (!empty($batch)) { DB::connection('gescon_temp')->table('temp_voci_spesa')->insert($batch); } fclose($handle); return $imported; } private function processOperazioni($csvFile, $stabilePath, $limit) { $handle = fopen($csvFile, 'r'); $headers = fgetcsv($handle); $fieldMap = $this->createFieldMap($headers); $batch = []; $imported = 0; while (($row = fgetcsv($handle)) !== false && $imported < $limit) { $importoEuro = $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_euro')); if (empty($importoEuro) || $importoEuro == 0) continue; $data = [ 'stabile_codice' => $stabilePath, 'id_operazione_gescon' => $this->getFieldValue($row, $fieldMap, 'id_operaz'), 'numero_spesa' => $this->getFieldValue($row, $fieldMap, 'n_spe'), 'data_spesa' => $this->parseDate($this->getFieldValue($row, $fieldMap, 'dt_spe')), 'cod_spe' => $this->getFieldValue($row, $fieldMap, 'cod_spe'), 'cod_for' => $this->getFieldValue($row, $fieldMap, 'cod_for'), 'importo_euro' => $importoEuro, 'beneficiario' => substr($this->getFieldValue($row, $fieldMap, 'benef'), 0, 255), 'numero_fattura' => $this->getFieldValue($row, $fieldMap, 'num_fat'), 'data_fattura' => $this->parseDate($this->getFieldValue($row, $fieldMap, 'dt_fat')), 'note' => $this->getFieldValue($row, $fieldMap, 'note'), 'natura' => $this->getFieldValue($row, $fieldMap, 'natura'), 'competenza' => $this->getFieldValue($row, $fieldMap, 'compet'), 'anno_gestione' => $this->getFieldValue($row, $fieldMap, 'anno') ]; $batch[] = $data; $imported++; if (count($batch) >= 100) { DB::connection('gescon_temp')->table('temp_operazioni')->insert($batch); $batch = []; } } if (!empty($batch)) { DB::connection('gescon_temp')->table('temp_operazioni')->insert($batch); } fclose($handle); // Aggiorna descrizioni e fornitori $this->updateOperazioniDescriptions(); return $imported; } private function updateOperazioniDescriptions() { $this->info("πŸ”— Collegamento descrizioni e fornitori..."); // Collega voci spesa DB::connection('gescon_temp')->statement(" UPDATE temp_operazioni o JOIN temp_voci_spesa v ON o.stabile_codice = v.stabile_codice AND o.cod_spe = v.cod_spe SET o.descrizione_spesa = v.descrizione "); // Collega fornitori DB::connection('gescon_temp')->statement(" UPDATE temp_operazioni o JOIN temp_fornitori f ON o.cod_for = f.cod_forn SET o.ragione_sociale_fornitore = f.ragione_sociale "); } private function viewTempData() { $this->info("πŸ‘οΈ VISUALIZZAZIONE DATI TEMPORANEI"); if (!$this->verifyTempConnection()) { $this->error("❌ Database temporaneo non trovato"); return; } // Statistiche generali $stats = DB::connection('gescon_temp')->select(" SELECT 'Fornitori' as tabella, COUNT(*) as records FROM temp_fornitori UNION ALL SELECT 'Voci Spesa' as tabella, COUNT(*) as records FROM temp_voci_spesa UNION ALL SELECT 'Operazioni' as tabella, COUNT(*) as records FROM temp_operazioni UNION ALL SELECT 'Incassi' as tabella, COUNT(*) as records FROM temp_incassi "); $this->info("πŸ“Š STATISTICHE DATABASE TEMPORANEO:"); foreach ($stats as $stat) { $this->info(" {$stat->tabella}: {$stat->records} record"); } // Operazioni recenti con dettagli $operazioni = DB::connection('gescon_temp')->select(" SELECT data_spesa, cod_spe, descrizione_spesa, ragione_sociale_fornitore, importo_euro, numero_fattura FROM temp_operazioni ORDER BY data_spesa DESC LIMIT 5 "); if (!empty($operazioni)) { $this->info("\nπŸ“‹ OPERAZIONI RECENTI:"); foreach ($operazioni as $op) { $this->info(" {$op->data_spesa} | {$op->cod_spe} | {$op->descrizione_spesa} | €{$op->importo_euro}"); } } } private function cleanupTempDatabase() { $this->warn("πŸ—‘οΈ ELIMINAZIONE DATABASE TEMPORANEO"); $this->warn("⚠️ ATTENZIONE: Tutti i dati di sviluppo saranno persi!"); if (!$this->confirm('Sei sicuro di voler eliminare il database temporaneo?')) { $this->info("❌ Operazione annullata"); return; } try { DB::statement("DROP DATABASE IF EXISTS {$this->tempDbName}"); $this->info("βœ… Database temporaneo eliminato: {$this->tempDbName}"); } catch (\Exception $e) { $this->error("❌ Errore eliminazione: " . $e->getMessage()); } } private function verifyTempConnection() { try { config(['database.connections.gescon_temp' => [ 'driver' => 'mysql', 'host' => '127.0.0.1', 'database' => $this->tempDbName, 'username' => 'netgescon_user', 'password' => 'NetGescon2024!', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', ]]); DB::connection('gescon_temp')->select('SELECT 1'); return true; } catch (\Exception $e) { return false; } } private function logImport($stabile, $anno, $tabella, $records, $status) { try { DB::connection('gescon_temp')->table('temp_import_log')->insert([ 'stabile_codice' => $stabile, 'anno' => $anno, 'tabella' => $tabella, 'records_imported' => $records, 'status' => $status ]); } catch (\Exception $e) { // Ignore log errors } } private function showImportSummary() { $logs = DB::connection('gescon_temp')->select(" SELECT tabella, SUM(records_imported) as totale FROM temp_import_log GROUP BY tabella "); $this->info("\nπŸ“Š RIEPILOGO IMPORT:"); foreach ($logs as $log) { $this->info(" {$log->tabella}: {$log->totale} record"); } } // Utility methods private function createFieldMap($headers) { $map = []; foreach ($headers as $index => $header) { $map[strtolower(trim($header))] = $index; } return $map; } private function getFieldValue($row, $fieldMap, $fieldName) { $fieldName = strtolower($fieldName); if (!isset($fieldMap[$fieldName])) return null; $index = $fieldMap[$fieldName]; return isset($row[$index]) ? trim($row[$index]) : null; } private function parseDate($dateString) { if (empty($dateString)) return null; try { $date = \DateTime::createFromFormat('m/d/y H:i:s', $dateString); if (!$date) { $date = \DateTime::createFromFormat('Y-m-d H:i:s', $dateString); } if (!$date) { $date = \DateTime::createFromFormat('Y-m-d', $dateString); } return $date ? $date->format('Y-m-d') : null; } catch (\Exception $e) { return null; } } private function parseDecimal($value) { if (empty($value)) return 0; $value = preg_replace('/[^\d.,\-]/', '', $value); $value = str_replace(',', '.', $value); return is_numeric($value) ? (float)$value : 0; } private function cleanString($string) { if (empty($string)) return null; return trim(preg_replace('/\s+/', ' ', $string)); } }