netgescon-day0/app/Console/Commands/SplitGesconFornitori.php

334 lines
12 KiB
PHP
Executable File

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class SplitGesconFornitori extends Command
{
protected $signature = 'gescon:split-fornitori
{--test : Modalità test, non salva i dati}
{--stabile-id=1 : ID dello stabile per dati specifici}';
protected $description = 'Divide i fornitori GESCON tra anagrafica unica e dati specifici';
public function handle()
{
$testMode = $this->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';
}
}