netgescon-day0/app/Filament/Pages/Condomini/UnitaImmobiliariArchivio.php

315 lines
14 KiB
PHP

<?php
namespace App\Filament\Pages\Condomini;
use App\Filament\Pages\UnitaImmobiliarePage;
use App\Models\UnitaImmobiliare;
use App\Models\User;
use App\Support\StabileContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Pages\Page;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema as DbSchema;
use UnitEnum;
class UnitaImmobiliariArchivio extends Page implements HasTable
{
use InteractsWithTable;
protected static ?string $navigationLabel = 'Unità immobiliari';
protected static ?string $title = 'Unità immobiliari';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-home';
protected static UnitEnum|string|null $navigationGroup = 'Stabile';
protected static ?int $navigationSort = 31;
protected static ?string $slug = 'condomini/unita-immobiliari';
protected string $view = 'filament.pages.condomini.unita-immobiliari-archivio';
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
}
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
$user = Auth::user();
if (! $user instanceof User) {
return UnitaImmobiliare::query()->whereRaw('1 = 0');
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return UnitaImmobiliare::query()->whereRaw('1 = 0');
}
$today = now()->toDateString();
$rubricaNameSubquery = "(\n"
. " SELECT MIN(\n"
. " CASE\n"
. " WHEN ru.tipo_contatto = 'persona_giuridica' THEN ru.ragione_sociale\n"
. " ELSE CONCAT_WS(' ', ru.nome, ru.cognome)\n"
. " END\n"
. " )\n"
. " FROM rubrica_ruoli rr\n"
. " JOIN rubrica_universale ru ON ru.id = rr.rubrica_id\n"
. " WHERE rr.unita_immobiliare_id = unita_immobiliari.id\n"
. " AND rr.is_attivo = 1\n"
. " AND (rr.data_inizio IS NULL OR rr.data_inizio <= ?)\n"
. " AND (rr.data_fine IS NULL OR rr.data_fine >= ?)\n"
. ")";
$nominativoSortExpr = "COALESCE(\n"
. " CASE\n"
. " WHEN unita_immobiliari.denominazione IS NULL THEN NULL\n"
. " WHEN TRIM(unita_immobiliari.denominazione) = '' THEN NULL\n"
. " WHEN LOWER(TRIM(unita_immobiliari.denominazione)) = 'area condominiale' THEN NULL\n"
. " ELSE unita_immobiliari.denominazione\n"
. " END,\n"
. " $rubricaNameSubquery,\n"
. " unita_immobiliari.codice_unita\n"
. ")";
$stabileCols = ['id', 'codice_stabile', 'cod_stabile'];
if (DbSchema::hasColumn('stabili', 'codice_operatore')) {
$stabileCols[] = 'codice_operatore';
}
return UnitaImmobiliare::query()
->where('stabile_id', $activeStabileId)
->with([
'stabile' => function ($q) use ($stabileCols) {
$q->select($stabileCols);
},
'rubricaRuoliAttivi.contatto:id,tipo_contatto,ragione_sociale,nome,cognome,codice_fiscale',
'soggetti:id,nome,cognome,ragione_sociale,codice_fiscale',
])
->orderBy('palazzina')
->orderBy('scala')
->orderBy('interno')
->orderBy('id');
}
public function getUnitaCount(): int
{
$user = Auth::user();
if (! $user instanceof User) {
return 0;
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return 0;
}
return UnitaImmobiliare::query()
->where('stabile_id', $activeStabileId)
->count();
}
public function table(Table $table): Table
{
$unitaPageUrl = UnitaImmobiliarePage::getUrl(panel: 'admin-filament');
return $table
->striped()
->columns([
TextColumn::make('codice_unita')
->label('Codice')
->searchable()
->sortable()
->formatStateUsing(function ($state, UnitaImmobiliare $record): string {
$code = trim((string) ($state ?? ''));
if ($code === '') {
return '—';
}
$legacy = trim((string) ($record->stabile?->codice_stabile ?? ''));
$mnemo = trim((string) ($record->stabile?->codice_operatore ?? $record->stabile?->cod_stabile ?? ''));
if ($legacy !== '' && $mnemo !== '' && str_starts_with($code, $legacy . '-')) {
return $mnemo . substr($code, strlen($legacy));
}
return $code;
}),
TextColumn::make('denominazione')
->label('Nominativo')
->searchable(query: function (Builder $query, string $search): Builder {
$s = trim($search);
if ($s === '') {
return $query;
}
return $query
->where(function (Builder $q) use ($s): void {
$q->where('denominazione', 'like', '%' . $s . '%')
->orWhereHas('rubricaRuoliAttivi.contatto', function (Builder $qq) use ($s): void {
$qq->where('ragione_sociale', 'like', '%' . $s . '%')
->orWhere('nome', 'like', '%' . $s . '%')
->orWhere('cognome', 'like', '%' . $s . '%')
->orWhere('codice_fiscale', 'like', '%' . $s . '%');
})
->orWhereHas('soggetti', function (Builder $qq) use ($s): void {
$qq->where('ragione_sociale', 'like', '%' . $s . '%')
->orWhere('cognome', 'like', '%' . $s . '%')
->orWhere('nome', 'like', '%' . $s . '%')
->orWhere('codice_fiscale', 'like', '%' . $s . '%');
});
});
})
->sortable(query: function (Builder $query, string $direction): Builder {
$today = now()->toDateString();
$rubricaNameSubquery = "(\n"
. " SELECT MIN(\n"
. " CASE\n"
. " WHEN ru.tipo_contatto = 'persona_giuridica' THEN ru.ragione_sociale\n"
. " ELSE CONCAT_WS(' ', ru.nome, ru.cognome)\n"
. " END\n"
. " )\n"
. " FROM rubrica_ruoli rr\n"
. " JOIN rubrica_universale ru ON ru.id = rr.rubrica_id\n"
. " WHERE rr.unita_immobiliare_id = unita_immobiliari.id\n"
. " AND rr.is_attivo = 1\n"
. " AND (rr.data_inizio IS NULL OR rr.data_inizio <= ?)\n"
. " AND (rr.data_fine IS NULL OR rr.data_fine >= ?)\n"
. ")";
$nominativoSortExpr = "COALESCE(\n"
. " CASE\n"
. " WHEN unita_immobiliari.denominazione IS NULL THEN NULL\n"
. " WHEN TRIM(unita_immobiliari.denominazione) = '' THEN NULL\n"
. " WHEN LOWER(TRIM(unita_immobiliari.denominazione)) = 'area condominiale' THEN NULL\n"
. " ELSE unita_immobiliari.denominazione\n"
. " END,\n"
. " $rubricaNameSubquery,\n"
. " unita_immobiliari.codice_unita\n"
. ")";
return $query->orderByRaw($nominativoSortExpr . ' ' . $direction, [$today, $today]);
})
->state(function (UnitaImmobiliare $record): string {
$den = trim((string) ($record->denominazione ?? ''));
$isArea = $den !== '' && preg_match('/^\s*area\s+condominiale\s*$/i', $den);
if ($den !== '' && ! $isArea) {
return $den;
}
// Preferisci ruoli rubrica attivi: prima inquilino, poi condomino.
$ruoli = $record->rubricaRuoliAttivi ?? collect();
if ($ruoli && method_exists($ruoli, 'sortByDesc')) {
$ruoli = $ruoli->sortByDesc(fn($r) => (bool) ($r->is_preferito ?? false));
}
$isInquilino = function ($r): bool {
$k = strtolower(trim((string) ($r->ruolo_standard ?? '')));
return in_array($k, ['inquilino', 'locatario', 'conduttore'], true);
};
$isCondomino = function ($r): bool {
$k = strtolower(trim((string) ($r->ruolo_standard ?? '')));
return in_array($k, ['condomino', 'proprietario', 'comproprietario', 'nudo_proprietario', 'usufruttuario', 'usufrutto'], true);
};
$pick = $ruoli?->first(fn($r) => $isInquilino($r))
?: $ruoli?->first(fn($r) => $isCondomino($r));
$nomeRub = trim((string) ($pick?->contatto?->nome_completo ?? ''));
if ($nomeRub !== '') {
return $nomeRub;
}
// Fallback proprietari da proprietà (soggetti): scegli il primo disponibile.
$soggetti = $record->soggetti ?? collect();
if ($soggetti && $soggetti->isNotEmpty()) {
$s = $soggetti->first();
$rs = trim((string) ($s?->ragione_sociale ?? ''));
if ($rs !== '') {
return $rs;
}
$full = trim((string) ($s?->nome ?? '') . ' ' . (string) ($s?->cognome ?? ''));
if ($full !== '') {
return $full;
}
}
return $den !== '' ? $den : '—';
})
->wrap(),
TextColumn::make('palazzina')
->label('Pal.')
->toggleable(),
TextColumn::make('scala')
->label('Scala')
->toggleable(),
TextColumn::make('piano')
->label('Piano')
->toggleable(),
TextColumn::make('interno')
->label('Int.')
->formatStateUsing(function ($state, UnitaImmobiliare $record): string {
$interno = trim((string) ($state ?? ''));
if ($interno === '') {
return '—';
}
$legacy = trim((string) ($record->stabile?->codice_stabile ?? $record->stabile?->cod_stabile ?? ''));
$scala = trim((string) ($record->scala ?? ''));
if ($legacy !== '' && $scala !== '') {
$prefix = $legacy . '-' . $scala . '-';
if (str_starts_with($interno, $prefix)) {
$short = trim((string) substr($interno, strlen($prefix)));
return $short !== '' ? $short : $interno;
}
}
if ($record->codice_unita && $interno === $record->codice_unita && str_contains($interno, '-')) {
$pos = strrpos($interno, '-');
if ($pos !== false) {
$short = trim((string) substr($interno, $pos + 1));
return $short !== '' ? $short : $interno;
}
}
return $interno;
})
->toggleable(),
IconColumn::make('attiva')
->label('Attiva')
->boolean(),
])
->actions([
Action::make('apri_dettaglio')
->label('Apri')
->icon('heroicon-o-arrow-right')
->url(fn(UnitaImmobiliare $record) => $unitaPageUrl . '?unita_id=' . $record->id),
]);
}
}