315 lines
14 KiB
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),
|
|
]);
|
|
}
|
|
}
|