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

274 lines
11 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class MapGesconStabiliCommand extends Command
{
protected $signature = 'gescon:import-stabili
{--mdb=/home/michele/netgescon/docs/02-architettura-laravel/Gescon/dbc/Stabili.mdb : Percorso file Stabili.mdb}
{--linux-base=/home/michele/netgescon/docs/02-architettura-laravel/Gescon/ : Base path Linux per cartelle stabile}
{--win-base= : Base path Windows}
{--dry-run : Simula senza scrivere}';
protected $description = 'Importa/aggiorna stabili da Stabili.mdb in tabella dominio e salva riferimenti Gescon in configurazione_avanzata';
public function handle(): int
{
$mdb = $this->option('mdb');
$linuxBase = rtrim((string)($this->option('linux-base') ?? ''), '/') . '/';
$winBase = $this->option('win-base');
$dry = (bool)$this->option('dry-run');
if (!is_file($mdb)) {
$this->error("File MDB non trovato: $mdb");
return 1;
}
if (!Schema::hasTable('stabili')) {
$this->error('Tabella stabili non presente.');
return 1;
}
$rows = $this->exportMdbTable($mdb, 'Stabili');
if (empty($rows)) {
$this->warn('Nessuna riga letta da Stabili.mdb');
return 0;
}
$created = 0;
$updated = 0;
$skipped = 0;
foreach ($rows as $row) {
$r = $this->normalizeKeys($row);
$nomeDir = trim($r['nome_directory'] ?? '');
$codStab = trim((string)($r['cod_stabile'] ?? ''));
if ($nomeDir === '' && $codStab === '') {
$skipped++;
continue;
}
$colCode = Schema::hasColumn('stabili', 'codice_stabile') ? 'codice_stabile' : (Schema::hasColumn('stabili', 'denominazione') ? 'denominazione' : null);
if (!$colCode) {
$this->error('Colonna codice/denominazione non disponibile in stabili.');
return 1;
}
$exists = DB::table('stabili')->where($colCode, $nomeDir ?: $codStab)->first();
if (!$exists && !empty($codStab) && Schema::hasColumn('stabili', 'old_id')) {
$exists = DB::table('stabili')->where('old_id', $codStab)->first();
}
$data = [
$colCode => $nomeDir ?: $codStab,
'denominazione' => $r['denominazione'] ?? ($r['fe_denominazione'] ?? ($nomeDir ?: $codStab)),
'indirizzo' => $r['indirizzo'] ?? ($r['indir_autorizzazione'] ?? ($r['indir_autorizzazione_2'] ?? 'ND')),
'cap' => $this->sanitizeCap($r['cap'] ?? null) ?: '00000',
'citta' => $this->sanitizeCitta($r['citta'] ?? null) ?: 'ND',
'provincia' => $this->sanitizeProvincia($r['pr'] ?? null) ?: 'XX',
'codice_destinatario_sdi' => $r['fe_codice_destinatario'] ?? null,
'pec_condominio' => $r['fe_pec'] ?? null,
'updated_at' => now(),
];
$configExtra = [
'gescon' => [
'cod_stabile' => $codStab ?: null,
'nome_directory' => $nomeDir ?: null,
'path_linux' => $linuxBase && $nomeDir ? ($linuxBase . $nomeDir . '/') : null,
'path_windows' => $winBase && $nomeDir ? ($winBase . '\\' . $nomeDir . '\\') : null,
],
'ac_catasto' => $this->collectPrefix($r, 'ac_'),
'fe' => $this->collectPrefix($r, 'fe_'),
'rata_flags' => [
'ord' => $this->collectPrefix($r, 'ord_rata_'),
'ris' => $this->collectPrefix($r, 'ris_rata_'),
],
'770' => $this->collectPrefix($r, 'amm_770_'),
'banca' => [
'abi' => $r['abi'] ?? null,
'cab' => $r['cab'] ?? null,
'sia' => $r['sia'] ?? null,
'iban_banca' => $r['iban_banca'] ?? null,
'iban_posta' => $r['iban_posta'] ?? null,
'banca' => $r['banca'] ?? null,
'banca2' => $r['banca2'] ?? null,
'num_ccp' => $r['num_ccp'] ?? null,
'intestaz_ccp' => $r['intestaz_ccp'] ?? null,
],
];
if ($exists) {
if (!$dry) {
// Safe assign old_id only if free or same row
if (!empty($codStab) && Schema::hasColumn('stabili', 'old_id')) {
$holder = DB::table('stabili')->where('old_id', $codStab)->first();
if (!$holder || $holder->id == $exists->id) {
$data['old_id'] = $codStab;
}
}
$merged = $this->mergeConfigJson($exists->configurazione_avanzata ?? null, $configExtra);
$data['configurazione_avanzata'] = $merged;
$this->safeUpdate('stabili', ['id' => $exists->id], $data);
}
$updated++;
} else {
if (!$dry) {
// Ensure amministratore_id if column is NOT nullable
if (Schema::hasColumn('stabili', 'amministratore_id')) {
$ammin = DB::table('amministratori')->first();
if (!$ammin) {
// Create minimal user+amministratore seed
$user = DB::table('users')->first();
if (!$user) {
$userId = DB::table('users')->insertGetId([
'name' => 'Admin Seed',
'email' => 'admin-seed@example.local',
'password' => bcrypt('password'),
'created_at' => now(),
'updated_at' => now(),
]);
} else {
$userId = $user->id;
}
$amminId = DB::table('amministratori')->insertGetId([
'nome' => 'Admin',
'cognome' => 'Seed',
'user_id' => $userId,
'codice_univoco' => 'ASEED001',
'created_at' => now(),
'updated_at' => now(),
]);
} else {
$amminId = $ammin->id;
}
$data['amministratore_id'] = $amminId;
}
$data['attivo'] = true;
$data['created_at'] = now();
$data['configurazione_avanzata'] = json_encode($configExtra);
// Safe set old_id only if not taken
if (!empty($codStab) && Schema::hasColumn('stabili', 'old_id')) {
$existsOld = DB::table('stabili')->where('old_id', $codStab)->exists();
if (!$existsOld) {
$data['old_id'] = $codStab;
}
}
$this->safeInsert('stabili', $data);
}
$created++;
}
}
$this->info("Stabili importati. Creati: $created, Aggiornati: $updated, Ignorati: $skipped");
return 0;
}
private function exportMdbTable(string $mdbPath, string $table): array
{
// Use a temp file to let fgetcsv handle embedded newlines safely
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
$cmd = sprintf(
'mdb-export -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null',
escapeshellarg('%Y-%m-%d'),
escapeshellarg('|'),
escapeshellarg('"'),
escapeshellarg($mdbPath),
escapeshellarg($table),
escapeshellarg($tmp)
);
shell_exec($cmd);
if (!is_file($tmp) || filesize($tmp) === 0) {
@unlink($tmp);
return [];
}
$fh = fopen($tmp, 'r');
if (!$fh) {
@unlink($tmp);
return [];
}
$headers = fgetcsv($fh, 0, '|');
if (!$headers) {
fclose($fh);
@unlink($tmp);
return [];
}
$headers = array_map(fn($h) => strtolower(trim($h)), $headers);
$rows = [];
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
if (count($cols) !== count($headers)) {
// pad/truncate to match headers length
$cols = array_pad($cols, count($headers), null);
$cols = array_slice($cols, 0, count($headers));
}
$rows[] = array_combine($headers, $cols);
}
fclose($fh);
@unlink($tmp);
return $rows;
}
private function normalizeKeys(array $row): array
{
$norm = [];
foreach ($row as $k => $v) {
$norm[strtolower($k)] = $v;
}
return $norm;
}
private function collectPrefix(array $r, string $prefix): array
{
$out = [];
foreach ($r as $k => $v) {
if (str_starts_with($k, $prefix)) $out[$k] = $v;
}
return $out;
}
private function mergeConfigJson(?string $existingJson, array $extra): string
{
$existing = $existingJson ? (json_decode($existingJson, true) ?: []) : [];
return json_encode(array_replace_recursive($existing, $extra));
}
private function safeInsert(string $table, array $data): void
{
$cols = Schema::getColumnListing($table);
DB::table($table)->insert(array_intersect_key($data, array_flip($cols)));
}
private function safeUpdate(string $table, array $where, array $data): void
{
$cols = Schema::getColumnListing($table);
DB::table($table)->where($where)->update(array_intersect_key($data, array_flip($cols)));
}
private function sanitizeCap($v): ?string
{
if ($v === null || $v === '') return null;
$s = preg_replace('/[^0-9]/', '', (string)$v);
if ($s === '') return null;
return substr($s, 0, 5);
}
private function sanitizeProvincia($v): ?string
{
if ($v === null || $v === '') return null;
$s = strtoupper(preg_replace('/[^A-Z]/', '', (string)$v));
if ($s === '') return null;
return substr($s, 0, 2);
}
private function sanitizeCitta($v): ?string
{
if ($v === null || $v === '') return null;
$s = trim((string)$v);
// Rimuovi spazi interni anomali tipo 'R O M A'
if (preg_match('/^(?:[A-Z]\s+)+[A-Z]$/', strtoupper($s))) {
$s = preg_replace('/\s+/', '', $s);
}
return substr($s, 0, 100);
}
}