Euro}'; protected $description = 'Import completo GESCON in database temporaneo con anti-duplicazione'; private $tassoConversione; private $modalitaTest; private $forzaImport; private $logImport = []; public function handle() { $this->info('πŸš€ IMPORT COMPLETO GESCON - Database Intermedio'); $this->info('================================================'); // Inizializza parametri $this->tassoConversione = (float) $this->option('lire-to-euro'); $this->modalitaTest = $this->option('test'); $this->forzaImport = $this->option('force'); $this->info("πŸ’° Tasso conversione: 1 Euro = {$this->tassoConversione} Lire"); if ($this->modalitaTest) { $this->warn('⚠️ MODALITΓ€ TEST ATTIVA - Nessun commit finale'); } // Verifica connessione database temporaneo if (!$this->verificaConnessioneTemp()) { $this->error('❌ Impossibile connettersi al database temporaneo'); return 1; } // Path base GESCON $pathGescon = '/home/michele/netgescon/docs/02-architettura-laravel/Gescon'; if (!File::exists($pathGescon)) { $this->error("❌ Path GESCON non trovato: {$pathGescon}"); return 1; } // Step 1: Import tabelle master centrali $this->info("\nπŸ“‹ STEP 1: Import Tabelle Master Centrali"); $this->line('==========================================='); $this->importTabelleMaster($pathGescon); // Step 2: Scan directory stabili $this->info("\n🏒 STEP 2: Scan Directory Stabili"); $this->line('=================================='); $stabiliProcessati = $this->scanDirectoryStabili($pathGescon); // Step 3: Report finale $this->info("\nπŸ“Š STEP 3: Report Import Completo"); $this->line('=================================='); $this->generaReportFinale($stabiliProcessati); if (!$this->modalitaTest) { $this->info("\nβœ… Import completato con successo!"); $this->info("πŸ”— Database temporaneo: gescon_import_temp"); $this->info("πŸ“ˆ Pronto per mapping verso NetGescon"); } else { $this->warn("\n⚠️ Import TEST completato - Database NON aggiornato"); } return 0; } private function verificaConnessioneTemp(): bool { try { // Test connessione DB::connection('gescon_temp')->select('SELECT 1'); $this->info("βœ… Connessione database temporaneo OK"); return true; } catch (\Exception $e) { $this->error("❌ Errore connessione: " . $e->getMessage()); return false; } } private function importTabelleMaster(string $pathGescon): void { // 1. Import Stabili.csv $this->importStabili($pathGescon . '/strutture/Stabili.mdb'); // 2. Import Fornitori.csv $this->importFornitori($pathGescon . '/strutture/Fornitori.mdb'); } private function importStabili(string $pathMdb): void { $this->info("πŸ“Š Importando Stabili da: " . basename($pathMdb)); try { // Estrai CSV da MDB $csvPath = $this->estraiTabellaCSV($pathMdb, 'Stabili'); if (!$csvPath) { $this->warn("⚠️ Impossibile estrarre tabella Stabili"); return; } $recordImportati = 0; $recordDuplicati = 0; $recordErrori = 0; // Leggi CSV $file = fopen($csvPath, 'r'); $headers = fgetcsv($file); while (($row = fgetcsv($file)) !== FALSE) { try { $data = array_combine($headers, $row); // Mappa campi GESCON -> Database temp $stabileData = $this->mappaStabile($data); // Controllo anti-duplicazione $esistente = DB::connection('gescon_temp') ->table('stabili_gescon') ->where('cod_stabile', $stabileData['cod_stabile']) ->first(); if ($esistente && !$this->forzaImport) { $recordDuplicati++; continue; } if (!$this->modalitaTest) { if ($esistente) { // Update DB::connection('gescon_temp') ->table('stabili_gescon') ->where('cod_stabile', $stabileData['cod_stabile']) ->update($stabileData); } else { // Insert DB::connection('gescon_temp') ->table('stabili_gescon') ->insert($stabileData); } } $recordImportati++; } catch (\Exception $e) { $recordErrori++; $this->warn("⚠️ Errore riga: " . $e->getMessage()); } } fclose($file); $this->info("βœ… Stabili: {$recordImportati} importati, {$recordDuplicati} duplicati, {$recordErrori} errori"); // Log import $this->logImport('Stabili', 'stabili_gescon', $pathMdb, $recordImportati, $recordDuplicati, $recordErrori); } catch (\Exception $e) { $this->error("❌ Errore import Stabili: " . $e->getMessage()); } } private function importFornitori(string $pathMdb): void { $this->info("πŸͺ Importando Fornitori da: " . basename($pathMdb)); try { $csvPath = $this->estraiTabellaCSV($pathMdb, 'Fornitori'); if (!$csvPath) { $this->warn("⚠️ Impossibile estrarre tabella Fornitori"); return; } $recordImportati = 0; $recordDuplicati = 0; $recordErrori = 0; $file = fopen($csvPath, 'r'); $headers = fgetcsv($file); while (($row = fgetcsv($file)) !== FALSE) { try { $data = array_combine($headers, $row); $fornitoreData = $this->mappaFornitore($data); // Anti-duplicazione $esistente = DB::connection('gescon_temp') ->table('fornitori_gescon') ->where('cod_forn', $fornitoreData['cod_forn']) ->first(); if ($esistente && !$this->forzaImport) { $recordDuplicati++; continue; } if (!$this->modalitaTest) { if ($esistente) { DB::connection('gescon_temp') ->table('fornitori_gescon') ->where('cod_forn', $fornitoreData['cod_forn']) ->update($fornitoreData); } else { DB::connection('gescon_temp') ->table('fornitori_gescon') ->insert($fornitoreData); } } $recordImportati++; } catch (\Exception $e) { $recordErrori++; } } fclose($file); $this->info("βœ… Fornitori: {$recordImportati} importati, {$recordDuplicati} duplicati, {$recordErrori} errori"); $this->logImport('Fornitori', 'fornitori_gescon', $pathMdb, $recordImportati, $recordDuplicati, $recordErrori); } catch (\Exception $e) { $this->error("❌ Errore import Fornitori: " . $e->getMessage()); } } private function scanDirectoryStabili(string $pathGescon): array { $stabiliProcessati = []; // Cerca directory numeriche (stabili) $directories = File::directories($pathGescon); foreach ($directories as $dir) { $nomeDir = basename($dir); // Solo directory numeriche (es: 0021, 0008, etc.) if (preg_match('/^\d+$/', $nomeDir)) { $codStabile = $nomeDir; // Filtro stabile specifico se richiesto if ($this->option('stabile') && $this->option('stabile') !== $codStabile) { continue; } $this->info("🏒 Processando Stabile: {$codStabile}"); $stabiliProcessati[] = $this->processaStabile($dir, $codStabile); } } return $stabiliProcessati; } private function processaStabile(string $dirStabile, string $codStabile): array { $risultato = [ 'cod_stabile' => $codStabile, 'path' => $dirStabile, 'tabelle_importate' => [], 'errori' => [] ]; try { // 1. Import generale_stabile.mdb $this->importGeneraleStabile($dirStabile, $codStabile); // 2. Scan directory anni (0001, 0002, etc.) $dirAnni = File::directories($dirStabile); foreach ($dirAnni as $dirAnno) { $anno = basename($dirAnno); if (preg_match('/^\d{4}$/', $anno)) { $this->info(" πŸ“… Anno: {$anno}"); $this->importSingoloAnno($dirAnno, $codStabile, $anno); } } } catch (\Exception $e) { $risultato['errori'][] = $e->getMessage(); $this->error("❌ Errore stabile {$codStabile}: " . $e->getMessage()); } return $risultato; } private function importGeneraleStabile(string $dirStabile, string $codStabile): void { $pathMdb = $dirStabile . '/generale_stabile.mdb'; if (!File::exists($pathMdb)) { $this->warn(" ⚠️ File generale_stabile.mdb non trovato"); return; } // Importa tabelle principali $tabelle = ['Fatture', 'emes_gen', 'emes_det']; foreach ($tabelle as $tabella) { $this->info(" πŸ“‹ Import {$tabella}..."); switch ($tabella) { case 'Fatture': $this->importFattureStabile($pathMdb, $codStabile); break; case 'emes_gen': $this->importRateGenerali($pathMdb, $codStabile); break; case 'emes_det': $this->importRateDettaglio($pathMdb, $codStabile); break; } } } private function importSingoloAnno(string $dirAnno, string $codStabile, string $annoGestione): void { $pathMdb = $dirAnno . '/singolo_anno.mdb'; if (!File::exists($pathMdb)) { $this->warn(" ⚠️ File singolo_anno.mdb non trovato per anno {$annoGestione}"); return; } // ⭐ IMPORT TABELLE CRITICHE $tabelleCritiche = [ 'condomin' => 'condomini_gescon', 'voc_spe' => 'voci_spesa_gescon', 'dett_tab' => 'dettagli_tabelle_gescon', 'Operazioni' => 'operazioni_gescon', 'dett_pers' => 'dettagli_personali_gescon', 'incassi' => 'incassi_gescon', 'Assemblee' => 'assemblee_gescon' ]; foreach ($tabelleCritiche as $tabellaOriginale => $tabellaDestinazione) { $this->info(" 🎯 Import {$tabellaOriginale} -> {$tabellaDestinazione}"); try { $this->importTabellaAnno($pathMdb, $tabellaOriginale, $tabellaDestinazione, $codStabile, $annoGestione); } catch (\Exception $e) { $this->warn(" ⚠️ Errore {$tabellaOriginale}: " . $e->getMessage()); } } } private function importTabellaAnno(string $pathMdb, string $tabellaOriginale, string $tabellaDestinazione, string $codStabile, string $annoGestione): void { $csvPath = $this->estraiTabellaCSV($pathMdb, $tabellaOriginale); if (!$csvPath) { return; } $recordImportati = 0; $recordDuplicati = 0; $recordErrori = 0; $file = fopen($csvPath, 'r'); $headers = fgetcsv($file); while (($row = fgetcsv($file)) !== FALSE) { try { $data = array_combine($headers, $row); // Mappa dati specifici per tabella $mappedData = $this->mappaDatiTabella($tabellaOriginale, $data, $codStabile, $annoGestione); if (!$mappedData) { continue; } // Controllo duplicazione (logic specifica per tabella) $chiaveUnica = $this->getChiaveUnicaTabella($tabellaDestinazione, $mappedData); $esistente = DB::connection('gescon_temp') ->table($tabellaDestinazione) ->where($chiaveUnica) ->first(); if ($esistente && !$this->forzaImport) { $recordDuplicati++; continue; } if (!$this->modalitaTest) { if ($esistente) { DB::connection('gescon_temp') ->table($tabellaDestinazione) ->where($chiaveUnica) ->update($mappedData); } else { DB::connection('gescon_temp') ->table($tabellaDestinazione) ->insert($mappedData); } } $recordImportati++; } catch (\Exception $e) { $recordErrori++; } } fclose($file); $this->line(" βœ… {$recordImportati} importati, {$recordDuplicati} duplicati, {$recordErrori} errori"); $this->logImport($tabellaOriginale, $tabellaDestinazione, $pathMdb, $recordImportati, $recordDuplicati, $recordErrori, $codStabile); } // === METODI UTILITY === private function estraiTabellaCSV(string $pathMdb, string $nomeTabella): ?string { try { $tempDir = storage_path('app/temp/gescon'); File::ensureDirectoryExists($tempDir); $csvPath = $tempDir . '/' . basename($pathMdb, '.mdb') . '_' . $nomeTabella . '.csv'; // Esegui mdb-export $command = "mdb-export '{$pathMdb}' '{$nomeTabella}' > '{$csvPath}' 2>/dev/null"; exec($command, $output, $returnCode); if ($returnCode === 0 && File::exists($csvPath) && File::size($csvPath) > 0) { return $csvPath; } return null; } catch (\Exception $e) { return null; } } private function convertLireToEuro(?float $importoLire): ?float { if (is_null($importoLire) || $importoLire == 0) { return null; } return round($importoLire / $this->tassoConversione, 2); } private function mappaStabile(array $data): array { return [ 'cod_stabile' => $data['Campo2'] ?? '', // cod_stabile 'codice_directory' => $data['Campo12'] ?? '', // codice_directory 'denominazione' => $data['Campo3'] ?? '', // denominazione 'indirizzo' => $data['Campo4'] ?? '', // indirizzo 'cap' => $data['Campo5'] ?? '', 'citta' => $data['Campo6'] ?? '', 'provincia' => $data['Campo7'] ?? '', 'codice_fiscale_cond' => $data['Campo8'] ?? '', 'cf_amministratore' => $data['Campo9'] ?? '', 'scale' => (int) ($data['Campo10'] ?? 0), 'n_interni' => (int) ($data['Campo11'] ?? 0), 'iban_principale' => $data['Campo81'] ?? '', 'flags_gestione' => json_encode([ 'attivo' => $data['Campo38'] ?? '', 'autorizzazione' => $data['Campo41'] ?? '' ]), 'origine_file' => 'Stabili.mdb', 'data_import' => Carbon::now(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } private function mappaFornitore(array $data): array { // Mappa campi fornitori (da determinare dalla struttura CSV) return [ 'cod_forn' => $data['cod_forn'] ?? $data['Campo1'] ?? '', 'ragione_sociale' => $data['ragione_sociale'] ?? $data['denominazione'] ?? '', 'codice_fiscale' => $data['codice_fiscale'] ?? '', 'partita_iva' => $data['partita_iva'] ?? '', 'indirizzo' => $data['indirizzo'] ?? '', 'cap' => $data['cap'] ?? '', 'citta' => $data['citta'] ?? '', 'provincia' => $data['provincia'] ?? '', 'telefono' => $data['telefono'] ?? '', 'email' => $data['email'] ?? '', 'iban' => $data['iban'] ?? '', 'attivo' => true, 'origine_file' => 'Fornitori.mdb', 'data_import' => Carbon::now(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; } private function mappaDatiTabella(string $tabella, array $data, string $codStabile, string $annoGestione): ?array { $baseData = [ 'cod_stabile' => $codStabile, 'anno_gestione' => $annoGestione, 'origine_file' => $tabella . '.mdb', 'data_import' => Carbon::now(), 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]; switch ($tabella) { case 'voc_spe': return array_merge($baseData, [ 'id_vocspe' => $data['id_vocspe'] ?? '', 'cod' => $data['cod'] ?? '', 'descriz' => $data['descriz'] ?? '', 'tabella' => $data['tabella'] ?? '', 'perc_proprietario' => (float) ($data['Perc_proprietario'] ?? 0), 'perc_inquilino' => (float) ($data['Perc_Inquilino'] ?? 0), 'imp_propr_lire' => (float) ($data['Imp_propr'] ?? 0), 'imp_propr_euro' => $this->convertLireToEuro($data['Imp_propr'] ?? 0), 'importo_lire' => (float) ($data['importo'] ?? 0), 'importo_euro' => $this->convertLireToEuro($data['importo'] ?? 0), 'preventivo_lire' => (float) ($data['preventivo'] ?? 0), 'preventivo_euro' => $this->convertLireToEuro($data['preventivo'] ?? 0), 'consuntivo_lire' => (float) ($data['consuntivo'] ?? 0), 'consuntivo_euro' => $this->convertLireToEuro($data['consuntivo'] ?? 0), 'note' => $data['note'] ?? '' ]); case 'dett_tab': return array_merge($baseData, [ 'id_dett_tab' => $data['ID'] ?? '', 'cod_tab' => $data['cod_tab'] ?? '', 'id_cond' => $data['id_cond'] ?? '', 'cond_inquil' => $data['cond_inquil'] ?? '', 'mm' => (float) ($data['mm'] ?? 0), 'prev_lire' => (float) ($data['prev'] ?? 0), 'prev_euro' => $this->convertLireToEuro($data['prev'] ?? 0), 'cons_lire' => (float) ($data['cons'] ?? 0), 'cons_euro' => $this->convertLireToEuro($data['cons'] ?? 0), 'n_stra' => $data['n_stra'] ?? '', 'unico' => (bool) ($data['UNICO'] ?? false) ]); case 'Operazioni': return array_merge($baseData, [ 'id_operaz' => $data['id_operaz'] ?? '', 'n_spe' => (int) ($data['n_spe'] ?? 0), 'dt_spe' => !empty($data['dt_spe']) ? Carbon::parse($data['dt_spe'])->format('Y-m-d') : null, 'cod_spe' => $data['cod_spe'] ?? '', 'tabella' => $data['Tabella'] ?? '', 'importo_lire' => (float) ($data['importo'] ?? 0), 'importo_euro' => $this->convertLireToEuro($data['importo'] ?? 0), 'cod_ben' => $data['cod_ben'] ?? '', 'benef' => $data['benef'] ?? '', 'cod_for' => $data['cod_for'] ?? '', 'num_fat' => $data['num_fat'] ?? '', 'dt_fat' => !empty($data['dt_fat']) ? Carbon::parse($data['dt_fat'])->format('Y-m-d') : null, 'natura' => $data['natura'] ?? '', 'note' => $data['note'] ?? '', 'importo_spese' => (float) ($data['Importo_Spese'] ?? 0), 'importo_entrate' => (float) ($data['Importo_Entrate'] ?? 0) ]); // Altri case per condomin, dett_pers, incassi, Assemblee... default: return $baseData; } } private function getChiaveUnicaTabella(string $tabella, array $data): array { switch ($tabella) { case 'voci_spesa_gescon': return [ 'cod_stabile' => $data['cod_stabile'], 'anno_gestione' => $data['anno_gestione'], 'id_vocspe' => $data['id_vocspe'] ]; case 'dettagli_tabelle_gescon': return [ 'cod_stabile' => $data['cod_stabile'], 'anno_gestione' => $data['anno_gestione'], 'id_dett_tab' => $data['id_dett_tab'] ]; case 'operazioni_gescon': return [ 'cod_stabile' => $data['cod_stabile'], 'anno_gestione' => $data['anno_gestione'], 'id_operaz' => $data['id_operaz'] ]; default: return ['cod_stabile' => $data['cod_stabile']]; } } private function logImport(string $tabellaOriginale, string $tabellaDestinazione, string $file, int $importati, int $duplicati, int $errori, string $codStabile = 'MASTER'): void { if (!$this->modalitaTest) { DB::connection('gescon_temp')->table('import_log')->insert([ 'cod_stabile' => $codStabile, 'tabella_origine' => $tabellaOriginale, 'tabella_destinazione' => $tabellaDestinazione, 'file_origine' => basename($file), 'record_processati' => $importati + $duplicati + $errori, 'record_importati' => $importati, 'record_duplicati' => $duplicati, 'record_errori' => $errori, 'inizio_import' => Carbon::now(), 'fine_import' => Carbon::now(), 'stato' => 'completato', 'created_at' => Carbon::now(), 'updated_at' => Carbon::now() ]); } $this->logImport[] = [ 'tabella' => $tabellaOriginale, 'importati' => $importati, 'duplicati' => $duplicati, 'errori' => $errori ]; } private function generaReportFinale(array $stabiliProcessati): void { $this->table( ['Tabella', 'Importati', 'Duplicati', 'Errori'], array_map(function ($log) { return [$log['tabella'], $log['importati'], $log['duplicati'], $log['errori']]; }, $this->logImport) ); $this->info("\nπŸ“Š STATISTICHE FINALI:"); $this->info("🏒 Stabili processati: " . count($stabiliProcessati)); $this->info("πŸ“‹ Tabelle importate: " . count($this->logImport)); $this->info("πŸ“ˆ Record totali importati: " . array_sum(array_column($this->logImport, 'importati'))); $this->info("⚠️ Record duplicati: " . array_sum(array_column($this->logImport, 'duplicati'))); $this->info("❌ Record con errori: " . array_sum(array_column($this->logImport, 'errori'))); } // Implementa altri metodi per import fatture, rate, etc. private function importFattureStabile(string $pathMdb, string $codStabile): void { // TODO: Implementa import fatture } private function importRateGenerali(string $pathMdb, string $codStabile): void { // TODO: Implementa import rate generali } private function importRateDettaglio(string $pathMdb, string $codStabile): void { // TODO: Implementa import rate dettaglio } }