option('test'); $stabileId = $this->option('stabile-id'); $this->info("🔧 SPLIT FORNITORI GESCON"); $this->info("Test Mode: " . ($testMode ? 'SI' : 'NO')); // Crea tabelle ottimizzate $this->createOptimizedTables(); // Processa i fornitori esistenti $this->processFornitori($testMode, $stabileId); return 0; } private function createOptimizedTables() { $this->info("📊 Creazione tabelle separate per fornitori..."); // Tabella anagrafica unica (comune a tutti gli stabili) DB::statement('DROP TABLE IF EXISTS anagrafica_unica_fornitori'); DB::statement(' CREATE TABLE anagrafica_unica_fornitori ( id INT AUTO_INCREMENT PRIMARY KEY, codice_fornitore_gescon INT UNIQUE, ragione_sociale VARCHAR(255), denominazione VARCHAR(255), nome VARCHAR(100), cognome VARCHAR(100), codice_fiscale VARCHAR(20), partita_iva VARCHAR(20), -- Indirizzo principale indirizzo VARCHAR(255), citta VARCHAR(100), provincia VARCHAR(10), cap VARCHAR(10), -- Contatti telefono VARCHAR(50), telefono2 VARCHAR(50), cellulare VARCHAR(50), fax VARCHAR(50), email VARCHAR(255), pec VARCHAR(255), sito_web VARCHAR(255), -- Dati bancari banca VARCHAR(255), iban VARCHAR(50), swift VARCHAR(20), -- Note generali note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_codice_gescon (codice_fornitore_gescon), INDEX idx_cf (codice_fiscale), INDEX idx_piva (partita_iva), INDEX idx_ragione_sociale (ragione_sociale) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci '); // Tabella dati specifici per stabile DB::statement('DROP TABLE IF EXISTS fornitori_stabili_specifici'); DB::statement(' CREATE TABLE fornitori_stabili_specifici ( id INT AUTO_INCREMENT PRIMARY KEY, stabile_id INT NOT NULL, anagrafica_fornitore_id INT NOT NULL, codice_interno_stabile VARCHAR(50), -- Dati contrattuali specifici categoria_servizio VARCHAR(100), tipo_contratto VARCHAR(100), data_inizio_contratto DATE, data_fine_contratto DATE, importo_contratto DECIMAL(15,2), periodicita_fatturazione VARCHAR(50), -- Condizioni specifiche giorni_pagamento INT DEFAULT 30, sconto_applicato DECIMAL(5,2) DEFAULT 0, ritenuta_acconto DECIMAL(5,2) DEFAULT 0, split_payment BOOLEAN DEFAULT FALSE, -- Status operativo attivo BOOLEAN DEFAULT TRUE, data_ultima_fattura DATE, importo_ultima_fattura DECIMAL(15,2), -- Note specifiche per questo stabile note_stabile TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (anagrafica_fornitore_id) REFERENCES anagrafica_unica_fornitori(id), INDEX idx_stabile (stabile_id), INDEX idx_anagrafica (anagrafica_fornitore_id), INDEX idx_categoria (categoria_servizio), UNIQUE KEY unique_fornitore_stabile (stabile_id, anagrafica_fornitore_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci '); $this->info("✅ Tabelle separate create"); } private function processFornitori($testMode, $stabileId) { $this->info("📂 Processing fornitori esistenti..."); // Verifica se esiste la tabella fornitori di import $fornitoriExist = DB::select("SHOW TABLES LIKE 'fornitori'"); if (empty($fornitoriExist)) { $this->error("❌ Tabella fornitori non trovata. Esegui prima l\'import fornitori."); return; } $fornitori = DB::table('fornitori')->get(); $this->info("📊 Trovati " . $fornitori->count() . " fornitori da processare"); $anagraficheImported = 0; $specificiImported = 0; foreach ($fornitori as $fornitore) { // 1. Import anagrafica unica (se non esiste già) $anagraficaId = $this->importAnagraficaUnica($fornitore, $testMode); if ($anagraficaId) { $anagraficheImported++; // 2. Import dati specifici per stabile $specificoImported = $this->importDatiSpecifici($fornitore, $anagraficaId, $stabileId, $testMode); if ($specificoImported) { $specificiImported++; } } } $this->info("✅ SPLIT FORNITORI COMPLETATO"); $this->info("📥 Anagrafiche uniche: {$anagraficheImported}"); $this->info("📥 Dati specifici: {$specificiImported}"); if ($testMode) { $this->warn("🧪 MODALITÀ TEST - Nessun dato salvato"); } } private function importAnagraficaUnica($fornitore, $testMode) { // Verifica se anagrafica esiste già $existing = DB::table('anagrafica_unica_fornitori') ->where('codice_fornitore_gescon', $fornitore->cod_forn) ->first(); if ($existing) { return $existing->id; } // Prepara dati anagrafica $anagraficaData = [ 'codice_fornitore_gescon' => $fornitore->cod_forn, 'ragione_sociale' => $this->cleanString($fornitore->ragione_sociale), 'denominazione' => $this->cleanString($fornitore->descrizione ?? $fornitore->ragione_sociale), // Estrai nome/cognome se è una persona fisica 'nome' => $this->extractNome($fornitore->ragione_sociale), 'cognome' => $this->extractCognome($fornitore->ragione_sociale), 'codice_fiscale' => $this->cleanString($fornitore->codice_fiscale ?? ''), 'partita_iva' => $this->cleanString($fornitore->partita_iva ?? ''), 'indirizzo' => $this->cleanString($fornitore->indirizzo ?? ''), 'citta' => $this->cleanString($fornitore->citta ?? ''), 'provincia' => $this->cleanString($fornitore->provincia ?? ''), 'cap' => $this->cleanString($fornitore->cap ?? ''), 'telefono' => $this->cleanString($fornitore->telefono ?? ''), 'telefono2' => $this->cleanString($fornitore->telefono2 ?? ''), 'cellulare' => $this->cleanString($fornitore->cellulare ?? ''), 'fax' => $this->cleanString($fornitore->fax ?? ''), 'email' => $this->cleanString($fornitore->email ?? ''), 'pec' => $this->cleanString($fornitore->pec ?? ''), 'banca' => $this->cleanString($fornitore->banca ?? ''), 'iban' => $this->cleanString($fornitore->iban ?? ''), 'note' => $this->cleanString($fornitore->note ?? '') ]; if (!$testMode) { return DB::table('anagrafica_unica_fornitori')->insertGetId($anagraficaData); } return 999; // ID fittizio per test } private function importDatiSpecifici($fornitore, $anagraficaId, $stabileId, $testMode) { // Prepara dati specifici per stabile $specificiData = [ 'stabile_id' => $stabileId, 'anagrafica_fornitore_id' => $anagraficaId, 'codice_interno_stabile' => $fornitore->cod_forn, // Deduce categoria dal nome/note 'categoria_servizio' => $this->deduceCategoria($fornitore->ragione_sociale, $fornitore->note ?? ''), 'tipo_contratto' => $this->deduceTipoContratto($fornitore->note ?? ''), // Default operativi 'giorni_pagamento' => 30, 'attivo' => true, 'note_stabile' => $this->cleanString($fornitore->note ?? '') ]; if (!$testMode) { try { DB::table('fornitori_stabili_specifici')->insert($specificiData); return true; } catch (\Exception $e) { $this->error("❌ Errore import specifici fornitore {$fornitore->cod_forn}: " . $e->getMessage()); return false; } } return true; } private function cleanString($string) { if (empty($string)) return null; return trim(preg_replace('/\s+/', ' ', $string)); } private function extractNome($ragioneSociale) { // Logica semplice per estrarre nome se sembra una persona fisica if (empty($ragioneSociale)) return null; $parts = explode(' ', trim($ragioneSociale)); if (count($parts) >= 2 && !$this->isCompany($ragioneSociale)) { return $parts[0]; } return null; } private function extractCognome($ragioneSociale) { if (empty($ragioneSociale)) return null; $parts = explode(' ', trim($ragioneSociale)); if (count($parts) >= 2 && !$this->isCompany($ragioneSociale)) { return implode(' ', array_slice($parts, 1)); } return null; } private function isCompany($ragioneSociale) { $companyIndicators = ['SRL', 'SPA', 'SAS', 'SNC', 'DITTA', 'AZIENDA', 'IMPRESA', 'COOPERATIVA']; $ragioneSociale = strtoupper($ragioneSociale); foreach ($companyIndicators as $indicator) { if (strpos($ragioneSociale, $indicator) !== false) { return true; } } return false; } private function deduceCategoria($ragioneSociale, $note) { $categorieMap = [ 'ELETTRIC' => 'Elettricista', 'IDRAUL' => 'Idraulico', 'PULIZIE' => 'Pulizie', 'MANUTENZ' => 'Manutenzione', 'GIARDIN' => 'Giardinaggio', 'ASCENSOR' => 'Ascensori', 'RISCALD' => 'Riscaldamento', 'PORTIER' => 'Portierato', 'AMMINISTR' => 'Amministrazione', 'LEGAL' => 'Legale', 'CONTAB' => 'Contabilità' ]; $text = strtoupper($ragioneSociale . ' ' . $note); foreach ($categorieMap as $keyword => $categoria) { if (strpos($text, $keyword) !== false) { return $categoria; } } return 'Generale'; } private function deduceTipoContratto($note) { $note = strtoupper($note); if (strpos($note, 'CONTRATTO') !== false) return 'Contratto'; if (strpos($note, 'ABBONAMENTO') !== false) return 'Abbonamento'; if (strpos($note, 'OCCASIONALE') !== false) return 'Occasionale'; return 'Standard'; } }