917 lines
47 KiB
PHP
917 lines
47 KiB
PHP
<?php
|
|
|
|
namespace App\Services\GesconImport;
|
|
|
|
use App\Models\MigrationDataset;
|
|
use App\Models\MigrationRecord;
|
|
use App\Models\UserSetting;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class LegacyArchiveService
|
|
{
|
|
// Public API used by controllers
|
|
public function scanLegacyYears(string $legacy): array
|
|
{
|
|
$base = UserSetting::get('gescon.source_path', '/mnt/gescon-archives/gescon');
|
|
$dir = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy;
|
|
if (!is_dir($dir)) return [];
|
|
$years = [];
|
|
foreach (scandir($dir) as $f) {
|
|
if ($f === '.' || $f === '..') continue;
|
|
if (preg_match('/^\d{4}$/', $f) && is_file($dir . DIRECTORY_SEPARATOR . $f . DIRECTORY_SEPARATOR . 'singolo_anno.mdb')) {
|
|
$years[] = $f;
|
|
}
|
|
}
|
|
sort($years, SORT_STRING);
|
|
return $years;
|
|
}
|
|
|
|
public function gestioniYear(string $legacy, $annoOrFolder): array
|
|
{
|
|
$base = UserSetting::get('gescon.source_path', '/mnt/gescon-archives/gescon');
|
|
$resolve = $this->resolveAnnoFolder($legacy, $annoOrFolder);
|
|
$folder = $resolve['folder'] ?? (is_numeric($annoOrFolder) ? str_pad((string)intval($annoOrFolder), 4, '0', STR_PAD_LEFT) : (string)$annoOrFolder);
|
|
$anno = $resolve['anno'] ?? (is_numeric($annoOrFolder) && (int)$annoOrFolder >= 1900 ? (int)$annoOrFolder : null);
|
|
$period = $resolve['period'] ?? null;
|
|
$dir = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy . DIRECTORY_SEPARATOR . $folder;
|
|
$singoloAnno = $dir . DIRECTORY_SEPARATOR . 'singolo_anno.mdb';
|
|
$generale = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy . DIRECTORY_SEPARATOR . 'generale_stabile.mdb';
|
|
$hasMdbTools = trim((string)@shell_exec('command -v mdb-export')) !== '';
|
|
$ordinaria = null;
|
|
$riscaldamento = null;
|
|
$straord = [];
|
|
if ($hasMdbTools && is_file($singoloAnno) && is_readable($singoloAnno)) {
|
|
try {
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$tablesRaw = @shell_exec(sprintf('%s -1 %s 2>/dev/null', 'mdb-tables', escapeshellarg($singoloAnno))) ?: '';
|
|
$tableCandidates = [];
|
|
foreach (preg_split('/\r?\n/', trim($tablesRaw)) as $t) {
|
|
if ($t === '') continue;
|
|
if (preg_match('/(gest|rate|piano)/i', $t)) $tableCandidates[] = trim($t);
|
|
}
|
|
$table = $tableCandidates[0] ?? null;
|
|
if ($table) {
|
|
$cmd = sprintf(
|
|
'%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null',
|
|
escapeshellarg($binExport),
|
|
escapeshellarg('%Y-%m-%d'),
|
|
escapeshellarg('|'),
|
|
escapeshellarg('"'),
|
|
escapeshellarg($singoloAnno),
|
|
escapeshellarg($table),
|
|
escapeshellarg($tmp)
|
|
);
|
|
@shell_exec($cmd);
|
|
if (@filesize($tmp) > 0) {
|
|
$fh = fopen($tmp, 'r');
|
|
$headers = fgetcsv($fh, 0, '|');
|
|
$headers = $headers ? array_map(fn($h) => strtolower(trim((string)$h)), $headers) : [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null]) continue;
|
|
if (!$headers) break;
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
$tipo = $row['tipo'] ?? ($row['tipo_gestione'] ?? null);
|
|
$isRisc = false;
|
|
if ($tipo) {
|
|
$isRisc = preg_match('/ris|risc|cald/i', $tipo);
|
|
}
|
|
$rate = [];
|
|
foreach ($row as $k => $v) {
|
|
if (preg_match('/^(rata|rata_)(\d{1,2})_(ord|ris)/i', $k, $m)) {
|
|
$num = (int)$m[2];
|
|
$flag = (string)$v !== '0' && $v !== '' && $v !== null;
|
|
if ($flag) $rate[$num] = 1;
|
|
} elseif (preg_match('/^(ord|ris)_rata_(\d{1,2})$/i', $k, $m)) {
|
|
$num = (int)$m[2];
|
|
$flag = (string)$v !== '0' && $v !== '' && $v !== null;
|
|
if ($flag) $rate[$num] = 1;
|
|
$isRisc = strtolower($m[1]) === 'ris';
|
|
}
|
|
}
|
|
$gest = ['anno' => $anno, 'stato' => ($row['stato'] ?? $row['stato_gestione'] ?? 'aperta'), 'rate' => $rate];
|
|
if ($isRisc) {
|
|
if (!$riscaldamento) $riscaldamento = $gest;
|
|
} else {
|
|
if (!$ordinaria) $ordinaria = $gest;
|
|
}
|
|
if ($ordinaria && $riscaldamento) break;
|
|
}
|
|
fclose($fh);
|
|
}
|
|
}
|
|
@unlink($tmp);
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
if ($hasMdbTools && is_file($generale) && is_readable($generale)) {
|
|
try {
|
|
$tmpS = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$tablesRaw = @shell_exec(sprintf('%s -1 %s 2>/dev/null', 'mdb-tables', escapeshellarg($generale))) ?: '';
|
|
$cand = null;
|
|
foreach (preg_split('/\r?\n/', trim($tablesRaw)) as $t) {
|
|
if (preg_match('/(straord|lavori|interventi)/i', $t)) {
|
|
$cand = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
if ($cand) {
|
|
$cmd = sprintf(
|
|
'%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null',
|
|
escapeshellarg($binExport),
|
|
escapeshellarg('%Y-%m-%d'),
|
|
escapeshellarg('|'),
|
|
escapeshellarg('"'),
|
|
escapeshellarg($generale),
|
|
escapeshellarg($cand),
|
|
escapeshellarg($tmpS)
|
|
);
|
|
@shell_exec($cmd);
|
|
if (@filesize($tmpS) > 0) {
|
|
$fh = fopen($tmpS, 'r');
|
|
$headers = fgetcsv($fh, 0, '|');
|
|
$headers = $headers ? array_map(fn($h) => strtolower(trim((string)$h)), $headers) : [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if (!$headers) break;
|
|
if ($cols === [null]) continue;
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
$dataInizio = $row['data'] ?? ($row['data_inizio'] ?? null);
|
|
$yr = null;
|
|
if ($dataInizio && preg_match('/^(\d{4})/', $dataInizio, $m)) $yr = (int)$m[1];
|
|
if ($yr && $yr != $anno) continue;
|
|
$descr = $row['descrizione'] ?? ($row['lavoro'] ?? ($row['oggetto'] ?? 'Straordinaria'));
|
|
$rateTot = (int)($row['rate_totali'] ?? ($row['num_rate'] ?? 0));
|
|
$rateEmesse = (int)($row['rate_emesse'] ?? ($row['rate_emessa'] ?? 0));
|
|
$straord[] = ['id' => $row['id'] ?? ($row['codice'] ?? null), 'descrizione' => $descr, 'data_inizio' => $dataInizio, 'data_fine' => $row['data_fine'] ?? null, 'rate_totali' => $rateTot, 'rate_emesse' => $rateEmesse];
|
|
if (count($straord) >= 50) break;
|
|
}
|
|
fclose($fh);
|
|
}
|
|
@unlink($tmpS);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
$meta = ['path_singolo_anno' => (is_file($singoloAnno) ? $singoloAnno : null), 'path_generale' => (is_file($generale) ? $generale : null), 'folder' => $folder, 'period' => $period];
|
|
return [
|
|
'ok' => true,
|
|
'anno' => $anno,
|
|
'ordinaria' => $ordinaria,
|
|
'riscaldamento' => $riscaldamento,
|
|
'straordinarie' => array_map(function ($s) {
|
|
$s['periodicita'] = $s['periodicita'] ?? null;
|
|
if (isset($s['data_inizio']) && preg_match('/^(\d{4})-(\d{2})/', $s['data_inizio'], $m)) {
|
|
$s['anno_inizio'] = (int)$m[1];
|
|
$s['mese_inizio'] = (int)$m[2];
|
|
}
|
|
$s['codice'] = $s['id'] ?? null;
|
|
return $s;
|
|
}, $straord),
|
|
'meta' => $meta,
|
|
];
|
|
}
|
|
|
|
public function unitaYear(string $legacy, $annoOrFolder, int $limit = 20): array
|
|
{
|
|
$base = UserSetting::get('gescon.source_path', '/mnt/gescon-archives/gescon');
|
|
$resolve = $this->resolveAnnoFolder($legacy, $annoOrFolder);
|
|
$folder = $resolve['folder'] ?? (is_numeric($annoOrFolder) ? str_pad((string)intval($annoOrFolder), 4, '0', STR_PAD_LEFT) : (string)$annoOrFolder);
|
|
$anno = $resolve['anno'] ?? (is_numeric($annoOrFolder) && (int)$annoOrFolder >= 1900 ? (int)$annoOrFolder : null);
|
|
$period = $resolve['period'] ?? null;
|
|
$dir = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy . DIRECTORY_SEPARATOR . $folder;
|
|
$singoloAnno = $dir . DIRECTORY_SEPARATOR . 'singolo_anno.mdb';
|
|
$hasMdbTools = trim((string)@shell_exec('command -v mdb-export')) !== '' && trim((string)@shell_exec('command -v mdb-tables')) !== '';
|
|
if (!$hasMdbTools || !is_file($singoloAnno) || !is_readable($singoloAnno)) {
|
|
try {
|
|
$primaryConn = UserSetting::get('gescon.import_conn', 'gescon_import');
|
|
$connCandidates = array_values(array_unique([$primaryConn, 'gescon_import_00000000']));
|
|
foreach ($connCandidates as $conn) {
|
|
$candidates = ['condomin', 'condomini', 'cond', 'condo', 'unita', 'unita_immobili', 'unita_immobiliari', 'ac_condomin'];
|
|
$table = null;
|
|
foreach ($candidates as $t) {
|
|
if (Schema::connection($conn)->hasTable($t)) {
|
|
$table = $t;
|
|
break;
|
|
}
|
|
}
|
|
if ($table) {
|
|
$cols = Schema::connection($conn)->getColumnListing($table);
|
|
$prefer = ['cod_stabile', 'codice_stabile', 'codstab', 'cod_condominio', 'cod_cond', 'scala', 'interno', 'piano', 'cognome', 'nome', 'codice_fiscale', 'telefono', 'cellulare', 'email', 'pec', 'indirizzo_corrispondenza', 'millesimi_generali', 'millesimi_risc', 'millesimi_proprieta', 'millesimi_riscaldamento', 'millesimi_ascensore', 'proprietario', 'inquilino', 'note'];
|
|
$stableCol = null;
|
|
foreach ($cols as $c) {
|
|
$lc = strtolower($c);
|
|
if (in_array($lc, ['cod_stabile', 'codice_stabile', 'codstab', 'cod_condominio', 'codice_condominio'], true)) {
|
|
$stableCol = $c;
|
|
break;
|
|
}
|
|
}
|
|
$headers = array_values(array_unique(array_merge($prefer, $cols)));
|
|
$select = array_values(array_filter($headers, function ($c) use ($cols) {
|
|
return in_array($c, $cols, true);
|
|
}));
|
|
if (empty($select)) $select = $cols;
|
|
$select = array_slice($select, 0, 24);
|
|
$q = DB::connection($conn)->table($table)->select($select);
|
|
if ($stableCol) {
|
|
$q->where($stableCol, $legacy);
|
|
}
|
|
$rows = $q->limit(max(1, $limit))->get()->map(fn($r) => (array)$r)->toArray();
|
|
if (!empty($rows)) {
|
|
return ['ok' => true, 'legacy_code' => $legacy, 'anno' => $anno ?: null, 'headers' => $select, 'rows' => $rows, 'staging_connection' => $conn, 'staging_table' => $table];
|
|
}
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
return ['ok' => false, 'error' => 'Dati Unità non disponibili: singolo_anno.mdb non leggibile e staging assente'];
|
|
}
|
|
try {
|
|
$tablesRaw = @shell_exec(sprintf('%s -1 %s 2>/dev/null', 'mdb-tables', escapeshellarg($singoloAnno))) ?: '';
|
|
$cand = [];
|
|
foreach (preg_split('/\r?\n/', trim($tablesRaw)) as $t) {
|
|
$tt = trim($t);
|
|
if ($tt === '') continue;
|
|
if (preg_match('/^condomin$/i', $tt)) {
|
|
$cand = [$tt];
|
|
break;
|
|
}
|
|
if (preg_match('/condo|min|unita|unit/i', $tt)) $cand[] = $tt;
|
|
}
|
|
$table = $cand[0] ?? null;
|
|
if (!$table) return ['ok' => false, 'error' => 'Tabella condomin non trovata'];
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$bin = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($bin), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($singoloAnno), escapeshellarg($table), escapeshellarg($tmp));
|
|
@shell_exec($cmd);
|
|
if (!@filesize($tmp)) return ['ok' => false, 'error' => 'Nessun dato disponibile'];
|
|
$fh = fopen($tmp, 'r');
|
|
$headers = fgetcsv($fh, 0, '|') ?: [];
|
|
$headers = array_map(fn($h) => (string)$h, $headers);
|
|
$rows = [];
|
|
$count = 0;
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null]) continue;
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
$rows[] = $row;
|
|
$count++;
|
|
if ($count >= max(1, $limit)) break;
|
|
}
|
|
fclose($fh);
|
|
@unlink($tmp);
|
|
return ['ok' => true, 'legacy_code' => $legacy, 'anno' => $anno, 'headers' => $headers, 'rows' => $rows, 'meta' => ['folder' => $folder, 'period' => $period]];
|
|
} catch (\Throwable $e) {
|
|
return ['ok' => false, 'error' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
public function casse(string $legacy): array
|
|
{
|
|
$base = UserSetting::get('gescon.source_path', '/mnt/gescon-archives/gescon');
|
|
$generale = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy . DIRECTORY_SEPARATOR . 'generale_stabile.mdb';
|
|
$hasMdbTools = trim((string)@shell_exec('command -v mdb-export')) !== '';
|
|
$out = [];
|
|
if ($hasMdbTools && is_file($generale) && is_readable($generale)) {
|
|
try {
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$tablesRaw = @shell_exec(sprintf('%s -1 %s 2>/dev/null', 'mdb-tables', escapeshellarg($generale))) ?: '';
|
|
$cand = null;
|
|
foreach (preg_split('/\r?\n/', trim($tablesRaw)) as $t) {
|
|
if (preg_match('/(casse|banche|conti|conto)/i', $t)) {
|
|
$cand = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
if ($cand) {
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($generale), escapeshellarg($cand), escapeshellarg($tmp));
|
|
@shell_exec($cmd);
|
|
if (@filesize($tmp) > 0) {
|
|
$fh = fopen($tmp, 'r');
|
|
$headers = fgetcsv($fh, 0, '|');
|
|
$headers = $headers ? array_map(fn($h) => strtolower(trim((string)$h)), $headers) : [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if (!$headers) break;
|
|
if ($cols === [null]) continue;
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
$cod = trim((string)($row['codice'] ?? ($row['cod_cassa'] ?? ($row['cod'] ?? ''))));
|
|
if ($cod === '') continue;
|
|
$desc = $row['descrizione'] ?? ($row['des'] ?? ($row['cassa'] ?? ''));
|
|
$iban = $row['iban'] ?? null;
|
|
$abi = $row['abi'] ?? null;
|
|
$cab = $row['cab'] ?? null;
|
|
$out[$cod] = ['codice' => $cod, 'descrizione' => $desc, 'abi' => $abi, 'cab' => $cab, 'iban' => $iban];
|
|
}
|
|
fclose($fh);
|
|
}
|
|
@unlink($tmp);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
if (empty($out)) {
|
|
try {
|
|
$primaryConn = UserSetting::get('gescon.import_conn', 'gescon_import');
|
|
$connCandidates = array_values(array_unique([$primaryConn, 'gescon_import_00000000']));
|
|
foreach ($connCandidates as $conn) {
|
|
$table = null;
|
|
foreach (['Anag_casse', 'anag_casse', 'casse', 'banche'] as $t) {
|
|
if (Schema::connection($conn)->hasTable($t)) {
|
|
$table = $t;
|
|
break;
|
|
}
|
|
}
|
|
if ($table) {
|
|
$cols = Schema::connection($conn)->getColumnListing($table);
|
|
$colCode = null;
|
|
$colDesc = null;
|
|
$colIban = null;
|
|
$colAbi = null;
|
|
$colCab = null;
|
|
foreach ($cols as $c) {
|
|
$lc = strtolower($c);
|
|
if (in_array($lc, ['codice', 'cod_cassa', 'cod'], true)) {
|
|
$colCode = $c;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($cols as $c) {
|
|
$lc = strtolower($c);
|
|
if (in_array($lc, ['descrizione', 'des', 'cassa', 'banca'], true)) {
|
|
$colDesc = $c;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($cols as $c) {
|
|
if (strtolower($c) === 'iban') {
|
|
$colIban = $c;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($cols as $c) {
|
|
if (strtolower($c) === 'abi') {
|
|
$colAbi = $c;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($cols as $c) {
|
|
if (strtolower($c) === 'cab') {
|
|
$colCab = $c;
|
|
break;
|
|
}
|
|
}
|
|
$q = DB::connection($conn)->table($table);
|
|
if (Schema::connection($conn)->hasColumn($table, 'cod_stabile')) {
|
|
$q->where('cod_stabile', $legacy);
|
|
}
|
|
$rows = $q->limit(500)->get();
|
|
foreach ($rows as $r) {
|
|
$cod = trim((string)($r->{$colCode} ?? ''));
|
|
if ($cod === '') continue;
|
|
$out[$cod] = ['codice' => $cod, 'descrizione' => (string)($r->{$colDesc} ?? ''), 'abi' => $colAbi ? (string)($r->{$colAbi} ?? '') : null, 'cab' => $colCab ? (string)($r->{$colCab} ?? '') : null, 'iban' => $colIban ? (string)($r->{$colIban} ?? '') : null];
|
|
}
|
|
if (!empty($out)) break;
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
if (!isset($out['CON'])) {
|
|
$out['CON'] = ['codice' => 'CON', 'descrizione' => 'CASSA CONTANTI', 'abi' => null, 'cab' => null, 'iban' => null];
|
|
}
|
|
$rows = array_values($out);
|
|
usort($rows, fn($a, $b) => strnatcasecmp($a['codice'], $b['codice']));
|
|
return $rows;
|
|
}
|
|
|
|
public function sampleLegacy(?string $legacy, int $index = 0): array
|
|
{
|
|
try {
|
|
$hasMdb = trim((string)@shell_exec('command -v mdb-export')) !== '';
|
|
$mdbPath = UserSetting::get('gescon.mdb_stabili');
|
|
if (!$mdbPath || !@is_file($mdbPath) || !@is_readable($mdbPath)) {
|
|
$storageFallback = '/var/www/netgescon/storage/gescon/Stabili.mdb';
|
|
if (@is_file($storageFallback) && @is_readable($storageFallback)) {
|
|
$mdbPath = $storageFallback;
|
|
}
|
|
}
|
|
if ($hasMdb && $mdbPath && is_file($mdbPath)) {
|
|
$row = $this->sampleStabileFromMdb($mdbPath, $legacy, $index);
|
|
if (!empty($row)) {
|
|
$legacyKey = $row['legacy_key'] ?? null;
|
|
unset($row['legacy_key']);
|
|
return ['ok' => true, 'index' => $index, 'data' => $row, 'legacy_key' => $legacyKey];
|
|
}
|
|
}
|
|
$ds = MigrationDataset::where('key', 'stabili')->orderByDesc('updated_at')->first();
|
|
if ($ds) {
|
|
$rec = MigrationRecord::where('dataset_id', $ds->id)->when($legacy, function ($q) use ($legacy) {
|
|
$q->where('legacy_key', $legacy);
|
|
})->orderBy('id')->skip($index)->take(1)->first();
|
|
if ($rec) {
|
|
return ['ok' => true, 'index' => $index, 'data' => (array)($rec->data ?? []), 'legacy_key' => $rec->legacy_key];
|
|
}
|
|
}
|
|
return ['ok' => false, 'error' => 'Anteprima non disponibile: nessun dataset e MDB non accessibile', 'index' => $index];
|
|
} catch (\Throwable $e) {
|
|
return ['ok' => false, 'error' => 'Errore: ' . $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
public function sampleUnita(?string $legacy, int $index = 0): array
|
|
{
|
|
try {
|
|
$rows = [];
|
|
if ($legacy && Schema::connection('gescon_import')->hasTable('condomin')) {
|
|
$rows = DB::connection('gescon_import')->table('condomin')->when($legacy, function ($q) use ($legacy) {
|
|
$q->where('cod_stabile', $legacy);
|
|
})->select(['cod_stabile', 'cod_cond', 'scala', 'interno', 'cognome', 'nome', 'codice_fiscale', 'millesimi_generali', 'millesimi_risc'])->orderBy('cod_cond')->skip($index)->take(1)->get()->map(fn($r) => (array)$r)->toArray();
|
|
}
|
|
if (empty($rows)) {
|
|
$rows[] = ['cod_stabile' => $legacy, 'cod_cond' => 'U' . str_pad((string)$index, 4, '0', STR_PAD_LEFT), 'scala' => 'A', 'interno' => '1', 'cognome' => 'Rossi', 'nome' => 'Mario', 'codice_fiscale' => 'RSSMRA80A01H501Z', 'millesimi_generali' => 45.67, 'millesimi_risc' => 12.34];
|
|
}
|
|
return ['ok' => true, 'index' => $index, 'data' => $rows[0]];
|
|
} catch (\Throwable $e) {
|
|
return ['ok' => false, 'error' => $e->getMessage()];
|
|
}
|
|
}
|
|
|
|
public function sampleTabelle(?string $legacy, int $index = 0): array
|
|
{
|
|
return ['ok' => true, 'index' => $index, 'data' => ['cod_stabile' => $legacy, 'tabella' => 'Generali', 'voce' => 'Scala A (app1)', 'millesimi' => 45.6700, 'nord_x10' => null]];
|
|
}
|
|
|
|
public function sampleVoci(?string $legacy, int $index = 0): array
|
|
{
|
|
return ['ok' => true, 'index' => $index, 'data' => ['cod_stabile' => $legacy, 'cod_voce' => 'A' . str_pad((string)$index, 3, '0', STR_PAD_LEFT), 'descrizione' => 'Spese generali condominio', 'gruppo' => 'MANUT', 'tipo' => 'ordinaria']];
|
|
}
|
|
|
|
// Discovery helpers used by index/config views
|
|
public function scanStabiliFromMasterIndex(string $indexMdbPath, string $legacyBasePath): array
|
|
{
|
|
$binTables = trim((string)@shell_exec('command -v mdb-tables')) ?: '/usr/bin/mdb-tables';
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
if (!is_file($indexMdbPath) || !is_readable($indexMdbPath)) return [];
|
|
$tableGuess = null;
|
|
$tables = @shell_exec(sprintf('%s -1 %s 2>/dev/null', escapeshellarg($binTables), escapeshellarg($indexMdbPath))) ?: '';
|
|
if ($tables) {
|
|
foreach (preg_split('/\r?\n/', trim($tables)) as $t) {
|
|
if ($t === '') continue;
|
|
if (preg_match('/(cartelle|stabil|anni)/i', $t)) {
|
|
$tableGuess = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!$tableGuess) {
|
|
$lines = array_filter(preg_split('/\r?\n/', trim($tables)));
|
|
$tableGuess = $lines ? trim(array_values($lines)[0]) : null;
|
|
}
|
|
if (!$tableGuess) return [];
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($indexMdbPath), escapeshellarg($tableGuess), 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((string)$h)), $headers);
|
|
$byCodeYears = [];
|
|
$byCodeName = [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null]) continue;
|
|
$cols = array_map(fn($v) => is_string($v) ? trim($v) : $v, $cols);
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
if (!$row) continue;
|
|
$code = $row['nome_directory'] ?? $row['cod_stabile'] ?? $row['internet_cod_stab'] ?? $row['codice'] ?? null;
|
|
$denom = $row['denominazione'] ?? $row['fe_denominazione'] ?? null;
|
|
$anno = $row['anno'] ?? $row['year'] ?? null;
|
|
if (!$code) continue;
|
|
$code = (string)$code;
|
|
if (!isset($byCodeYears[$code])) $byCodeYears[$code] = [];
|
|
if ($anno && preg_match('/^\d{4}$/', (string)$anno)) {
|
|
$byCodeYears[$code][(string)$anno] = true;
|
|
}
|
|
if ($denom) $byCodeName[$code] = (string)$denom;
|
|
}
|
|
fclose($fh);
|
|
@unlink($tmp);
|
|
$items = [];
|
|
foreach ($byCodeYears as $code => $yearsSet) {
|
|
$den = $byCodeName[$code] ?? null;
|
|
$years = array_keys($yearsSet);
|
|
sort($years, SORT_STRING);
|
|
$items[] = ['legacy_code' => $code, 'denominazione' => $den, 'years_count' => count($years), 'years' => $years];
|
|
}
|
|
if (empty($items)) {
|
|
$items = $this->scanLegacyCodesFromDir($legacyBasePath);
|
|
$items = $this->enrichLegacyWithArchives($items, $legacyBasePath);
|
|
}
|
|
usort($items, fn($a, $b) => strnatcasecmp((string)($a['legacy_code'] ?? ''), (string)($b['legacy_code'] ?? '')));
|
|
return $items;
|
|
}
|
|
|
|
public function scanStabiliFromMdb(string $mdbPath): array
|
|
{
|
|
$binTables = trim((string)@shell_exec('command -v mdb-tables')) ?: '/usr/bin/mdb-tables';
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$tableGuess = 'Stabili';
|
|
$tables = @shell_exec(sprintf('%s -1 %s 2>/dev/null', escapeshellarg($binTables), escapeshellarg($mdbPath))) ?: '';
|
|
if ($tables) {
|
|
foreach (preg_split('/\r?\n/', trim($tables)) as $t) {
|
|
if ($t === '') continue;
|
|
if (preg_match('/stabil/i', $t)) {
|
|
$tableGuess = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($mdbPath), escapeshellarg($tableGuess), 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((string)$h)), $headers);
|
|
$items = [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null] || $cols === false) continue;
|
|
$cols = array_map(fn($v) => is_string($v) ? trim($v) : $v, $cols);
|
|
$countH = count($headers);
|
|
if (count($cols) < $countH) $cols = array_pad($cols, $countH, null);
|
|
if (count($cols) > $countH) $cols = array_slice($cols, 0, $countH);
|
|
$row = @array_combine($headers, $cols);
|
|
if (!$row) continue;
|
|
$legacyCode = $row['nome_directory'] ?? ($row['internet_cod_stab'] ?? ($row['cod_stabile'] ?? null));
|
|
$denom = $row['denominazione'] ?? ($row['fe_denominazione'] ?? null);
|
|
if ($legacyCode) {
|
|
$items[] = ['legacy_code' => trim((string)$legacyCode), 'denominazione' => $denom ? trim((string)$denom) : null];
|
|
}
|
|
}
|
|
fclose($fh);
|
|
@unlink($tmp);
|
|
$byCode = [];
|
|
foreach ($items as $it) {
|
|
if (!empty($it['legacy_code'])) $byCode[$it['legacy_code']] = $it;
|
|
}
|
|
ksort($byCode, SORT_NATURAL);
|
|
return array_values($byCode);
|
|
}
|
|
|
|
public function sampleStabileFromMdb(string $mdbPath, ?string $legacyCode, int $index = 0): array
|
|
{
|
|
$binTables = trim((string)@shell_exec('command -v mdb-tables')) ?: '/usr/bin/mdb-tables';
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$tableGuess = 'Stabili';
|
|
$tables = @shell_exec(sprintf('%s -1 %s 2>/dev/null', escapeshellarg($binTables), escapeshellarg($mdbPath))) ?: '';
|
|
if ($tables) {
|
|
foreach (preg_split('/\r?\n/', trim($tables)) as $t) {
|
|
if ($t === '') continue;
|
|
if (preg_match('/stabil/i', $t)) {
|
|
$tableGuess = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($mdbPath), escapeshellarg($tableGuess), 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((string)$h)), $headers);
|
|
$rowData = [];
|
|
$i = 0;
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null]) continue;
|
|
$cols = array_map(fn($v) => is_string($v) ? trim($v) : $v, $cols);
|
|
$countH = count($headers);
|
|
if (count($cols) < $countH) $cols = array_pad($cols, $countH, null);
|
|
if (count($cols) > $countH) $cols = array_slice($cols, 0, $countH);
|
|
$row = @array_combine($headers, $cols) ?: [];
|
|
$legacyKey = $row['nome_directory'] ?? ($row['internet_cod_stab'] ?? ($row['cod_stabile'] ?? null));
|
|
if ($legacyCode) {
|
|
if ((string)$legacyKey === (string)$legacyCode) {
|
|
$rowData = $row;
|
|
break;
|
|
}
|
|
} else {
|
|
if ($i++ >= $index) {
|
|
$rowData = $row;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fclose($fh);
|
|
@unlink($tmp);
|
|
if (empty($rowData)) return [];
|
|
$rowData['legacy_key'] = (string)($rowData['nome_directory'] ?? ($rowData['internet_cod_stab'] ?? ($rowData['cod_stabile'] ?? '')));
|
|
return $rowData;
|
|
}
|
|
|
|
public function scanLegacyCodesFromDir(string $basePath): array
|
|
{
|
|
$items = [];
|
|
if (!is_dir($basePath)) return $items;
|
|
try {
|
|
$dh = opendir($basePath);
|
|
if ($dh) {
|
|
while (($file = readdir($dh)) !== false) {
|
|
if ($file === '.' || $file === '..') continue;
|
|
$full = rtrim($basePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file;
|
|
if (!is_dir($full)) continue;
|
|
$code = null;
|
|
if (preg_match('/^(\d{2,5})/', $file, $m)) {
|
|
$code = $m[1];
|
|
} elseif (preg_match('/(\d{2,5})/', $file, $m)) {
|
|
$code = $m[1];
|
|
}
|
|
$hasGenerale = is_file($full . DIRECTORY_SEPARATOR . 'generale_stabile.mdb');
|
|
$hasYears = false;
|
|
if (is_dir($full)) {
|
|
try {
|
|
$sub = opendir($full);
|
|
if ($sub) {
|
|
while (($yf = readdir($sub)) !== false) {
|
|
if ($yf === '.' || $yf === '..') continue;
|
|
if (!preg_match('/^\d{4}$/', $yf)) continue;
|
|
$ya = $full . DIRECTORY_SEPARATOR . $yf . DIRECTORY_SEPARATOR . 'singolo_anno.mdb';
|
|
if (is_file($ya)) {
|
|
$hasYears = true;
|
|
break;
|
|
}
|
|
}
|
|
closedir($sub);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
if ($code || $hasGenerale || $hasYears) {
|
|
$items[] = ['legacy_code' => $code ?: $file, 'denominazione' => null];
|
|
}
|
|
}
|
|
closedir($dh);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
$byCode = [];
|
|
foreach ($items as $it) {
|
|
$c = (string)($it['legacy_code'] ?? '');
|
|
if ($c !== '') {
|
|
$byCode[$c] = $it;
|
|
}
|
|
}
|
|
uksort($byCode, 'strnatcasecmp');
|
|
return array_values($byCode);
|
|
}
|
|
|
|
public function enrichLegacyWithArchives(array $items, string $basePath): array
|
|
{
|
|
$enriched = [];
|
|
foreach ($items as $it) {
|
|
$code = trim((string)($it['legacy_code'] ?? ''));
|
|
if ($code === '') {
|
|
$enriched[] = $it;
|
|
continue;
|
|
}
|
|
$dir = rtrim($basePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $code;
|
|
$hasGenerale = is_file($dir . DIRECTORY_SEPARATOR . 'generale_stabile.mdb');
|
|
$yearsCount = 0;
|
|
if (is_dir($dir)) {
|
|
try {
|
|
$dh = opendir($dir);
|
|
if ($dh) {
|
|
while (($f = readdir($dh)) !== false) {
|
|
if ($f === '.' || $f === '..') continue;
|
|
if (!preg_match('/^\d{4}$/', $f)) continue;
|
|
$sub = $dir . DIRECTORY_SEPARATOR . $f . DIRECTORY_SEPARATOR . 'singolo_anno.mdb';
|
|
if (is_file($sub)) $yearsCount++;
|
|
}
|
|
closedir($dh);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
$it['has_generale'] = $hasGenerale;
|
|
$it['years_count'] = $yearsCount;
|
|
$enriched[] = $it;
|
|
}
|
|
return $enriched;
|
|
}
|
|
|
|
private function resolveAnnoFolder(string $legacy, $annoOrFolder): array
|
|
{
|
|
$base = UserSetting::get('gescon.source_path', '/mnt/gescon-archives/gescon');
|
|
$legacyDir = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $legacy;
|
|
$folder = null;
|
|
$anno = null;
|
|
// If provided a string like '0001' or '2024'
|
|
if (is_string($annoOrFolder)) {
|
|
$cand = trim($annoOrFolder);
|
|
if ($cand !== '') {
|
|
if (is_dir($legacyDir . DIRECTORY_SEPARATOR . $cand) && is_file($legacyDir . DIRECTORY_SEPARATOR . $cand . DIRECTORY_SEPARATOR . 'singolo_anno.mdb')) {
|
|
$folder = $cand;
|
|
} elseif (ctype_digit($cand) && strlen($cand) <= 4) {
|
|
$pad = str_pad($cand, 4, '0', STR_PAD_LEFT);
|
|
if (is_dir($legacyDir . DIRECTORY_SEPARATOR . $pad) && is_file($legacyDir . DIRECTORY_SEPARATOR . $pad . DIRECTORY_SEPARATOR . 'singolo_anno.mdb')) {
|
|
$folder = $pad;
|
|
}
|
|
}
|
|
if (ctype_digit($cand) && strlen($cand) === 4 && (int)$cand >= 1900) {
|
|
$anno = (int)$cand;
|
|
}
|
|
}
|
|
}
|
|
// If provided a numeric like 1 or 2024
|
|
if ($folder === null && is_numeric($annoOrFolder)) {
|
|
$n = (int)$annoOrFolder;
|
|
if ($n >= 1900) {
|
|
$yr = (string)$n;
|
|
if (is_dir($legacyDir . DIRECTORY_SEPARATOR . $yr) && is_file($legacyDir . DIRECTORY_SEPARATOR . $yr . DIRECTORY_SEPARATOR . 'singolo_anno.mdb')) {
|
|
$folder = $yr;
|
|
$anno = $n;
|
|
}
|
|
}
|
|
if ($folder === null) {
|
|
$pad = str_pad((string)$n, 4, '0', STR_PAD_LEFT);
|
|
if (is_dir($legacyDir . DIRECTORY_SEPARATOR . $pad) && is_file($legacyDir . DIRECTORY_SEPARATOR . $pad . DIRECTORY_SEPARATOR . 'singolo_anno.mdb')) {
|
|
$folder = $pad;
|
|
}
|
|
}
|
|
}
|
|
// If still unknown, pick first available folder containing singolo_anno.mdb
|
|
if ($folder === null && is_dir($legacyDir)) {
|
|
$cands = [];
|
|
foreach (scandir($legacyDir) as $f) {
|
|
if ($f === '.' || $f === '..') continue;
|
|
$p = $legacyDir . DIRECTORY_SEPARATOR . $f . DIRECTORY_SEPARATOR . 'singolo_anno.mdb';
|
|
if (is_file($p)) $cands[] = $f;
|
|
}
|
|
if (!empty($cands)) {
|
|
natsort($cands);
|
|
$cands = array_values($cands);
|
|
$folder = end($cands);
|
|
}
|
|
}
|
|
// Try map folder->anno from generale_stabile.mdb: table ANNI
|
|
$generale = $legacyDir . DIRECTORY_SEPARATOR . 'generale_stabile.mdb';
|
|
$hasMdbTools = trim((string)@shell_exec('command -v mdb-export')) !== '';
|
|
if ($hasMdbTools && is_file($generale) && is_readable($generale)) {
|
|
try {
|
|
$tablesRaw = @shell_exec(sprintf('%s -1 %s 2>/dev/null', 'mdb-tables', escapeshellarg($generale))) ?: '';
|
|
$anniTable = null;
|
|
foreach (preg_split('/\r?\n/', trim($tablesRaw)) as $t) {
|
|
if (preg_match('/^anni$/i', trim($t))) {
|
|
$anniTable = trim($t);
|
|
break;
|
|
}
|
|
}
|
|
if ($anniTable) {
|
|
$tmp = tempnam(sys_get_temp_dir(), 'mdbcsv_');
|
|
$binExport = trim((string)@shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$cmd = sprintf('%s -D %s -d %s -q %s -R "\\n" %s %s > %s 2>/dev/null', escapeshellarg($binExport), escapeshellarg('%Y-%m-%d'), escapeshellarg('|'), escapeshellarg('"'), escapeshellarg($generale), escapeshellarg($anniTable), escapeshellarg($tmp));
|
|
@shell_exec($cmd);
|
|
if (@filesize($tmp) > 0) {
|
|
$fh = fopen($tmp, 'r');
|
|
$headers = fgetcsv($fh, 0, '|');
|
|
$headers = $headers ? array_map(fn($h) => strtolower(trim((string)$h)), $headers) : [];
|
|
$rows = [];
|
|
while (($cols = fgetcsv($fh, 0, '|')) !== false) {
|
|
if ($cols === [null]) continue;
|
|
if (count($cols) < count($headers)) $cols = array_pad($cols, count($headers), null);
|
|
if (count($cols) > count($headers)) $cols = array_slice($cols, 0, count($headers));
|
|
$rows[] = @array_combine($headers, $cols) ?: [];
|
|
}
|
|
fclose($fh);
|
|
// Try to find mapping by folder code
|
|
$folderCols = ['nome_dir', 'cartella', 'id_cartella', 'dir', 'directory', 'idcart', 'id_dir', 'num', 'numero'];
|
|
$annoCols = ['anno_o', 'anno', 'year'];
|
|
$startCols = ['ordinarie_dal', 'data_inizio', 'inizio', 'dal', 'data_dal'];
|
|
$endCols = ['ordinarie_al', 'data_fine', 'fine', 'al', 'data_al'];
|
|
$riscStartCols = ['riscald_dal'];
|
|
$riscEndCols = ['riscald_al'];
|
|
$folderCol = null;
|
|
$annoCol = null;
|
|
$startCol = null;
|
|
$endCol = null;
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $folderCols, true)) {
|
|
$folderCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $annoCols, true)) {
|
|
$annoCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $startCols, true)) {
|
|
$startCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $endCols, true)) {
|
|
$endCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
$riscStartCol = null;
|
|
$riscEndCol = null;
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $riscStartCols, true)) {
|
|
$riscStartCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
foreach ($headers as $h) {
|
|
if (in_array($h, $riscEndCols, true)) {
|
|
$riscEndCol = $h;
|
|
break;
|
|
}
|
|
}
|
|
if ($folderCol || $annoCol) {
|
|
foreach ($rows as $r) {
|
|
$rFolder = isset($r[$folderCol]) ? trim((string)$r[$folderCol]) : null;
|
|
$rAnno = isset($r[$annoCol]) ? (int)preg_replace('/[^0-9]/', '', (string)$r[$annoCol]) : null;
|
|
// Normalize folder zero-padded
|
|
if ($rFolder !== null && ctype_digit($rFolder)) {
|
|
$rFolder = str_pad($rFolder, 4, '0', STR_PAD_LEFT);
|
|
}
|
|
$period = [
|
|
'ordinaria_dal' => $startCol ? ($r[$startCol] ?? null) : null,
|
|
'ordinaria_al' => $endCol ? ($r[$endCol] ?? null) : null,
|
|
'riscald_dal' => $riscStartCol ? ($r[$riscStartCol] ?? null) : null,
|
|
'riscald_al' => $riscEndCol ? ($r[$riscEndCol] ?? null) : null,
|
|
];
|
|
// If a folder is already picked but ANNO is specified and maps to a different row, prefer the ANNO mapping
|
|
if ($anno && $rAnno && $rAnno === $anno && $rFolder) {
|
|
if ($folder !== $rFolder) {
|
|
$folder = $rFolder;
|
|
}
|
|
return ['folder' => $folder, 'anno' => $anno, 'period' => $period];
|
|
}
|
|
if ($folder && $rFolder && $rFolder === $folder) {
|
|
$anno = $rAnno ?: $anno;
|
|
return ['folder' => $folder, 'anno' => $anno, 'period' => $period];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@unlink($tmp);
|
|
}
|
|
} catch (\Throwable $e) {
|
|
}
|
|
}
|
|
return ['folder' => $folder, 'anno' => $anno];
|
|
}
|
|
}
|