resolveStabileId(); $pianoIds = null; if ($stabileId !== null) { $pianoIds = DB::table('piano_rateizzazione') ->where('stabile_id', $stabileId) ->pluck('piano_rateizzazione.id') ->map(fn($v) => (int) $v) ->filter(fn(int $v) => $v > 0) ->values() ->all(); $this->info('Filtro stabile_id=' . $stabileId . ' (piani=' . count($pianoIds) . ')'); } $dryRun = (bool) $this->option('dry-run'); $groupsQuery = DB::table('rate_emesse') ->select( 'piano_rateizzazione_id', 'unita_immobiliare_id', 'numero_rata_progressivo', DB::raw('COUNT(*) as c') ) ->when(is_array($pianoIds), fn($q) => $q->whereIn('piano_rateizzazione_id', $pianoIds)) ->groupBy('piano_rateizzazione_id', 'unita_immobiliare_id', 'numero_rata_progressivo') ->having('c', '>', 1) ->orderBy('piano_rateizzazione_id') ->orderBy('unita_immobiliare_id') ->orderBy('numero_rata_progressivo'); $duplicateGroups = 0; $deleted = 0; foreach ($groupsQuery->cursor() as $g) { $duplicateGroups++; $rows = DB::table('rate_emesse') ->where('piano_rateizzazione_id', $g->piano_rateizzazione_id) ->where('unita_immobiliare_id', $g->unita_immobiliare_id) ->where('numero_rata_progressivo', $g->numero_rata_progressivo) ->orderBy('id') ->get(['id', 'soggetto_responsabile_id']); $preferredSoggettoId = DB::table('proprieta') ->where('unita_immobiliare_id', $g->unita_immobiliare_id) ->orderByRaw("CASE tipo_diritto WHEN 'proprieta' THEN 0 WHEN 'locazione' THEN 1 ELSE 2 END") ->orderBy('id') ->value('soggetto_id'); $keepId = (int) $rows->first()->id; if ($preferredSoggettoId) { foreach ($rows as $r) { if ((int) $r->soggetto_responsabile_id === (int) $preferredSoggettoId) { $keepId = (int) $r->id; break; } } } $toDelete = $rows ->pluck('id') ->map(fn($v) => (int) $v) ->filter(fn(int $id) => $id !== $keepId) ->values() ->all(); if (count($toDelete) === 0) { continue; } if (!$dryRun) { $deleted += DB::table('rate_emesse')->whereIn('id', $toDelete)->delete(); } } $remainingQuery = DB::table('rate_emesse'); if (is_array($pianoIds)) { $remainingQuery->whereIn('piano_rateizzazione_id', $pianoIds); } $remaining = (int) $remainingQuery->count(); $this->info('duplicate_groups=' . $duplicateGroups); $this->info('deleted=' . ($dryRun ? 0 : $deleted) . ($dryRun ? ' (dry-run)' : '')); $this->info('remaining=' . $remaining); return self::SUCCESS; } private function resolveStabileId(): ?int { $stabileId = $this->option('stabile-id'); if (is_numeric($stabileId)) { $stabileId = (int) $stabileId; return $stabileId > 0 ? $stabileId : null; } $codStabile = $this->option('cod-stabile'); if (!is_string($codStabile) || trim($codStabile) === '') { return null; } $codStabile = trim($codStabile); $query = DB::table('stabili'); $hasAny = false; foreach (['codice_stabile', 'codice_interno', 'cod_stabile'] as $col) { if (!Schema::hasColumn('stabili', $col)) { continue; } $hasAny = true; $query->orWhere($col, $codStabile); } if (!$hasAny) { $this->warn('Tabella stabili senza colonne codice note (nessun filtro applicato)'); return null; } $id = $query->value('id'); if (is_numeric($id)) { $id = (int) $id; return $id > 0 ? $id : null; } $this->warn('Stabile non trovato per cod_stabile=' . $codStabile . ' (nessun filtro applicato)'); return null; } }