508 lines
22 KiB
PHP
508 lines
22 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Persona;
|
|
use App\Models\PersonaUnitaRelazione;
|
|
use App\Models\Stabile;
|
|
use App\Models\UnitaImmobiliare;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class GesconReconstructMirror0021Command extends Command
|
|
{
|
|
protected $signature = 'gescon:reconstruct-mirror-0021 {--stabile=0021 : Codice dello stabile pilot}';
|
|
|
|
protected $description = 'Ricostruisce Anagrafica Unica, Unità Immobiliari e Relazioni Temporali dal condomin_mirror 0021 con gestione rigorosa CF e subentri';
|
|
|
|
private array $resolvedPersonasByStableId = [];
|
|
|
|
public function handle(): int
|
|
{
|
|
$stabileCode = (string) $this->option('stabile');
|
|
$this->info("=== Ricostruzione Anagrafica e Unità dal condomin_mirror Stabile {$stabileCode} ===");
|
|
|
|
// 1. Estrazione CF Stabile raw da Stabili.mdb (Nessun fallback 80000000021)
|
|
$rawStabileCf = $this->getRawStabileCodiceFiscale($stabileCode);
|
|
if (! $rawStabileCf) {
|
|
$this->error("BLOCCO_DATI: Impossibile recuperare il codice fiscale raw dello stabile {$stabileCode} da dbc/Stabili.mdb.");
|
|
return 1;
|
|
}
|
|
|
|
// Verifica o creazione dello Stabile con CF raw estratto
|
|
$stabile = Stabile::where('codice_stabile', $stabileCode)->first();
|
|
if (! $stabile) {
|
|
$adminId = DB::table('amministratori')->value('id') ?? 1;
|
|
$stabile = Stabile::create([
|
|
'codice_stabile' => $stabileCode,
|
|
'denominazione' => 'SUPERCONDOMINIO MILIZIE 3',
|
|
'indirizzo' => 'Viale delle Milizie 3',
|
|
'cap' => '00192',
|
|
'citta' => 'Roma',
|
|
'provincia' => 'RM',
|
|
'codice_fiscale' => $rawStabileCf,
|
|
'amministratore_id' => $adminId,
|
|
'attivo' => true,
|
|
]);
|
|
} else {
|
|
if ($stabile->codice_fiscale !== $rawStabileCf) {
|
|
$stabile->update(['codice_fiscale' => $rawStabileCf]);
|
|
}
|
|
}
|
|
|
|
$this->info("Stabile di riferimento: ID {$stabile->id} | CF Raw Stabile: {$stabile->codice_fiscale}");
|
|
|
|
// 2. Lettura Staging Lossless condomin_mirror
|
|
if (! Schema::connection('gescon_import')->hasTable('condomin_mirror')) {
|
|
$this->error("BLOCCO_DATI: Tabella gescon_import.condomin_mirror non esistente.");
|
|
return 1;
|
|
}
|
|
|
|
$mirrorRows = DB::connection('gescon_import')
|
|
->table('condomin_mirror')
|
|
->where('cod_stabile', $stabileCode)
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
$totalMirrorRows = $mirrorRows->count();
|
|
if ($totalMirrorRows === 0) {
|
|
$this->error("BLOCCO_DATI: Nessuna riga presente in condomin_mirror per lo stabile {$stabileCode}.");
|
|
return 1;
|
|
}
|
|
$this->info("Righe totali da condomin_mirror: {$totalMirrorRows}");
|
|
|
|
// 3. Elaborazione e Ricostruzione
|
|
$unitaCreatedOrFound = 0;
|
|
$personeCreatedOrFound = 0;
|
|
$relazioniProprietariCount = 0;
|
|
$relazioniInquiliniCount = 0;
|
|
$processedMirrorRows = 0;
|
|
|
|
$unitMap = [];
|
|
|
|
foreach ($mirrorRows as $row) {
|
|
$scalaRaw = trim((string) ($row->scala ?? ''));
|
|
$intRaw = trim((string) ($row->interno ?? ''));
|
|
$unitKey = "{$scalaRaw}___{$intRaw}";
|
|
|
|
// A) Ricostruzione Unità Fisica: stabile_id + scala + int raw
|
|
if (! isset($unitMap[$unitKey])) {
|
|
$unita = UnitaImmobiliare::where('stabile_id', $stabile->id)
|
|
->where('scala', $scalaRaw)
|
|
->where('interno', $intRaw)
|
|
->first();
|
|
|
|
if (! $unita) {
|
|
$unitaCode = '0021-' . ($scalaRaw !== '' ? "{$scalaRaw}-" : '') . $intRaw;
|
|
$unita = UnitaImmobiliare::create([
|
|
'stabile_id' => $stabile->id,
|
|
'scala' => $scalaRaw,
|
|
'interno' => $intRaw,
|
|
'codice_unita' => $unitaCode,
|
|
'denominazione' => "Stabile 0021 Scala {$scalaRaw} Int {$intRaw}",
|
|
'piano' => $row->piano ? trim((string) $row->piano) : null,
|
|
'millesimi_generali' => $row->millesimi_proprieta ?: null,
|
|
'millesimi_proprieta' => $row->millesimi_proprieta ?: null,
|
|
'millesimi_riscaldamento' => $row->millesimi_riscaldamento ?: null,
|
|
'millesimi_ascensore' => $row->millesimi_ascensore ?: null,
|
|
'stato' => 'attiva',
|
|
]);
|
|
$unitaCreatedOrFound++;
|
|
} else {
|
|
$updates = [];
|
|
if (empty($unita->piano) && ! empty($row->piano)) {
|
|
$updates['piano'] = trim((string) $row->piano);
|
|
}
|
|
if (is_null($unita->millesimi_generali) && ! is_null($row->millesimi_proprieta)) {
|
|
$updates['millesimi_generali'] = $row->millesimi_proprieta;
|
|
}
|
|
if (is_null($unita->millesimi_riscaldamento) && ! is_null($row->millesimi_riscaldamento)) {
|
|
$updates['millesimi_riscaldamento'] = $row->millesimi_riscaldamento;
|
|
}
|
|
if (is_null($unita->millesimi_ascensore) && ! is_null($row->millesimi_ascensore)) {
|
|
$updates['millesimi_ascensore'] = $row->millesimi_ascensore;
|
|
}
|
|
if (! empty($updates)) {
|
|
$unita->update($updates);
|
|
}
|
|
$unitaCreatedOrFound++;
|
|
}
|
|
$unitMap[$unitKey] = $unita;
|
|
} else {
|
|
$unita = $unitMap[$unitKey];
|
|
}
|
|
|
|
// B) Ricostruzione Persona Proprietario / Intitolato
|
|
$personaProprietario = $this->resolveOrCreatePersona($row, false, $rawStabileCf);
|
|
if ($personaProprietario->wasRecentlyCreated) {
|
|
$personeCreatedOrFound++;
|
|
}
|
|
|
|
// C) Relazione Temporale Proprietario
|
|
$idCondStr = trim((string) $row->id_cond);
|
|
$codCondStr = trim((string) $row->cod_cond);
|
|
$sourceFile = (string) ($row->source_file ?? '');
|
|
$sourceYear = (string) ($row->source_year ?? '');
|
|
$sourceRow = (int) ($row->source_row ?? 0);
|
|
$provenanceHash = (string) ($row->provenance_hash ?? "mirror_{$row->id}");
|
|
|
|
$provenanceFull = "{$sourceFile}#row:{$sourceRow}|{$provenanceHash}";
|
|
|
|
$relProp = PersonaUnitaRelazione::where('unita_id', $unita->id)
|
|
->where('id_cond', $idCondStr)
|
|
->where('tipo_relazione', 'proprietario')
|
|
->first();
|
|
|
|
$subDalRaw = trim((string) ($row->subentrato_dal ?? ''));
|
|
$attFinoRaw = trim((string) ($row->attivo_fino_al ?? ''));
|
|
$subPrimaRaw = trim((string) ($row->subentro_prima_cera ?? ''));
|
|
$subAdessoRaw = trim((string) ($row->subentro_adesso_ce ?? ''));
|
|
|
|
$dataInizioParsed = $this->parseMirrorDate($subDalRaw) ?: '2000-01-01';
|
|
$dataFineParsed = $this->parseMirrorDate($attFinoRaw);
|
|
|
|
$isAttivo = true;
|
|
if ($attFinoRaw !== '' && $attFinoRaw !== '0' && $attFinoRaw !== '00/00/00' && $attFinoRaw !== '00/00/0000') {
|
|
$isAttivo = false;
|
|
}
|
|
|
|
if (! $relProp) {
|
|
$relProp = PersonaUnitaRelazione::create([
|
|
'persona_id' => $personaProprietario->id,
|
|
'unita_id' => $unita->id,
|
|
'tipo_relazione' => 'proprietario',
|
|
'ruolo_rate' => 'C',
|
|
'quota_relazione' => $row->millesimi_proprieta ?: 100.00,
|
|
'data_inizio' => $dataInizioParsed,
|
|
'data_fine' => $dataFineParsed,
|
|
'attivo' => $isAttivo,
|
|
'riceve_comunicazioni' => true,
|
|
'riceve_convocazioni' => true,
|
|
'vota_assemblea' => true,
|
|
'id_cond' => $idCondStr,
|
|
'cod_cond' => $codCondStr,
|
|
'provenance' => $provenanceFull,
|
|
'subentrato_dal' => $subDalRaw !== '' ? $subDalRaw : null,
|
|
'attivo_fino_al' => $attFinoRaw !== '' ? $attFinoRaw : null,
|
|
'subentro_prima_cera' => $subPrimaRaw !== '' ? $subPrimaRaw : null,
|
|
'subentro_adesso_ce' => $subAdessoRaw !== '' ? $subAdessoRaw : null,
|
|
'note_relazione' => "Gestione: {$sourceYear} | File: {$sourceFile} | Row: {$sourceRow}",
|
|
]);
|
|
$relazioniProprietariCount++;
|
|
} else {
|
|
$updatesRel = [];
|
|
if ($relProp->persona_id !== $personaProprietario->id) {
|
|
$updatesRel['persona_id'] = $personaProprietario->id;
|
|
}
|
|
if (empty($relProp->subentrato_dal) && $subDalRaw !== '') {
|
|
$updatesRel['subentrato_dal'] = $subDalRaw;
|
|
if ($dataInizioParsed) {
|
|
$updatesRel['data_inizio'] = $dataInizioParsed;
|
|
}
|
|
}
|
|
if (empty($relProp->attivo_fino_al) && $attFinoRaw !== '') {
|
|
$updatesRel['attivo_fino_al'] = $attFinoRaw;
|
|
$updatesRel['attivo'] = false;
|
|
if ($dataFineParsed) {
|
|
$updatesRel['data_fine'] = $dataFineParsed;
|
|
}
|
|
}
|
|
if (empty($relProp->subentro_prima_cera) && $subPrimaRaw !== '') {
|
|
$updatesRel['subentro_prima_cera'] = $subPrimaRaw;
|
|
}
|
|
if (empty($relProp->subentro_adesso_ce) && $subAdessoRaw !== '') {
|
|
$updatesRel['subentro_adesso_ce'] = $subAdessoRaw;
|
|
}
|
|
if (! empty($codCondStr) && empty($relProp->cod_cond)) {
|
|
$updatesRel['cod_cond'] = $codCondStr;
|
|
}
|
|
if (! empty($updatesRel)) {
|
|
$relProp->update($updatesRel);
|
|
}
|
|
}
|
|
|
|
// D) Inquilino (se presente nel mirror row o nel payload)
|
|
$payload = json_decode($row->legacy_payload ?? '{}', true);
|
|
$inquilinoRaw = trim((string) ($row->inquilino ?: ($payload['inquil_nome'] ?? '')));
|
|
if ($inquilinoRaw !== '' && $inquilinoRaw !== '0') {
|
|
$personaInquilino = $this->resolveOrCreatePersona($row, true, $rawStabileCf);
|
|
if ($personaInquilino->wasRecentlyCreated) {
|
|
$personeCreatedOrFound++;
|
|
}
|
|
|
|
$inqContrattoDal = trim((string) ($payload['Inquil_contratto_dal'] ?? $payload['inquil_dal'] ?? $row->inquil_dal ?? ''));
|
|
$inqDataInizioParsed = $this->parseMirrorDate($inqContrattoDal) ?: $dataInizioParsed;
|
|
|
|
$inqIdCond = "{$idCondStr}_inq";
|
|
|
|
// Ogni diversa persona inquilina o diversa occupazione mantenuta come relazione temporale
|
|
$relInq = PersonaUnitaRelazione::where('unita_id', $unita->id)
|
|
->where('persona_id', $personaInquilino->id)
|
|
->where('tipo_relazione', 'inquilino')
|
|
->first();
|
|
|
|
if (! $relInq) {
|
|
$relInq = PersonaUnitaRelazione::create([
|
|
'persona_id' => $personaInquilino->id,
|
|
'unita_id' => $unita->id,
|
|
'tipo_relazione' => 'inquilino',
|
|
'ruolo_rate' => 'I',
|
|
'quota_relazione' => null,
|
|
'data_inizio' => $inqDataInizioParsed,
|
|
'data_fine' => $dataFineParsed,
|
|
'attivo' => $isAttivo,
|
|
'riceve_comunicazioni' => true,
|
|
'riceve_convocazioni' => false,
|
|
'vota_assemblea' => false,
|
|
'id_cond' => $inqIdCond,
|
|
'cod_cond' => $codCondStr,
|
|
'provenance' => $provenanceFull,
|
|
'subentrato_dal' => $inqContrattoDal !== '' ? $inqContrattoDal : ($subDalRaw !== '' ? $subDalRaw : null),
|
|
'attivo_fino_al' => $attFinoRaw !== '' ? $attFinoRaw : null,
|
|
'subentro_prima_cera' => $subPrimaRaw !== '' ? $subPrimaRaw : null,
|
|
'subentro_adesso_ce' => $subAdessoRaw !== '' ? $subAdessoRaw : null,
|
|
'note_relazione' => "Inquilino Gestione: {$sourceYear} | Contratto Dal Raw: {$inqContrattoDal} | File: {$sourceFile}",
|
|
]);
|
|
$relazioniInquiliniCount++;
|
|
}
|
|
}
|
|
|
|
$processedMirrorRows++;
|
|
}
|
|
|
|
// 4. Stampa Quadratura Completa
|
|
$distinctPhysicalUnits = UnitaImmobiliare::where('stabile_id', $stabile->id)->count();
|
|
|
|
$int11Relations = PersonaUnitaRelazione::whereHas('unitaImmobiliare', function ($q) use ($stabile) {
|
|
$q->where('stabile_id', $stabile->id)
|
|
->where('scala', 'A')
|
|
->where('interno', '11');
|
|
})->get();
|
|
|
|
$this->info('=== ESITO QUADRATURA 0021 ===');
|
|
$this->info("RIGHE_MIRROR_TOTALI: {$totalMirrorRows}");
|
|
$this->info("RIGHE_ELABORATE: {$processedMirrorRows}");
|
|
$this->info("UNITA_FISICHE_DISTINTE: {$distinctPhysicalUnits}");
|
|
$this->info("RELAZIONI_PROPRIETARI_TOTALI: {$relazioniProprietariCount}");
|
|
$this->info("RELAZIONI_INQUILINI_TOTALI: {$relazioniInquiliniCount}");
|
|
$this->info('VERIFICA_SCALA_A_INT_11: ' . $int11Relations->count() . ' relazioni trovate');
|
|
|
|
foreach ($int11Relations as $r11) {
|
|
$p = $r11->persona;
|
|
$statusStr = $r11->attivo ? 'ATTIVA' : 'INATTIVA (Uscente)';
|
|
$cfStr = $p->codice_fiscale ? "CF: {$p->codice_fiscale}" : 'CF: NULL (Candidato)';
|
|
$this->line(" -> Persona: {$p->nome_completo} | {$cfStr} | Relazione: {$r11->tipo_relazione} | Status: {$statusStr} | sub_dal: {$r11->subentrato_dal} | att_fino: {$r11->attivo_fino_al}");
|
|
}
|
|
|
|
if ($processedMirrorRows === $totalMirrorRows) {
|
|
$this->info("QUADRATURA_ESITO: PERFETTA (100% delle {$totalMirrorRows} righe specchiate)");
|
|
} else {
|
|
$this->error("QUADRATURA_ESITO: DISCREPANZA ({$processedMirrorRows}/{$totalMirrorRows} righe)");
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Risolve o crea una Persona seguendo rigorosamente le regole CF:
|
|
* - CF proprietario = Cond_cod_fisc; CF inquilino = Inquil_cod_fisc;
|
|
* - Valida ogni CF raw. Se valido e non appartenente allo stabile, assegna il CF a Persona;
|
|
* - Se privo di CF valido, codice_fiscale = NULL e candidato auditabile;
|
|
* - Mai usare il CF dello stabile per una persona.
|
|
*/
|
|
private function resolveOrCreatePersona(object $row, bool $isTenant, string $stabileCf): Persona
|
|
{
|
|
$payload = json_decode($row->legacy_payload ?? '{}', true);
|
|
|
|
if ($isTenant) {
|
|
$rawName = trim((string) ($row->inquilino ?: ($payload['inquil_nome'] ?? '')));
|
|
$rawCf = trim((string) ($payload['Inquil_cod_fisc'] ?? ''));
|
|
} else {
|
|
$rawName = trim((string) ($row->nom_cond ?? ''));
|
|
$rawCf = trim((string) ($payload['Cond_cod_fisc'] ?? $row->codice_fiscale ?? ''));
|
|
}
|
|
|
|
$cleanCf = strtoupper($rawCf);
|
|
|
|
// 1. Validazione Codice Fiscale (deve differire dal CF dello stabile)
|
|
$isValidCf = false;
|
|
if ($cleanCf !== '' && $cleanCf !== '0' && $cleanCf !== strtoupper($stabileCf)) {
|
|
if (preg_match('/^[A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z]$/', $cleanCf) || preg_match('/^\d{11}$/', $cleanCf)) {
|
|
$isValidCf = true;
|
|
}
|
|
}
|
|
|
|
$idCondStr = trim((string) ($row->id_cond ?? ''));
|
|
$stableKey = $isTenant ? "0021_ID_{$idCondStr}_INQ_" . md5($rawName) : "0021_ID_{$idCondStr}";
|
|
|
|
if ($isValidCf) {
|
|
$existingByCf = Persona::where('codice_fiscale', $cleanCf)->first();
|
|
if ($existingByCf) {
|
|
return $existingByCf;
|
|
}
|
|
|
|
$existingByStable = Persona::where('note', 'LIKE', "%[MDB_STABLE_ID: {$stableKey}]%")->first();
|
|
if ($existingByStable) {
|
|
if (empty($existingByStable->codice_fiscale)) {
|
|
$existingByStable->update(['codice_fiscale' => $cleanCf]);
|
|
}
|
|
$this->resolvedPersonasByStableId[$stableKey] = $existingByStable;
|
|
return $existingByStable;
|
|
}
|
|
} else {
|
|
if (isset($this->resolvedPersonasByStableId[$stableKey])) {
|
|
return $this->resolvedPersonasByStableId[$stableKey];
|
|
}
|
|
|
|
$existingByStable = Persona::where('note', 'LIKE', "%[MDB_STABLE_ID: {$stableKey}]%")->first();
|
|
if ($existingByStable) {
|
|
$this->resolvedPersonasByStableId[$stableKey] = $existingByStable;
|
|
return $existingByStable;
|
|
}
|
|
}
|
|
|
|
// 3. Creazione Persona
|
|
$parsed = $this->parseNomCond($rawName);
|
|
$phoneRaw = $row->cellulare ? trim((string) $row->cellulare) : ($row->telefono ? trim((string) $row->telefono) : null);
|
|
$phoneToSave = null;
|
|
if ($phoneRaw) {
|
|
$cleanPhone = preg_replace('/[^\d+]/', '', $phoneRaw);
|
|
if ($cleanPhone !== '' && ! Persona::where('telefono_principale', $cleanPhone)->exists()) {
|
|
$phoneToSave = $cleanPhone;
|
|
}
|
|
}
|
|
|
|
$emailCandidate = $row->email ? trim((string) $row->email) : null;
|
|
$pecCandidate = $row->pec ? trim((string) $row->pec) : null;
|
|
|
|
$note = $isValidCf
|
|
? "[MDB_0021] CF Validato da condomin_mirror [MDB_STABLE_ID: {$stableKey}]"
|
|
: "[CANDIDATO_AUDITABILE] Stabile 0021 [MDB_STABLE_ID: {$stableKey}]";
|
|
|
|
$persona = Persona::create([
|
|
'codice_interno' => Persona::generaCodiceUnivoco(),
|
|
'tipologia' => $parsed['tipologia'],
|
|
'cognome' => $parsed['cognome'],
|
|
'nome' => $parsed['nome'],
|
|
'ragione_sociale' => $parsed['ragione_sociale'],
|
|
'codice_fiscale' => $isValidCf ? $cleanCf : null,
|
|
'telefono_principale' => $phoneToSave,
|
|
'email_principale' => $emailCandidate,
|
|
'email_pec' => $pecCandidate,
|
|
'residenza_via' => $row->indirizzo_corrispondenza ? trim((string) $row->indirizzo_corrispondenza) : null,
|
|
'note' => $note,
|
|
'attivo' => true,
|
|
]);
|
|
|
|
$this->resolvedPersonasByStableId[$stableKey] = $persona;
|
|
|
|
return $persona;
|
|
}
|
|
|
|
/**
|
|
* Estrazione CF dello stabile direttamente da dbc/Stabili.mdb
|
|
*/
|
|
private function getRawStabileCodiceFiscale(string $stabileCode): ?string
|
|
{
|
|
// 1. Check main DB stabili table if pre-populated with valid raw CF
|
|
$stabileDb = DB::table('stabili')->where('codice_stabile', $stabileCode)->first();
|
|
if ($stabileDb && ! empty($stabileDb->codice_fiscale) && $stabileDb->codice_fiscale !== '80000000021') {
|
|
return trim((string) $stabileDb->codice_fiscale);
|
|
}
|
|
|
|
// 2. Read from /mnt/gescon-archives/gescon/dbc/Stabili.mdb
|
|
$mdbPath = '/mnt/gescon-archives/gescon/dbc/Stabili.mdb';
|
|
if (file_exists($mdbPath)) {
|
|
$output = shell_exec('mdb-export ' . escapeshellarg($mdbPath) . ' Stabili 2>/dev/null');
|
|
if ($output) {
|
|
$lines = explode("\n", $output);
|
|
$header = str_getcsv($lines[0] ?? '');
|
|
$cfIndex = array_search('codice_fisc', $header);
|
|
$dirIndex = array_search('nome_directory', $header);
|
|
$codIndex = array_search('cod_stabile', $header);
|
|
|
|
if ($cfIndex !== false) {
|
|
for ($i = 1; $i < count($lines); $i++) {
|
|
$row = str_getcsv($lines[$i]);
|
|
$dir = $row[$dirIndex] ?? '';
|
|
$cod = $row[$codIndex] ?? '';
|
|
if ($dir === $stabileCode || $cod === $stabileCode) {
|
|
$cf = trim((string) ($row[$cfIndex] ?? ''));
|
|
if (! empty($cf)) {
|
|
return $cf;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function parseNomCond(string $nomCond): array
|
|
{
|
|
$nomCond = trim($nomCond);
|
|
$upper = mb_strtoupper($nomCond);
|
|
$companyKeywords = ['ATER', 'SRL', 'S.R.L.', 'SPA', 'S.P.A.', 'SAS', 'S.A.S.', 'SNC', 'S.N.C.', 'CONDOMINI', 'EREDI', 'C/O', 'SOC.', 'SOCIETA', 'SOCIETÀ', 'DOMUS'];
|
|
|
|
foreach ($companyKeywords as $kw) {
|
|
if (str_contains($upper, $kw)) {
|
|
return [
|
|
'tipologia' => 'giuridica',
|
|
'cognome' => $nomCond,
|
|
'nome' => '',
|
|
'ragione_sociale' => $nomCond,
|
|
];
|
|
}
|
|
}
|
|
|
|
$parts = preg_split('/\s+/', $nomCond, 2);
|
|
|
|
return [
|
|
'tipologia' => 'fisica',
|
|
'cognome' => $parts[0] ?? $nomCond,
|
|
'nome' => $parts[1] ?? '',
|
|
'ragione_sociale' => null,
|
|
];
|
|
}
|
|
|
|
private function parseMirrorDate(?string $dateStr): ?string
|
|
{
|
|
if (empty($dateStr)) {
|
|
return null;
|
|
}
|
|
$dateStr = trim($dateStr);
|
|
if ($dateStr === '0' || $dateStr === '00/00/00' || $dateStr === '00/00/0000') {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$parts = explode(' ', $dateStr);
|
|
$datePart = $parts[0];
|
|
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$/', $datePart, $m)) {
|
|
$month = (int) $m[1];
|
|
$day = (int) $m[2];
|
|
$year = (int) $m[3];
|
|
if ($year < 100) {
|
|
$year += ($year > 50 ? 1900 : 2000);
|
|
}
|
|
if ($month > 12 && $day <= 12) {
|
|
$tmp = $month;
|
|
$month = $day;
|
|
$day = $tmp;
|
|
}
|
|
|
|
return sprintf('%04d-%02d-%02d', $year, $month, $day);
|
|
}
|
|
$dt = new \DateTime($dateStr);
|
|
|
|
return $dt->format('Y-m-d');
|
|
} catch (\Throwable $e) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|