260 lines
9.2 KiB
PHP
260 lines
9.2 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Scadenza;
|
|
use App\Models\Stabile;
|
|
use Illuminate\Console\Command;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class ImportScadenzeMdb extends Command
|
|
{
|
|
protected $signature = 'scadenze:import-mdb
|
|
{--mdb= : Percorso a parti_comuni.mdb}
|
|
{--stabile= : Codice stabile legacy per filtrare}
|
|
{--truncate : Svuota la tabella scadenze prima dell import}';
|
|
|
|
protected $description = 'Importa le scadenze legacy da parti_comuni.mdb evitando Descriz_lunga.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$mdb = $this->option('mdb') ?: '/mnt/gescon-archives/gescon/parti_comuni.mdb';
|
|
$filterStabile = trim((string) $this->option('stabile'));
|
|
|
|
if (! is_file($mdb)) {
|
|
$this->error('Specifica --mdb con path valido al file parti_comuni.mdb');
|
|
return self::FAILURE;
|
|
}
|
|
|
|
if ((bool) $this->option('truncate')) {
|
|
Scadenza::query()->truncate();
|
|
}
|
|
|
|
$rows = $this->mdbExportRows($mdb, 'Scadenze');
|
|
if ($rows === []) {
|
|
$this->warn('Nessuna riga letta dalla tabella Scadenze.');
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$imported = 0;
|
|
foreach ($rows as $row) {
|
|
$legacyId = $this->toInt($row['id_scadenza'] ?? null);
|
|
if ($legacyId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$codStabile = $this->normalizeString($row['cod_stabile'] ?? null);
|
|
if ($filterStabile !== '' && $codStabile !== $filterStabile) {
|
|
continue;
|
|
}
|
|
|
|
$natura = strtoupper($this->normalizeString($row['Natura'] ?? null) ?? '');
|
|
|
|
Scadenza::query()->updateOrCreate(
|
|
['legacy_id' => $legacyId],
|
|
[
|
|
'stabile_id' => $this->resolveStabileId($codStabile),
|
|
'codice_stabile_legacy' => $codStabile,
|
|
'descrizione_sintetica' => $this->normalizeString($row['Descriz_sintetica'] ?? null),
|
|
'data_scadenza' => $this->toDate($row['Dt_scadenza'] ?? null),
|
|
'ora_scadenza' => $this->toTime($row['ora_scadenza'] ?? null),
|
|
'natura' => $natura !== '' ? $natura : null,
|
|
'natura_label' => $this->resolveNaturaLabel($natura),
|
|
'gestione_tipo' => $this->resolveGestioneTipo($row['Gest_ors'] ?? null),
|
|
'num_assemblea' => $this->toInt($row['Num_assemblea'] ?? null) ?: null,
|
|
'numero_straordinaria' => $this->toInt($row['N_stra'] ?? null) ?: null,
|
|
'anno' => $this->normalizeString($row['Anno'] ?? null),
|
|
'rata' => $this->toInt($row['Rata'] ?? null) ?: null,
|
|
'fatto' => $this->normalizeString($row['Fatto'] ?? null),
|
|
'tipo_riga' => $this->normalizeString($row['tipo_riga'] ?? null),
|
|
'rif_f24' => $this->toInt($row['Rif_f24'] ?? null) ?: null,
|
|
'importo_f24' => $this->toDecimal($row['Importo_f24'] ?? null),
|
|
'richiede_pop_up' => $this->toBoolean($row['Richiede_pop_up'] ?? null),
|
|
'giorni_anticipo' => $this->toInt($row['gg_anticipo'] ?? null) ?: null,
|
|
'popup_dal' => $this->toDate($row['Pop_Up_dal'] ?? null),
|
|
'legacy_payload' => [
|
|
'legacy_id' => $legacyId,
|
|
'cod_stabile' => $codStabile,
|
|
'descriz_sintetica' => $this->normalizeString($row['Descriz_sintetica'] ?? null),
|
|
'gest_ors' => $this->normalizeString($row['Gest_ors'] ?? null),
|
|
'natura' => $natura,
|
|
'tipo_riga' => $this->normalizeString($row['tipo_riga'] ?? null),
|
|
'num_assemblea' => $this->toInt($row['Num_assemblea'] ?? null) ?: null,
|
|
'numero_straordinaria'=> $this->toInt($row['N_stra'] ?? null) ?: null,
|
|
'anno' => $this->normalizeString($row['Anno'] ?? null),
|
|
'rata' => $this->toInt($row['Rata'] ?? null) ?: null,
|
|
],
|
|
]
|
|
);
|
|
|
|
$imported++;
|
|
}
|
|
|
|
$this->info('Scadenze importate/aggiornate: ' . $imported);
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function mdbExportRows(string $mdb, string $table): array
|
|
{
|
|
$bin = trim((string) shell_exec('command -v mdb-export')) ?: '/usr/bin/mdb-export';
|
|
$process = new Process([$bin, $mdb, $table]);
|
|
$process->setTimeout(120);
|
|
$process->run();
|
|
|
|
if (! $process->isSuccessful()) {
|
|
$this->warn("mdb-export fallito per {$table}: " . $process->getErrorOutput());
|
|
return [];
|
|
}
|
|
|
|
$csv = $process->getOutput();
|
|
if ($csv === '') {
|
|
return [];
|
|
}
|
|
|
|
$fh = fopen('php://temp', 'r+');
|
|
fwrite($fh, $csv);
|
|
rewind($fh);
|
|
|
|
$header = fgetcsv($fh);
|
|
if (! is_array($header)) {
|
|
return [];
|
|
}
|
|
|
|
$header = array_map(static fn($value) => trim((string) $value), $header);
|
|
$rows = [];
|
|
|
|
while (($row = fgetcsv($fh)) !== false) {
|
|
if ($row === [null]) {
|
|
continue;
|
|
}
|
|
|
|
$assoc = [];
|
|
foreach ($header as $index => $column) {
|
|
$assoc[$column] = $row[$index] ?? null;
|
|
}
|
|
|
|
$rows[] = $assoc;
|
|
}
|
|
|
|
fclose($fh);
|
|
|
|
return $rows;
|
|
}
|
|
|
|
private function resolveStabileId(?string $cod): ?int
|
|
{
|
|
if ($cod === null || $cod === '') {
|
|
return null;
|
|
}
|
|
|
|
$query = Stabile::query();
|
|
$variants = array_values(array_unique(array_filter([
|
|
$cod,
|
|
ltrim($cod, '0'),
|
|
str_pad(ltrim($cod, '0') !== '' ? ltrim($cod, '0') : $cod, 4, '0', STR_PAD_LEFT),
|
|
], static fn($value) => $value !== '')));
|
|
|
|
foreach ($variants as $variant) {
|
|
$id = $query->clone()->where('codice_stabile', $variant)->value('id');
|
|
if ($id) {
|
|
return (int) $id;
|
|
}
|
|
|
|
$id = $query->clone()->where('cod_stabile', $variant)->value('id');
|
|
if ($id) {
|
|
return (int) $id;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function normalizeString(mixed $value): ?string
|
|
{
|
|
$normalized = trim((string) $value);
|
|
return $normalized !== '' ? $normalized : null;
|
|
}
|
|
|
|
private function toInt(mixed $value): int
|
|
{
|
|
$normalized = $this->normalizeString($value);
|
|
return $normalized !== null ? (int) preg_replace('/[^0-9-]+/', '', $normalized) : 0;
|
|
}
|
|
|
|
private function toDecimal(mixed $value): ?float
|
|
{
|
|
$normalized = $this->normalizeString($value);
|
|
if ($normalized === null) {
|
|
return null;
|
|
}
|
|
|
|
if (str_contains($normalized, ',') && str_contains($normalized, '.')) {
|
|
$normalized = str_replace('.', '', $normalized);
|
|
$normalized = str_replace(',', '.', $normalized);
|
|
} elseif (str_contains($normalized, ',')) {
|
|
$normalized = str_replace(',', '.', $normalized);
|
|
}
|
|
|
|
return is_numeric($normalized) ? round((float) $normalized, 2) : null;
|
|
}
|
|
|
|
private function toBoolean(mixed $value): bool
|
|
{
|
|
$normalized = strtolower($this->normalizeString($value) ?? '');
|
|
return in_array($normalized, ['1', 'si', 'sì', 'true', 'yes', 'y'], true);
|
|
}
|
|
|
|
private function toDate(mixed $value): ?string
|
|
{
|
|
$normalized = $this->normalizeString($value);
|
|
if ($normalized === null) {
|
|
return null;
|
|
}
|
|
|
|
$formats = ['m/d/y H:i:s', 'm/d/Y H:i:s', 'm/d/y', 'm/d/Y'];
|
|
foreach ($formats as $format) {
|
|
$date = \DateTimeImmutable::createFromFormat($format, $normalized);
|
|
if ($date instanceof \DateTimeImmutable) {
|
|
return $date->format('Y-m-d');
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function toTime(mixed $value): ?string
|
|
{
|
|
$normalized = $this->normalizeString($value);
|
|
if ($normalized === null) {
|
|
return null;
|
|
}
|
|
|
|
$formats = ['H:i:s', 'H:i'];
|
|
foreach ($formats as $format) {
|
|
$date = \DateTimeImmutable::createFromFormat($format, $normalized);
|
|
if ($date instanceof \DateTimeImmutable) {
|
|
return $date->format('H:i:s');
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function resolveGestioneTipo(mixed $value): ?string
|
|
{
|
|
return match (strtoupper($this->normalizeString($value) ?? '')) {
|
|
'O' => 'ordinaria',
|
|
'S' => 'straordinaria',
|
|
default => $this->normalizeString($value),
|
|
};
|
|
}
|
|
|
|
private function resolveNaturaLabel(?string $value): ?string
|
|
{
|
|
return match (strtoupper($value ?? '')) {
|
|
'F' => 'Versamento F24',
|
|
'R' => 'Rata / emissione rata',
|
|
default => $this->normalizeString($value),
|
|
};
|
|
}
|
|
} |