149 lines
5.0 KiB
PHP
Executable File
149 lines
5.0 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class DedupeRateEmesseCommand extends Command
|
|
{
|
|
protected $signature = 'netgescon:dedupe-rate-emesse
|
|
{--stabile-id= : ID stabile (domain) da filtrare}
|
|
{--cod-stabile= : Codice stabile legacy (es. 0021) da filtrare}
|
|
{--dry-run : Non elimina, stampa solo le statistiche}';
|
|
|
|
protected $description = 'Deduplica rate_emesse su (piano_rateizzazione_id, unita_immobiliare_id, numero_rata_progressivo)';
|
|
|
|
public function handle(): int
|
|
{
|
|
$stabileId = $this->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;
|
|
}
|
|
}
|