520 lines
19 KiB
PHP
Executable File
520 lines
19 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
class ImportGesconCompleteData extends Command
|
|
{
|
|
protected $signature = 'gescon:import-complete
|
|
{--admin-code= : Codice amministratore specifico}
|
|
{--stabile= : Codice stabile specifico}
|
|
{--test : Modalità test senza modifiche}
|
|
{--euro-only : Solo importi in EURO}';
|
|
|
|
protected $description = 'Import completo dati GESCON in database intermedio';
|
|
|
|
private $gesconDb;
|
|
private $netgesconDb;
|
|
private $basePath = '/home/michele/netgescon/docs/02-architettura-laravel/Gescon';
|
|
private $importStats = [];
|
|
|
|
public function handle()
|
|
{
|
|
$this->info('🚀 GESCON IMPORT COMPLETO - Avvio importazione...');
|
|
|
|
// Inizializza connessioni
|
|
$this->gesconDb = DB::connection('gescon_import');
|
|
$this->netgesconDb = DB::connection('mysql');
|
|
|
|
$isTest = $this->option('test');
|
|
$euroOnly = $this->option('euro-only') ?? true; // Default: solo EURO
|
|
|
|
if ($isTest) {
|
|
$this->warn('🧪 MODALITÀ TEST - Nessuna modifica verrà salvata');
|
|
}
|
|
|
|
if ($euroOnly) {
|
|
$this->info('💰 MODALITÀ EURO-ONLY - Ignoro campi in lire');
|
|
}
|
|
|
|
try {
|
|
// FASE 1: Import anagrafica base
|
|
$this->importAnagraficaBase($isTest);
|
|
|
|
// FASE 2: Import configurazioni gestioni
|
|
$this->importConfigurazioniGestioni($isTest);
|
|
|
|
// FASE 3: Import dati contabili per stabile
|
|
$this->importDatiContabiliStabili($isTest, $euroOnly);
|
|
|
|
// FASE 4: Mappatura verso NetGescon
|
|
$this->mappaVersNetGescon($isTest);
|
|
|
|
// Report finale
|
|
$this->showFinalReport();
|
|
} catch (\Exception $e) {
|
|
$this->error('❌ Errore durante importazione: ' . $e->getMessage());
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private function importAnagraficaBase($isTest = false)
|
|
{
|
|
$this->info('📊 FASE 1: Import anagrafica base...');
|
|
|
|
// 1. Import Stabili da Stabili.csv
|
|
$stabiliFile = $this->basePath . '/dbc/Stabili.csv';
|
|
if (File::exists($stabiliFile)) {
|
|
$this->importStabiliCsv($stabiliFile, $isTest);
|
|
}
|
|
|
|
// 2. Import Fornitori da dbc/Fornitori.mdb
|
|
$fornitoriMdb = $this->basePath . '/dbc/Fornitori.mdb';
|
|
if (File::exists($fornitoriMdb)) {
|
|
$this->importFornitoriMdb($fornitoriMdb, $isTest);
|
|
}
|
|
}
|
|
|
|
private function importStabiliCsv($file, $isTest = false)
|
|
{
|
|
$this->info(" 📁 Importo Stabili da: {$file}");
|
|
|
|
if (!File::exists($file)) {
|
|
$this->warn(" ⚠️ File non trovato: {$file}");
|
|
return;
|
|
}
|
|
|
|
$handle = fopen($file, 'r');
|
|
$header = fgetcsv($handle); // Prima riga header
|
|
$count = 0;
|
|
|
|
while (($row = fgetcsv($handle)) !== false) {
|
|
try {
|
|
// Mappa solo campi essenziali
|
|
$data = [
|
|
'cod_stabile' => $row[1] ?? null, // Campo 2: cod_stabile
|
|
'denominazione' => $row[2] ?? 'Senza denominazione', // Campo 3
|
|
'indirizzo' => $row[3] ?? null, // Campo 4
|
|
'cap' => $row[4] ?? null, // Campo 5
|
|
'citta' => $row[5] ?? null, // Campo 6
|
|
'provincia' => $row[6] ?? null, // Campo 7
|
|
'codice_fiscale' => $row[7] ?? null, // Campo 8
|
|
'cf_amministratore' => $row[8] ?? null, // Campo 9
|
|
'scale' => is_numeric($row[9] ?? null) ? (int)$row[9] : null,
|
|
'n_interni' => is_numeric($row[10] ?? null) ? (int)$row[10] : null,
|
|
'codice_directory' => $row[11] ?? null, // Campo 12
|
|
'flag_attivo' => true,
|
|
'iban' => $row[80] ?? null, // Campo IBAN se presente
|
|
];
|
|
|
|
// Controllo campi obbligatori
|
|
if (empty($data['cod_stabile']) || empty($data['codice_directory'])) {
|
|
$this->warn(" ⚠️ Stabile saltato - Dati incompleti");
|
|
continue;
|
|
}
|
|
|
|
if (!$isTest) {
|
|
// Verifica duplicati
|
|
$exists = $this->gesconDb->table('stabili')
|
|
->where('cod_stabile', $data['cod_stabile'])
|
|
->exists();
|
|
|
|
if (!$exists) {
|
|
$this->gesconDb->table('stabili')->insert($data);
|
|
$count++;
|
|
$this->line(" ✅ Stabile {$data['cod_stabile']}: {$data['denominazione']}");
|
|
} else {
|
|
$this->line(" 🔄 Stabile {$data['cod_stabile']}: già presente");
|
|
}
|
|
} else {
|
|
$count++;
|
|
$this->line(" 🧪 TEST - Stabile {$data['cod_stabile']}: {$data['denominazione']}");
|
|
}
|
|
} catch (\Exception $e) {
|
|
$this->warn(" ❌ Errore riga: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
fclose($handle);
|
|
$this->importStats['stabili'] = $count;
|
|
$this->info(" 📊 Stabili importati: {$count}");
|
|
}
|
|
|
|
private function importFornitoriMdb($file, $isTest = false)
|
|
{
|
|
$this->info(" 📁 Importo Fornitori da: {$file}");
|
|
|
|
try {
|
|
// Esporta tabella fornitori da MDB
|
|
$csvTemp = '/tmp/fornitori_temp.csv';
|
|
exec("mdb-export '{$file}' Fornitori > {$csvTemp} 2>/dev/null", $output, $result);
|
|
|
|
if ($result !== 0 || !File::exists($csvTemp)) {
|
|
$this->warn(" ⚠️ Impossibile esportare fornitori da MDB");
|
|
return;
|
|
}
|
|
|
|
$handle = fopen($csvTemp, 'r');
|
|
$header = fgetcsv($handle);
|
|
$count = 0;
|
|
|
|
// Trova indici colonne importanti (case-insensitive)
|
|
$indices = $this->findColumnIndices($header, [
|
|
'cod_forn',
|
|
'cognome',
|
|
'nome',
|
|
'denominazione',
|
|
'cod_fisc',
|
|
'p_iva',
|
|
'indirizzo',
|
|
'cap',
|
|
'citta',
|
|
'pr',
|
|
'telef_1',
|
|
'indir_email',
|
|
'cod_iban'
|
|
]);
|
|
|
|
while (($row = fgetcsv($handle)) !== false) {
|
|
try {
|
|
// Costruisce ragione sociale da cognome+nome o denominazione
|
|
$ragioneSociale = '';
|
|
if (!empty($row[$indices['denominazione'] ?? -1])) {
|
|
$ragioneSociale = $row[$indices['denominazione']];
|
|
} else {
|
|
$cognome = $row[$indices['cognome'] ?? -1] ?? '';
|
|
$nome = $row[$indices['nome'] ?? -1] ?? '';
|
|
$ragioneSociale = trim($cognome . ' ' . $nome);
|
|
}
|
|
|
|
if (empty($ragioneSociale)) {
|
|
$ragioneSociale = 'Fornitore senza nome';
|
|
}
|
|
|
|
$data = [
|
|
'cod_forn' => $row[$indices['cod_forn'] ?? -1] ?? null,
|
|
'ragione_sociale' => $ragioneSociale,
|
|
'codice_fiscale' => $row[$indices['cod_fisc'] ?? -1] ?? null,
|
|
'partita_iva' => $row[$indices['p_iva'] ?? -1] ?? null,
|
|
'indirizzo' => $row[$indices['indirizzo'] ?? -1] ?? null,
|
|
'cap' => $row[$indices['cap'] ?? -1] ?? null,
|
|
'citta' => $row[$indices['citta'] ?? -1] ?? null,
|
|
'provincia' => $row[$indices['pr'] ?? -1] ?? null,
|
|
'telefono' => $row[$indices['telef_1'] ?? -1] ?? null,
|
|
'email' => $row[$indices['indir_email'] ?? -1] ?? null,
|
|
'iban' => $row[$indices['cod_iban'] ?? -1] ?? null,
|
|
'attivo' => true,
|
|
];
|
|
|
|
if (empty($data['cod_forn'])) continue;
|
|
|
|
if (!$isTest) {
|
|
$exists = $this->gesconDb->table('fornitori')
|
|
->where('cod_forn', $data['cod_forn'])
|
|
->exists();
|
|
|
|
if (!$exists) {
|
|
$this->gesconDb->table('fornitori')->insert($data);
|
|
$count++;
|
|
}
|
|
} else {
|
|
$count++;
|
|
$this->line(" 🧪 TEST - Fornitore {$data['cod_forn']}: {$data['ragione_sociale']}");
|
|
}
|
|
} catch (\Exception $e) {
|
|
$this->warn(" ❌ Errore fornitore: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
fclose($handle);
|
|
unlink($csvTemp);
|
|
|
|
$this->importStats['fornitori'] = $count;
|
|
$this->info(" 📊 Fornitori importati: {$count}");
|
|
} catch (\Exception $e) {
|
|
$this->warn(" ❌ Errore import fornitori: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function importConfigurazioniGestioni($isTest = false)
|
|
{
|
|
$this->info('📊 FASE 2: Import configurazioni gestioni...');
|
|
|
|
// Itera ogni stabile per trovare i suoi anni di gestione
|
|
$stabili = $this->gesconDb->table('stabili')->get();
|
|
|
|
foreach ($stabili as $stabile) {
|
|
$this->importAnniGestioneStabile($stabile->cod_stabile, $stabile->codice_directory, $isTest);
|
|
}
|
|
}
|
|
|
|
private function importAnniGestioneStabile($codStabile, $codiceDirectory, $isTest = false)
|
|
{
|
|
$stabileDir = $this->basePath . "/{$codiceDirectory}";
|
|
|
|
if (!File::isDirectory($stabileDir)) {
|
|
$this->warn(" ⚠️ Directory stabile non trovata: {$stabileDir}");
|
|
return;
|
|
}
|
|
|
|
// Cerca file anni.csv o simili
|
|
$anniFile = $stabileDir . '/anni.csv';
|
|
if (!File::exists($anniFile)) {
|
|
// Cerca subdirectory per anni (0001, 0002, etc.)
|
|
$subdirs = glob($stabileDir . '/[0-9][0-9][0-9][0-9]', GLOB_ONLYDIR);
|
|
|
|
foreach ($subdirs as $subdir) {
|
|
$anno = 2020 + (int)basename($subdir); // Stima anno da directory
|
|
$this->createAnnoGestione($codStabile, $anno, $isTest);
|
|
}
|
|
} else {
|
|
$this->importAnniCsv($anniFile, $codStabile, $isTest);
|
|
}
|
|
}
|
|
|
|
private function createAnnoGestione($codStabile, $anno, $isTest = false)
|
|
{
|
|
$data = [
|
|
'cod_stabile' => $codStabile,
|
|
'anno' => $anno,
|
|
'data_inizio' => "{$anno}-01-01",
|
|
'data_fine' => "{$anno}-12-31",
|
|
'chiuso' => $anno < date('Y'),
|
|
];
|
|
|
|
if (!$isTest) {
|
|
$exists = $this->gesconDb->table('anni_gestione')
|
|
->where('cod_stabile', $codStabile)
|
|
->where('anno', $anno)
|
|
->exists();
|
|
|
|
if (!$exists) {
|
|
$this->gesconDb->table('anni_gestione')->insert($data);
|
|
$this->line(" ✅ Anno gestione {$codStabile}/{$anno}");
|
|
}
|
|
} else {
|
|
$this->line(" 🧪 TEST - Anno gestione {$codStabile}/{$anno}");
|
|
}
|
|
}
|
|
|
|
private function importDatiContabiliStabili($isTest = false, $euroOnly = true)
|
|
{
|
|
$this->info('📊 FASE 3: Import dati contabili per stabile...');
|
|
|
|
$stabili = $this->gesconDb->table('stabili')->get();
|
|
|
|
foreach ($stabili as $stabile) {
|
|
$this->info(" 🏢 Elaboro stabile: {$stabile->cod_stabile} - {$stabile->denominazione}");
|
|
$this->importDatiStabile($stabile, $isTest, $euroOnly);
|
|
}
|
|
}
|
|
|
|
private function importDatiStabile($stabile, $isTest = false, $euroOnly = true)
|
|
{
|
|
$stabileDir = $this->basePath . "/{$stabile->codice_directory}";
|
|
|
|
// 1. Import da generale_stabile.mdb (se presente)
|
|
$generaleMdb = $stabileDir . '/generale_stabile.mdb';
|
|
if (File::exists($generaleMdb)) {
|
|
$this->importFromGeneraleStabile($generaleMdb, $stabile->cod_stabile, $isTest, $euroOnly);
|
|
}
|
|
|
|
// 2. Import da singolo_anno.mdb per ogni anno
|
|
$subdirs = glob($stabileDir . '/[0-9][0-9][0-9][0-9]', GLOB_ONLYDIR);
|
|
foreach ($subdirs as $subdir) {
|
|
$anno = 2020 + (int)basename($subdir);
|
|
$singoloAnnoMdb = $subdir . '/singolo_anno.mdb';
|
|
|
|
if (File::exists($singoloAnnoMdb)) {
|
|
$this->importFromSingoloAnno($singoloAnnoMdb, $stabile->cod_stabile, $anno, $isTest, $euroOnly);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function importFromSingoloAnno($mdbFile, $codStabile, $anno, $isTest = false, $euroOnly = true)
|
|
{
|
|
$this->line(" 📅 Anno {$anno}: {$mdbFile}");
|
|
|
|
$tabelle = ['condomin', 'voc_spe', 'Operazioni', 'rate', 'incassi', 'dett_tab'];
|
|
|
|
foreach ($tabelle as $tabella) {
|
|
try {
|
|
$csvTemp = "/tmp/{$tabella}_{$codStabile}_{$anno}.csv";
|
|
exec("mdb-export '{$mdbFile}' '{$tabella}' > {$csvTemp} 2>/dev/null", $output, $result);
|
|
|
|
if ($result === 0 && File::exists($csvTemp)) {
|
|
$count = $this->importTabellaSpecifica($csvTemp, $tabella, $codStabile, $anno, $isTest, $euroOnly);
|
|
$this->line(" ✅ {$tabella}: {$count} record");
|
|
unlink($csvTemp);
|
|
} else {
|
|
$this->line(" ⚠️ {$tabella}: non disponibile");
|
|
}
|
|
} catch (\Exception $e) {
|
|
$this->warn(" ❌ Errore {$tabella}: " . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
private function importTabellaSpecifica($csvFile, $tabella, $codStabile, $anno, $isTest = false, $euroOnly = true)
|
|
{
|
|
$handle = fopen($csvFile, 'r');
|
|
$header = fgetcsv($handle);
|
|
$count = 0;
|
|
|
|
// Metodi specifici per ogni tabella
|
|
$method = 'import' . ucfirst($tabella) . 'Data';
|
|
if (method_exists($this, $method)) {
|
|
while (($row = fgetcsv($handle)) !== false) {
|
|
try {
|
|
$processed = $this->$method($row, $header, $codStabile, $anno, $euroOnly);
|
|
if ($processed && !$isTest) {
|
|
$count++;
|
|
} elseif ($processed && $isTest) {
|
|
$count++;
|
|
}
|
|
} catch (\Exception $e) {
|
|
// Ignora errori singoli
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose($handle);
|
|
return $count;
|
|
}
|
|
|
|
private function importCondominData($row, $header, $codStabile, $anno, $euroOnly)
|
|
{
|
|
$indices = $this->findColumnIndices($header, [
|
|
'id_cond',
|
|
'cod_cond',
|
|
'cognome',
|
|
'nome',
|
|
'cf',
|
|
'codice_fiscale',
|
|
'indirizzo',
|
|
'cap',
|
|
'citta',
|
|
'telefono',
|
|
'email',
|
|
'mm_prop',
|
|
'millesimi'
|
|
]);
|
|
|
|
$data = [
|
|
'cod_stabile' => $codStabile,
|
|
'id_cond' => $row[$indices['id_cond']] ?? null,
|
|
'cod_cond' => $row[$indices['cod_cond']] ?? null,
|
|
'cognome' => $row[$indices['cognome']] ?? null,
|
|
'nome' => $row[$indices['nome']] ?? null,
|
|
'codice_fiscale' => $row[$indices['cf']] ?? $row[$indices['codice_fiscale']] ?? null,
|
|
'indirizzo' => $row[$indices['indirizzo']] ?? null,
|
|
'cap' => $row[$indices['cap']] ?? null,
|
|
'citta' => $row[$indices['citta']] ?? null,
|
|
'telefono' => $row[$indices['telefono']] ?? null,
|
|
'email' => $row[$indices['email']] ?? null,
|
|
'millesimi_proprieta' => $row[$indices['mm_prop']] ?? $row[$indices['millesimi']] ?? null,
|
|
];
|
|
|
|
if (!empty($data['id_cond'])) {
|
|
$exists = $this->gesconDb->table('condomini')
|
|
->where('cod_stabile', $codStabile)
|
|
->where('id_cond', $data['id_cond'])
|
|
->exists();
|
|
|
|
if (!$exists) {
|
|
$this->gesconDb->table('condomini')->insert($data);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function importVoc_speData($row, $header, $codStabile, $anno, $euroOnly)
|
|
{
|
|
$indices = $this->findColumnIndices($header, [
|
|
'cod',
|
|
'descriz',
|
|
'tabella',
|
|
'preventivo_euro',
|
|
'consuntivo_euro',
|
|
'Perc_proprietario',
|
|
'Perc_Inquilino'
|
|
]);
|
|
|
|
// Solo valori in EURO se richiesto
|
|
$preventivo = $euroOnly ? ($row[$indices['preventivo_euro']] ?? null) : null;
|
|
$consuntivo = $euroOnly ? ($row[$indices['consuntivo_euro']] ?? null) : null;
|
|
|
|
$data = [
|
|
'cod_stabile' => $codStabile,
|
|
'anno' => $anno,
|
|
'cod_voce' => $row[$indices['cod']] ?? null,
|
|
'descrizione' => $row[$indices['descriz']] ?? 'Voce senza descrizione',
|
|
'tabella_millesimi' => $row[$indices['tabella']] ?? null,
|
|
'perc_proprietario' => $row[$indices['Perc_proprietario']] ?? null,
|
|
'perc_inquilino' => $row[$indices['Perc_Inquilino']] ?? null,
|
|
'preventivo_euro' => is_numeric($preventivo) ? $preventivo : null,
|
|
'consuntivo_euro' => is_numeric($consuntivo) ? $consuntivo : null,
|
|
];
|
|
|
|
if (!empty($data['cod_voce'])) {
|
|
$exists = $this->gesconDb->table('voci_spesa')
|
|
->where('cod_stabile', $codStabile)
|
|
->where('anno', $anno)
|
|
->where('cod_voce', $data['cod_voce'])
|
|
->exists();
|
|
|
|
if (!$exists) {
|
|
$this->gesconDb->table('voci_spesa')->insert($data);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private function mappaVersNetGescon($isTest = false)
|
|
{
|
|
$this->info('📊 FASE 4: Mappatura verso NetGescon...');
|
|
|
|
if ($isTest) {
|
|
$this->warn('🧪 TEST - Mappatura simulata');
|
|
return;
|
|
}
|
|
|
|
// Qui implementeremo il mapping selettivo verso NetGescon
|
|
// mantenendo l'anagrafica unica e le relazioni
|
|
$this->info(' 🔄 Mappatura in sviluppo...');
|
|
}
|
|
|
|
private function findColumnIndices($header, $columns)
|
|
{
|
|
$indices = [];
|
|
foreach ($columns as $col) {
|
|
$index = array_search(strtolower($col), array_map('strtolower', $header));
|
|
if ($index !== false) {
|
|
$indices[$col] = $index;
|
|
}
|
|
}
|
|
return $indices;
|
|
}
|
|
|
|
private function showFinalReport()
|
|
{
|
|
$this->info('📊 REPORT FINALE IMPORTAZIONE');
|
|
$this->info('================================');
|
|
|
|
foreach ($this->importStats as $tipo => $count) {
|
|
$this->info(" {$tipo}: {$count} record");
|
|
}
|
|
|
|
$this->info('✅ Importazione completata!');
|
|
}
|
|
}
|