option('stabile'), 4, '0', STR_PAD_LEFT); $ammCode = 'HWFGITXK'; if ($this->option('refresh')) { DB::connection('gescon_import')->table('condomin_mirror')->truncate(); $this->info("Tabella gescon_import.condomin_mirror svuotata."); } $baseDirs = [ "/mnt/gescon-archives/gescon/{$stabileCode}", storage_path("app/amministratori/{$ammCode}/legacy/{$stabileCode}") ]; $targetDir = null; foreach ($baseDirs as $dir) { if (is_dir($dir)) { $targetDir = $dir; break; } } if (! $targetDir) { $this->error("Directory MDB non trovata per lo stabile {$stabileCode}"); return Command::FAILURE; } $fileConfigs = [ '0001' => ['year' => '0001', 'rel' => "{$stabileCode}/0001/singolo_anno.mdb", 'path' => "{$targetDir}/0001/singolo_anno.mdb"], '0003' => ['year' => '0003', 'rel' => "{$stabileCode}/0003/singolo_anno.mdb", 'path' => "{$targetDir}/0003/singolo_anno.mdb"], '0004' => ['year' => '0004', 'rel' => "{$stabileCode}/0004/singolo_anno.mdb", 'path' => "{$targetDir}/0004/singolo_anno.mdb"], ]; $perFileCounts = []; $totalMdbRows = 0; foreach ($fileConfigs as $key => $cfg) { if (! file_exists($cfg['path'])) { $this->warn("File non trovato: {$cfg['path']}"); continue; } $rows = $this->extractMdbCondominRows($cfg['path']); $count = count($rows); $totalMdbRows += $count; $perFileCounts[$key] = [ 'rel' => $cfg['rel'], 'year' => $cfg['year'], 'mdb_rows' => $count, 'imported' => 0 ]; $rowNum = 0; foreach ($rows as $r) { $rowNum++; $provHash = hash('sha256', "{$ammCode}|{$stabileCode}|{$cfg['rel']}|{$cfg['year']}|condomin|{$rowNum}"); // Extract real MDB interno column (int or interno) without reconstructing from id_cond/cod_cond $rawInterno = isset($r['int']) ? (string)$r['int'] : (isset($r['interno']) ? (string)$r['interno'] : ''); $rawScala = isset($r['scala']) ? (string)$r['scala'] : ''; $rawPiano = isset($r['piano']) ? (string)$r['piano'] : ''; $idCond = isset($r['id_cond']) ? (string)$r['id_cond'] : null; $codCond = isset($r['cod_cond']) ? (string)$r['cod_cond'] : null; $cognome = isset($r['cognome']) ? (string)$r['cognome'] : null; $nome = isset($r['nome']) ? (string)$r['nome'] : null; $nomCond = isset($r['nom_cond']) ? (string)$r['nom_cond'] : null; $codFisc = isset($r['cond_cod_fisc']) ? (string)$r['cond_cod_fisc'] : (isset($r['codice_fiscale']) ? (string)$r['codice_fiscale'] : null); $tel = isset($r['tel1']) ? (string)$r['tel1'] : (isset($r['telefono']) ? (string)$r['telefono'] : null); $cell = isset($r['cell_cond']) ? (string)$r['cell_cond'] : (isset($r['cellulare']) ? (string)$r['cellulare'] : null); $email = isset($r['e_mail_condomino']) ? (string)$r['e_mail_condomino'] : (isset($r['email']) ? (string)$r['email'] : null); $pec = isset($r['pec_condomino']) ? (string)$r['pec_condomino'] : (isset($r['pec']) ? (string)$r['pec'] : null); $proprietario = isset($r['proprietario']) ? (string)$r['proprietario'] : null; $inquilino = isset($r['inquilino']) ? (string)$r['inquilino'] : (isset($r['inquil_nome']) ? (string)$r['inquil_nome'] : null); $subPrima = isset($r['subentro_prima_cera']) ? (string)$r['subentro_prima_cera'] : null; $subAdesso = isset($r['subentro_adesso_ce']) ? (string)$r['subentro_adesso_ce'] : null; $subDal = isset($r['subentrato_dal']) ? (string)$r['subentrato_dal'] : null; $attivoAl = isset($r['attivo_fino_al']) ? (string)$r['attivo_fino_al'] : null; $inquilDal = isset($r['inquil_dal']) ? (string)$r['inquil_dal'] : null; $inquilAl = isset($r['inquil_al']) ? (string)$r['inquil_al'] : null; $dirReale = isset($r['diritto_reale']) ? (string)$r['diritto_reale'] : null; $dirGodimento = isset($r['diritto_godimento']) ? (string)$r['diritto_godimento'] : null; $percDir = isset($r['perc_diritto_reale']) ? (string)$r['perc_diritto_reale'] : null; $millProp = isset($r['millesimi_proprieta']) && is_numeric($r['millesimi_proprieta']) ? (float)$r['millesimi_proprieta'] : null; $millRisc = isset($r['millesimi_riscaldamento']) && is_numeric($r['millesimi_riscaldamento']) ? (float)$r['millesimi_riscaldamento'] : null; $millAsc = isset($r['millesimi_ascensore']) && is_numeric($r['millesimi_ascensore']) ? (float)$r['millesimi_ascensore'] : null; $record = [ 'amministratore_code' => $ammCode, 'cod_stabile' => $stabileCode, 'source_file' => $cfg['rel'], 'source_year' => $cfg['year'], 'source_table' => 'condomin', 'source_row' => $rowNum, 'provenance_hash' => $provHash, 'id_cond' => $idCond, 'cod_cond' => $codCond, 'scala' => trim($rawScala) !== '' ? trim($rawScala) : null, 'interno' => trim($rawInterno) !== '' ? trim($rawInterno) : null, 'piano' => trim($rawPiano) !== '' ? trim($rawPiano) : null, 'cognome' => $cognome, 'nome' => $nome, 'nom_cond' => $nomCond, 'codice_fiscale' => $codFisc, 'telefono' => $tel, 'cellulare' => $cell, 'email' => $email, 'pec' => $pec, 'millesimi_proprieta' => $millProp, 'millesimi_riscaldamento' => $millRisc, 'millesimi_ascensore' => $millAsc, 'proprietario' => $proprietario, 'inquilino' => $inquilino, 'subentro_prima_cera' => $subPrima, 'subentro_adesso_ce' => $subAdesso, 'subentrato_dal' => $subDal, 'attivo_fino_al' => $attivoAl, 'inquil_dal' => $inquilDal, 'inquil_al' => $inquilAl, 'diritto_reale' => $dirReale, 'diritto_godimento' => $dirGodimento, 'perc_diritto_reale' => $percDir, 'legacy_payload' => json_encode($r, JSON_UNESCAPED_UNICODE), 'created_at' => now(), 'updated_at' => now(), ]; DB::connection('gescon_import')->table('condomin_mirror')->updateOrInsert( ['provenance_hash' => $provHash], $record ); $perFileCounts[$key]['imported']++; } } $stagingRows = DB::connection('gescon_import')->table('condomin_mirror')->where('cod_stabile', $stabileCode)->count(); $duplicates = DB::connection('gescon_import')->select(" SELECT provenance_hash, COUNT(*) as cnt FROM condomin_mirror WHERE cod_stabile = ? GROUP BY provenance_hash HAVING cnt > 1 ", [$stabileCode]); $duplicateCount = count($duplicates); $collisionCount = $stagingRows < $totalMdbRows ? ($totalMdbRows - $stagingRows) : 0; $this->info("=== FASE 1A MIRROR STAGING 0021 COMPLETATA ==="); $this->line("MDB_ROWS_TOTAL: {$totalMdbRows}"); $this->line("STAGING_ROWS: {$stagingRows}"); $this->line("COLLISION_COUNT: {$collisionCount}"); $this->line("DUPLICATE_PROVENANCE_COUNT: {$duplicateCount}"); foreach ($perFileCounts as $k => $info) { $this->line("PER_FILE: {$info['rel']} | YEAR: {$info['year']} | MDB: {$info['mdb_rows']} | STAGING: {$info['imported']}"); } return Command::SUCCESS; } private function extractMdbCondominRows(string $mdbPath): array { $proc = new Process(['mdb-export', $mdbPath, 'condomin']); $proc->run(); if (! $proc->isSuccessful()) { return []; } $csvContent = $proc->getOutput(); $stream = fopen('php://memory', 'r+'); fwrite($stream, $csvContent); rewind($stream); $header = fgetcsv($stream); if (! $header) { fclose($stream); return []; } $rows = []; while (($data = fgetcsv($stream)) !== false) { if (count($data) === count($header)) { $rows[] = array_combine($header, $data); } } fclose($stream); return $rows; } }