334 lines
12 KiB
PHP
334 lines
12 KiB
PHP
<?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';
|
|
}
|
|
}
|