false, 'missing_units' => [], 'tabelle_sbilanciate' => [], 'discrepanze_assemblee' => [], ]; } $stabile = Stabile::find($stabileId); $stabileCode = $stabile?->codice_stabile; // 1. Audit delle Unità Mancanti 1:1 $missingUnits = []; if ($stabileCode && Schema::connection('gescon_import')->hasTable('condomin')) { $legacyUnits = DB::connection('gescon_import')->table('condomin') ->where('cod_stabile', $stabileCode) ->get(['cod_cond', 'interno', 'scala', 'cognome', 'nome']); foreach ($legacyUnits as $lu) { $exists = DB::table('unita_immobiliari') ->where('stabile_id', $stabileId) ->where('legacy_cond_id', $lu->cod_cond) ->exists(); if (!$exists) { $missingUnits[] = [ 'cod_cond' => $lu->cod_cond, 'nominativo' => trim(($lu->nome ?? '') . ' ' . ($lu->cognome ?? '')) ?: 'N/D', 'scala' => $lu->scala ?: 'N/D', 'interno' => $lu->interno ?: 'N/D', ]; } } } // 2. Sbilanciamento millesimale delle tabelle $tabelleSbilanciate = []; $tabelle = TabellaMillesimale::where('stabile_id', $stabileId)->get(); foreach ($tabelle as $t) { $sommaMillesimi = DB::table('dettaglio_millesimi') ->where('tabella_millesimale_id', $t->id) ->sum('millesimi'); $expected = (float) $t->totale_millesimi; if (abs($sommaMillesimi - $expected) > 0.01) { $legacyYear = $t->meta_legacy['legacy_year'] ?? null; $totMmLegacy = null; if ($stabileCode && $legacyYear && Schema::connection('gescon_import')->hasTable('tabelle_millesimali')) { $totMmLegacyRaw = DB::connection('gescon_import')->table('tabelle_millesimali') ->where('cod_stabile', $stabileCode) ->where('legacy_year', $legacyYear) ->where('codice_tabella', $t->codice_tabella) ->value('totale_millesimi'); if ($totMmLegacyRaw > 9999) { $totMmLegacy = $totMmLegacyRaw / 10000.0; } else { $totMmLegacy = $totMmLegacyRaw; } } $tabelleSbilanciate[] = [ 'codice' => $t->codice_tabella, 'denominazione' => $t->denominazione, 'anno_gestione' => $t->anno_gestione ?? ($t->meta_legacy['legacy_year'] ?? 'N/D'), 'somma_reale' => $sommaMillesimi, 'atteso_db' => $expected, 'atteso_legacy' => $totMmLegacy ?: $expected, 'differenza' => abs($sommaMillesimi - $expected), ]; } } // 3. Discrepanze sul calcolo delle teste e dei millesimi presenti nell'assemblea $discrepanzeAssemblee = []; if ($stabileCode && Schema::connection('gescon_import')->hasTable('pres_assemblee')) { $legacyPresRows = DB::connection('gescon_import')->table('pres_assemblee') ->where('cod_stabile', $stabileCode) ->get(); $tabAId = DB::table('tabelle_millesimali') ->where('stabile_id', $stabileId) ->where('codice_tabella', 'TAB.A') ->value('id'); foreach ($legacyPresRows as $pr) { $idCond = $pr->id_condomino ?? null; $millesimiLegacy = (float) ($pr->millesimi ?? 0); $unit = DB::table('unita_immobiliari') ->where('stabile_id', $stabileId) ->where('legacy_cond_id', $idCond) ->first(); if (!$unit) { continue; } $unitMillesimi = 0.0; if ($tabAId) { $unitMillesimi = (float) DB::table('dettaglio_millesimi') ->where('tabella_millesimale_id', $tabAId) ->where('unita_immobiliare_id', $unit->id) ->value('millesimi'); } if (abs($unitMillesimi - $millesimiLegacy) > 0.01) { $discrepanzeAssemblee[] = [ 'anno' => $pr->legacy_year ?? 'N/D', 'assemblea' => $pr->num_assemblea ?? 'N/D', 'unita' => $unit->codice_unita ?: $unit->id, 'legacy_cond_id' => $idCond, 'millesimi_db' => $unitMillesimi, 'millesimi_legacy' => $millesimiLegacy, 'p_d_a' => $pr->p_d_a ?? 'N/D', ]; } } } // 4. Audit delle Anomalie Anagrafiche e dei Record Orfani $anagraficheAnomale = []; if ($stabileCode && Schema::connection('gescon_import')->hasTable('condomin')) { $condominRows = DB::connection('gescon_import')->table('condomin') ->where('cod_stabile', $stabileCode) ->get(); foreach ($condominRows as $cr) { $cf = trim($cr->cond_cod_fisc ?? $cr->codice_fiscale ?? ''); $nome = trim(($cr->nome ?? '') . ' ' . ($cr->cognome ?? '')); if (empty($cf) && !empty($nome)) { $anagraficheAnomale[] = [ 'tipo' => 'Codice Fiscale Mancante', 'dettaglio' => "Unità Int. {$cr->interno} (Scala {$cr->scala}) - Nominativo: {$nome}", 'istruzioni' => "CRITICO: Inserire il Codice Fiscale valido negli archivi legacy." ]; } if ($cr->cod_cond) { $hasPeriodo = DB::table('unita_anagrafica_periodo as uap') ->join('unita_immobiliari as ui', 'ui.id', '=', 'uap.unita_immobiliare_id') ->where('ui.stabile_id', $stabileId) ->where('ui.legacy_cond_id', $cr->cod_cond) ->exists(); if (!$hasPeriodo && !empty($nome)) { $anagraficheAnomale[] = [ 'tipo' => 'Associazione Timeline Mancante', 'dettaglio' => "Nominativo: {$nome} (Cod. Cond: {$cr->cod_cond}) - Unità Int. {$cr->interno} (Scala {$cr->scala})", 'istruzioni' => "CRITICO: Periodo di occupazione mancante. Creare manualmente la relazione timeline per evitare errori di quadratura contabile." ]; } } } } return [ 'has_active_stabile' => true, 'stabile_nome' => $stabile?->denominazione, 'missing_units' => $missingUnits, 'tabelle_sbilanciate' => $tabelleSbilanciate, 'discrepanze_assemblee' => array_slice($discrepanzeAssemblee, 0, 100), 'anagrafiche_anomale' => $anagraficheAnomale, ]; } }