fix(millesimi): resolve false positive quadratura & missing unit audit alerts (task-d095b0e23b)

This commit is contained in:
michele 2026-08-29 01:10:26 +02:00
parent edd4b1a0f3
commit 31849ae697
2 changed files with 59 additions and 9 deletions

View File

@ -2539,6 +2539,25 @@ private function stepMillesimi(?int $limit): int
$unitaId = $u->id ?? null; $unitaId = $u->id ?? null;
} }
} }
if (! $unitaId && isset($r->scala) && isset($r->interno)) {
$rScala = strtoupper(trim((string) $r->scala));
$rInt = strtoupper(trim((string) $r->interno));
$allUnits = DB::table('unita_immobiliari')
->where('stabile_id', $targetStabileId)
->whereNull('deleted_at')
->get(['id', 'scala', 'interno']);
foreach ($allUnits as $uItem) {
if (strtoupper(trim((string) $uItem->scala)) === $rScala) {
$uInt = strtoupper(trim((string) $uItem->interno));
if ($uInt === $rInt || str_contains($uInt, $rInt) || str_contains($rInt, $uInt)) {
$unitaId = $uItem->id;
break;
}
}
}
}
} }
if (! $unitaId) { if (! $unitaId) {
@ -2579,7 +2598,7 @@ private function stepMillesimi(?int $limit): int
$exists = $existsQuery->first(); $exists = $existsQuery->first();
if ($exists) { if ($exists) {
$upd = [ $upd = [
'millesimi' => $mm, 'millesimi' => (float) ($exists->millesimi ?? 0) + $mm,
'updated_at' => now(), 'updated_at' => now(),
]; ];
// Se la tabella ha una colonna per ordine (es. posizione, ordinale, nord), prova ad aggiornarla // Se la tabella ha una colonna per ordine (es. posizione, ordinale, nord), prova ad aggiornarla

View File

@ -2018,12 +2018,18 @@ public function getMillesimiAuditProperty(): array
$tablesOutOfQuadratura = []; $tablesOutOfQuadratura = [];
$tabelle = TabellaMillesimale::where('stabile_id', $stabileId)->get(); $tabelle = TabellaMillesimale::where('stabile_id', $stabileId)->get();
foreach ($tabelle as $t) { foreach ($tabelle as $t) {
$code = strtoupper(trim((string) ($t->codice_tabella ?: $t->nome_tabella)));
// Ignora tabelle header-only, virtuali, a consumo o detrazioni (RI.ASS, RIPART, INDIV, ACQUA, CONG.O, SINDIV, P01.ST, DET_*)
if (in_array($code, ['RI.ASS', 'RIPART', 'INDIV.', 'INDIV', 'ACQUA', 'CONG.O', 'SINDIV', 'P01.ST'], true) || str_starts_with($code, 'DET_')) {
continue;
}
$sum = DB::table('dettaglio_millesimi') $sum = DB::table('dettaglio_millesimi')
->where('tabella_millesimale_id', $t->id) ->where('tabella_millesimale_id', $t->id)
->sum('millesimi'); ->sum('millesimi');
$expected = (float) ($t->getRawOriginal('totale_millesimi') ?: 1000.0); $expected = (float) ($t->getRawOriginal('totale_millesimi') ?: 1000.0);
if (abs($sum - $expected) > 0.01) { if ($expected > 0 && abs($sum - $expected) > 0.01) {
$tablesOutOfQuadratura[] = [ $tablesOutOfQuadratura[] = [
'id' => $t->id, 'id' => $t->id,
'codice' => $t->codice_tabella, 'codice' => $t->codice_tabella,
@ -2043,27 +2049,52 @@ public function getMillesimiAuditProperty(): array
$legacyCode = $this->codiceStabile; $legacyCode = $this->codiceStabile;
if ($legacyCode && Schema::connection('gescon_import')->hasTable('condomin')) { if ($legacyCode && Schema::connection('gescon_import')->hasTable('condomin')) {
$latestYear = DB::connection('gescon_import')
->table('condomin')
->where('cod_stabile', $legacyCode)
->max('legacy_year') ?: '0015';
$legacyUnits = DB::connection('gescon_import') $legacyUnits = DB::connection('gescon_import')
->table('condomin') ->table('condomin')
->where('cod_stabile', $legacyCode) ->where('cod_stabile', $legacyCode)
->get(['cod_cond', 'interno', 'scala', 'cognome', 'nome']); ->where('legacy_year', $latestYear)
->get(['cod_cond', 'id_cond', 'interno', 'scala', 'cognome', 'nome']);
$totalLegacy = $legacyUnits->count(); $totalLegacy = $legacyUnits->count();
$netGesconLegacyIds = DB::table('unita_immobiliari') $netGesconUnits = DB::table('unita_immobiliari')
->where('stabile_id', $stabileId) ->where('stabile_id', $stabileId)
->whereNull('deleted_at') ->whereNull('deleted_at')
->whereNotNull('legacy_cond_id') ->get(['id', 'scala', 'interno', 'legacy_cond_id']);
->where('legacy_cond_id', '!=', '')
$netGesconLegacyIds = $netGesconUnits
->pluck('legacy_cond_id') ->pluck('legacy_cond_id')
->filter()
->map(fn($val) => (int)$val) ->map(fn($val) => (int)$val)
->toArray(); ->toArray();
foreach ($legacyUnits as $lu) { foreach ($legacyUnits as $lu) {
$luCod = (int) $lu->cod_cond; $luCod = (int) $lu->cod_cond;
if (!in_array($luCod, $netGesconLegacyIds, true)) { $luIdCond = (int) ($lu->id_cond ?? 0);
$matched = in_array($luCod, $netGesconLegacyIds, true) || in_array($luIdCond, $netGesconLegacyIds, true);
if (! $matched && ! empty($lu->scala) && ! empty($lu->interno)) {
$luScala = strtoupper(trim((string) $lu->scala));
$luInt = strtoupper(trim((string) $lu->interno));
foreach ($netGesconUnits as $uItem) {
if (strtoupper(trim((string) $uItem->scala)) === $luScala) {
$uInt = strtoupper(trim((string) $uItem->interno));
if ($uInt === $luInt || str_contains($uInt, $luInt) || str_contains($luInt, $uInt)) {
$matched = true;
break;
}
}
}
}
if (! $matched) {
$missingLegacyUnits[] = [ $missingLegacyUnits[] = [
'cod_cond' => $lu->cod_cond, 'cod_cond' => $lu->cod_cond,
'posizione' => "Scala " . ($lu->scala ?: '—') . " Int. " . ($lu->interno ?: '—'), 'posizione' => "Scala " . ($lu->scala ?: '—') . " Int. " . ($lu->interno ?: '—'),
'nominativo' => trim($lu->cognome . ' ' . $lu->nome) ?: '—', 'nominativo' => trim($lu->cognome . ' ' . $lu->nome) ?: '—',
]; ];