argument('file'); $euroOnly = $this->option('euro-only'); $testMode = $this->option('test'); $stabileId = $this->option('stabile-id'); $this->info("πŸ”§ IMPORT OPERAZIONI GESCON"); $this->info("File: {$file}"); $this->info("EURO Only: " . ($euroOnly ? 'SI' : 'NO')); $this->info("Test Mode: " . ($testMode ? 'SI' : 'NO')); // Path del file MDB $mdbPath = "/home/michele/netgescon/docs/02-architettura-laravel/Gescon/strutture/{$file}"; if (!file_exists($mdbPath)) { $this->error("❌ File MDB non trovato: {$mdbPath}"); return 1; } // Crea tabella ottimizzata per operazioni $this->createOptimizedOperazioniTable(); // Import delle operazioni con filtraggio intelligente $this->importOperazioni($mdbPath, $euroOnly, $testMode, $stabileId); return 0; } private function createOptimizedOperazioniTable() { $this->info("πŸ“Š Creazione tabella operazioni ottimizzata..."); // Elimina e ricrea la tabella con solo campi essenziali DB::statement('DROP TABLE IF EXISTS gescon_operazioni_import'); DB::statement(' CREATE TABLE gescon_operazioni_import ( id INT AUTO_INCREMENT PRIMARY KEY, stabile_id INT NOT NULL, id_operazione_originale BIGINT, numero_spesa INT, data_spesa DATE, codice_spesa VARCHAR(10), codice_tabella VARCHAR(10), importo_euro DECIMAL(15,2), codice_beneficiario INT, beneficiario VARCHAR(200), beneficiario2 VARCHAR(100), competenza CHAR(1), note TEXT, numero_straordinaria INT, codice_cassa VARCHAR(10), natura VARCHAR(2), natura_dettaglio VARCHAR(20), codice_fornitore INT, numero_fattura VARCHAR(50), data_fattura DATE, anno_gestione VARCHAR(20), importo_calcolato_euro DECIMAL(15,2), importo_spese DECIMAL(15,2) DEFAULT 0, importo_entrate DECIMAL(15,2) DEFAULT 0, importo_crediti DECIMAL(15,2) DEFAULT 0, importo_debiti DECIMAL(15,2) DEFAULT 0, incluso CHAR(1), gestione CHAR(1), tipo_detrazioni VARCHAR(10), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_stabile (stabile_id), INDEX idx_data_spesa (data_spesa), INDEX idx_codice_spesa (codice_spesa), INDEX idx_fornitore (codice_fornitore), INDEX idx_anno (anno_gestione), INDEX idx_natura (natura) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci '); $this->info("βœ… Tabella operazioni ottimizzata creata"); } private function importOperazioni($mdbPath, $euroOnly, $testMode, $stabileId) { $this->info("πŸ“‚ Esportazione dati da MDB..."); // Export della tabella Operazioni $tempCsv = '/tmp/gescon_operazioni_' . time() . '.csv'; $command = "mdb-export '{$mdbPath}' Operazioni > {$tempCsv}"; exec($command, $output, $returnCode); if ($returnCode !== 0) { $this->error("❌ Errore nell'export MDB"); return; } if (!file_exists($tempCsv)) { $this->error("❌ File CSV temporaneo non creato"); return; } $this->info("πŸ“Š Analisi e import dati..."); $handle = fopen($tempCsv, 'r'); if (!$handle) { $this->error("❌ Impossibile aprire file CSV"); return; } // Leggi header $headers = fgetcsv($handle); if (!$headers) { $this->error("❌ Header CSV non trovato"); fclose($handle); return; } // Mappa degli indici dei campi che ci interessano $fieldMap = $this->createFieldMap($headers); $recordsProcessed = 0; $recordsImported = 0; $recordsSkipped = 0; $batch = []; $batchSize = 100; while (($row = fgetcsv($handle)) !== false) { $recordsProcessed++; // Filtra record vuoti o non validi if (!$this->isValidOperationRecord($row, $fieldMap, $euroOnly)) { $recordsSkipped++; continue; } // Prepara record per import $operationData = $this->prepareOperationData($row, $fieldMap, $stabileId); if ($operationData) { $batch[] = $operationData; // Import batch quando raggiunge la dimensione if (count($batch) >= $batchSize) { if (!$testMode) { DB::table('gescon_operazioni_import')->insert($batch); } $recordsImported += count($batch); $batch = []; // Progress feedback if ($recordsImported % 500 == 0) { $this->info("πŸ“ˆ Importati: {$recordsImported} record"); } } } } // Import ultimo batch if (!empty($batch) && !$testMode) { DB::table('gescon_operazioni_import')->insert($batch); $recordsImported += count($batch); } fclose($handle); unlink($tempCsv); // Report finale $this->info("βœ… IMPORT OPERAZIONI COMPLETATO"); $this->info("πŸ“Š Record elaborati: {$recordsProcessed}"); $this->info("πŸ“₯ Record importati: {$recordsImported}"); $this->info("⏭️ Record saltati: {$recordsSkipped}"); if ($testMode) { $this->warn("πŸ§ͺ MODALITΓ€ TEST - Nessun dato salvato nel database"); } } private function createFieldMap($headers) { $map = []; foreach ($headers as $index => $header) { $map[strtolower(trim($header))] = $index; } return $map; } private function isValidOperationRecord($row, $fieldMap, $euroOnly) { // Verifica che abbia un ID operazione $idOperaz = $this->getFieldValue($row, $fieldMap, 'id_operaz'); if (empty($idOperaz)) return false; // Se richiesto solo EURO, verifica che abbia importo in euro if ($euroOnly) { $importoEuro = $this->getFieldValue($row, $fieldMap, 'importo_euro'); if (empty($importoEuro) || $importoEuro == 0) return false; } // Verifica che abbia almeno una data spesa o codice spesa $dataSpesa = $this->getFieldValue($row, $fieldMap, 'dt_spe'); $codiceSpesa = $this->getFieldValue($row, $fieldMap, 'cod_spe'); return !empty($dataSpesa) || !empty($codiceSpesa); } private function prepareOperationData($row, $fieldMap, $stabileId) { try { $data = [ 'stabile_id' => $stabileId, 'id_operazione_originale' => $this->getFieldValue($row, $fieldMap, 'id_operaz'), 'numero_spesa' => $this->getFieldValue($row, $fieldMap, 'n_spe'), 'data_spesa' => $this->parseDate($this->getFieldValue($row, $fieldMap, 'dt_spe')), 'codice_spesa' => $this->getFieldValue($row, $fieldMap, 'cod_spe'), 'codice_tabella' => $this->getFieldValue($row, $fieldMap, 'tabella'), 'importo_euro' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_euro')), 'codice_beneficiario' => $this->getFieldValue($row, $fieldMap, 'cod_ben'), 'beneficiario' => substr($this->getFieldValue($row, $fieldMap, 'benef'), 0, 200), 'beneficiario2' => substr($this->getFieldValue($row, $fieldMap, 'benef2'), 0, 100), 'competenza' => $this->getFieldValue($row, $fieldMap, 'compet'), 'note' => $this->getFieldValue($row, $fieldMap, 'note'), 'numero_straordinaria' => $this->getFieldValue($row, $fieldMap, 'n_stra'), 'codice_cassa' => $this->getFieldValue($row, $fieldMap, 'cod_cassa'), 'natura' => $this->getFieldValue($row, $fieldMap, 'natura'), 'natura_dettaglio' => $this->getFieldValue($row, $fieldMap, 'natura2'), 'codice_fornitore' => $this->getFieldValue($row, $fieldMap, 'cod_for'), 'numero_fattura' => $this->getFieldValue($row, $fieldMap, 'num_fat'), 'data_fattura' => $this->parseDate($this->getFieldValue($row, $fieldMap, 'dt_fat')), 'anno_gestione' => $this->getFieldValue($row, $fieldMap, 'anno'), 'importo_calcolato_euro' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'imp_calcolato_euro')), 'importo_spese' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_spese')), 'importo_entrate' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_entrate')), 'importo_crediti' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_crediti')), 'importo_debiti' => $this->parseDecimal($this->getFieldValue($row, $fieldMap, 'importo_debiti')), 'incluso' => $this->getFieldValue($row, $fieldMap, 'incluso'), 'gestione' => $this->getFieldValue($row, $fieldMap, 'gestione'), 'tipo_detrazioni' => $this->getFieldValue($row, $fieldMap, 'detraz_36') ]; return $data; } catch (\Exception $e) { $this->error("❌ Errore preparazione record: " . $e->getMessage()); return null; } } 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('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; // Rimuovi spazi e caratteri non numerici eccetto punto e virgola $value = preg_replace('/[^\d.,\-]/', '', $value); // Gestisci separatori decimali $value = str_replace(',', '.', $value); return is_numeric($value) ? (float)$value : 0; } }