netgescon-day0/app/Filament/Pages/SuperAdmin/Amministratori.php

312 lines
17 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Filament\Pages\SuperAdmin;
use App\Models\Amministratore;
use App\Models\User;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Pages\Page;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\DatePicker;
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;
use Illuminate\Support\Carbon;
use UnitEnum;
class Amministratori extends Page implements HasTable
{
use InteractsWithTable;
protected static ?string $navigationLabel = 'Amministratori';
protected static ?string $title = 'Gestione amministratori';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-building-office';
protected static UnitEnum|string|null $navigationGroup = 'Super Admin';
protected static ?int $navigationSort = 2;
protected static ?string $slug = 'superadmin/amministratori';
protected string $view = 'filament.pages.gescon.table';
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin'])
&& Schema::hasTable('amministratori');
}
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
return Amministratore::query()->withCount('stabili');
}
public function table(Table $table): Table
{
return $table
->striped()
->defaultSort('id', 'desc')
->columns([
TextColumn::make('id')->label('ID')->sortable(),
TextColumn::make('codice_univoco')->label('Codice')->searchable()->sortable(),
TextColumn::make('nome')->label('Nome')->searchable()->sortable(),
TextColumn::make('cognome')->label('Cognome')->searchable()->sortable(),
TextColumn::make('stabili_count')->label('Stabili')->sortable(),
TextColumn::make('denominazione_studio')->label('Studio')->searchable()->toggleable(),
TextColumn::make('email_studio')->label('Email')->searchable()->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('pec_studio')->label('PEC')->searchable()->toggleable(isToggledHiddenByDefault: true),
IconColumn::make('attivo')->label('Attivo')->boolean()->sortable()->toggleable(),
IconColumn::make('abilita_import_stabili')->label('Import')->boolean()->sortable()->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('fe_cassetto_status')
->label('FE Stato')
->state(function (Amministratore $record): string {
if (! (bool) ($record->fe_cassetto_enabled ?? false)) {
return 'Disabilitato';
}
$expiresAt = $record->fe_cassetto_expires_at;
if ($expiresAt instanceof Carbon && $expiresAt->startOfDay()->lt(now()->startOfDay())) {
return 'Scaduto';
}
return 'Attivo';
})
->badge()
->color(function (Amministratore $record): string {
if (! (bool) ($record->fe_cassetto_enabled ?? false)) {
return 'gray';
}
$expiresAt = $record->fe_cassetto_expires_at;
if ($expiresAt instanceof Carbon && $expiresAt->startOfDay()->lt(now()->startOfDay())) {
return 'danger';
}
return 'success';
})
->sortable(),
IconColumn::make('fe_cassetto_enabled')->label('FE Abilitato')->boolean()->sortable()->toggleable(),
TextColumn::make('fe_cassetto_expires_at')->label('FE Scadenza')->date('d/m/Y')->sortable()->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('updated_at')->label('Aggiornato')->dateTime('d/m/Y H:i')->toggleable(isToggledHiddenByDefault: true),
])
->headerActions([
Action::make('create')
->label('Nuovo')
->icon('heroicon-o-plus')
->form([
Select::make('user_id')
->label('Utente collegato')
->options(fn() => User::query()
->whereDoesntHave('amministratore')
->orderBy('name')
->get()
->mapWithKeys(fn(User $u) => [
$u->id => trim($u->name . ' <' . $u->email . '>'),
])
->all())
->searchable()
->required(),
TextInput::make('nome')->label('Nome')->required()->maxLength(100),
TextInput::make('cognome')->label('Cognome')->required()->maxLength(100),
TextInput::make('denominazione_studio')->label('Denominazione studio')->maxLength(255),
TextInput::make('partita_iva')->label('Partita IVA')->maxLength(30),
TextInput::make('codice_fiscale_studio')->label('Codice fiscale')->maxLength(30),
TextInput::make('indirizzo_studio')->label('Indirizzo')->maxLength(255),
TextInput::make('cap_studio')->label('CAP')->maxLength(10),
TextInput::make('citta_studio')->label('Città')->maxLength(60),
TextInput::make('provincia_studio')->label('Provincia')->maxLength(5),
TextInput::make('telefono_studio')->label('Telefono')->maxLength(50),
TextInput::make('email_studio')->label('Email')->maxLength(255),
TextInput::make('pec_studio')->label('PEC')->maxLength(255),
Toggle::make('attivo')->label('Attivo')->default(true),
Toggle::make('abilita_import_stabili')->label('Abilita import stabili')->default(true),
Toggle::make('fe_cassetto_enabled')
->label('Abilita servizio scarico Fatture (Cassetto Fiscale)')
->helperText('Servizio a pagamento: abilita solo per gli amministratori autorizzati.')
->default(false),
DatePicker::make('fe_cassetto_expires_at')
->label('Scadenza servizio (opzionale)')
->helperText('Se valorizzata, dopo questa data lo scarico sarà bloccato finché non rinnovato.')
->native(false)
->displayFormat('d/m/Y')
->nullable(),
])
->action(function (array $data): void {
$amm = Amministratore::query()->create([
'user_id' => (int) ($data['user_id'] ?? 0),
'nome' => trim((string) ($data['nome'] ?? '')),
'cognome' => trim((string) ($data['cognome'] ?? '')),
'denominazione_studio' => (string) ($data['denominazione_studio'] ?? ''),
'partita_iva' => (string) ($data['partita_iva'] ?? ''),
'codice_fiscale_studio' => (string) ($data['codice_fiscale_studio'] ?? ''),
'indirizzo_studio' => (string) ($data['indirizzo_studio'] ?? ''),
'cap_studio' => (string) ($data['cap_studio'] ?? ''),
'citta_studio' => (string) ($data['citta_studio'] ?? ''),
'provincia_studio' => (string) ($data['provincia_studio'] ?? ''),
'telefono_studio' => (string) ($data['telefono_studio'] ?? ''),
'email_studio' => (string) ($data['email_studio'] ?? ''),
'pec_studio' => (string) ($data['pec_studio'] ?? ''),
'attivo' => (bool) ($data['attivo'] ?? true),
'abilita_import_stabili' => (bool) ($data['abilita_import_stabili'] ?? true),
'fe_cassetto_enabled' => (bool) ($data['fe_cassetto_enabled'] ?? false),
'fe_cassetto_expires_at' => $data['fe_cassetto_expires_at'] ?? null,
]);
// Best-effort: provisioning cartelle.
try {
$amm->provisionArchiveIfMissing();
} catch (\Throwable) {
}
}),
])
->actions([
Action::make('edit')
->label('Modifica')
->icon('heroicon-o-pencil-square')
->form([
Select::make('user_id')
->label('Utente collegato')
->options(fn(Amministratore $record) => User::query()
->where(function (Builder $q) use ($record) {
$q->whereDoesntHave('amministratore')
->orWhere('id', (int) $record->user_id);
})
->orderBy('name')
->get()
->mapWithKeys(fn(User $u) => [
$u->id => trim($u->name . ' <' . $u->email . '>'),
])
->all())
->searchable()
->required(),
TextInput::make('nome')->label('Nome')->required()->maxLength(100),
TextInput::make('cognome')->label('Cognome')->required()->maxLength(100),
TextInput::make('denominazione_studio')->label('Denominazione studio')->maxLength(255),
TextInput::make('partita_iva')->label('Partita IVA')->maxLength(30),
TextInput::make('codice_fiscale_studio')->label('Codice fiscale')->maxLength(30),
TextInput::make('indirizzo_studio')->label('Indirizzo')->maxLength(255),
TextInput::make('cap_studio')->label('CAP')->maxLength(10),
TextInput::make('citta_studio')->label('Città')->maxLength(60),
TextInput::make('provincia_studio')->label('Provincia')->maxLength(5),
TextInput::make('telefono_studio')->label('Telefono')->maxLength(50),
TextInput::make('email_studio')->label('Email')->maxLength(255),
TextInput::make('pec_studio')->label('PEC')->maxLength(255),
Toggle::make('attivo')->label('Attivo'),
Toggle::make('abilita_import_stabili')->label('Abilita import stabili'),
Toggle::make('fe_cassetto_enabled')
->label('Abilita servizio scarico Fatture (Cassetto Fiscale)')
->helperText('Servizio a pagamento: abilita solo per gli amministratori autorizzati.'),
DatePicker::make('fe_cassetto_expires_at')
->label('Scadenza servizio (opzionale)')
->native(false)
->displayFormat('d/m/Y')
->nullable(),
])
->fillForm(fn(Amministratore $record): array => [
'user_id' => (int) $record->user_id,
'nome' => (string) ($record->nome ?? ''),
'cognome' => (string) ($record->cognome ?? ''),
'denominazione_studio' => (string) ($record->denominazione_studio ?? ''),
'partita_iva' => (string) ($record->partita_iva ?? ''),
'codice_fiscale_studio' => (string) ($record->codice_fiscale_studio ?? ''),
'indirizzo_studio' => (string) ($record->indirizzo_studio ?? ''),
'cap_studio' => (string) ($record->cap_studio ?? ''),
'citta_studio' => (string) ($record->citta_studio ?? ''),
'provincia_studio' => (string) ($record->provincia_studio ?? ''),
'telefono_studio' => (string) ($record->telefono_studio ?? ''),
'email_studio' => (string) ($record->email_studio ?? ''),
'pec_studio' => (string) ($record->pec_studio ?? ''),
'attivo' => (bool) ($record->attivo ?? true),
'abilita_import_stabili' => (bool) ($record->abilita_import_stabili ?? true),
'fe_cassetto_enabled' => (bool) ($record->fe_cassetto_enabled ?? false),
'fe_cassetto_expires_at' => $record->fe_cassetto_expires_at?->format('Y-m-d'),
])
->action(function (Amministratore $record, array $data): void {
$update = [
'user_id' => (int) ($data['user_id'] ?? 0),
'nome' => trim((string) ($data['nome'] ?? '')),
'cognome' => trim((string) ($data['cognome'] ?? '')),
'denominazione_studio' => (string) ($data['denominazione_studio'] ?? ''),
'partita_iva' => (string) ($data['partita_iva'] ?? ''),
'codice_fiscale_studio' => (string) ($data['codice_fiscale_studio'] ?? ''),
'indirizzo_studio' => (string) ($data['indirizzo_studio'] ?? ''),
'cap_studio' => (string) ($data['cap_studio'] ?? ''),
'citta_studio' => (string) ($data['citta_studio'] ?? ''),
'provincia_studio' => (string) ($data['provincia_studio'] ?? ''),
'telefono_studio' => (string) ($data['telefono_studio'] ?? ''),
'email_studio' => (string) ($data['email_studio'] ?? ''),
'pec_studio' => (string) ($data['pec_studio'] ?? ''),
'attivo' => (bool) ($data['attivo'] ?? true),
'abilita_import_stabili' => (bool) ($data['abilita_import_stabili'] ?? true),
'fe_cassetto_enabled' => (bool) ($data['fe_cassetto_enabled'] ?? false),
'fe_cassetto_expires_at' => $data['fe_cassetto_expires_at'] ?? null,
];
$record->fill($update);
$record->save();
try {
$record->provisionArchiveIfMissing();
} catch (\Throwable) {
}
}),
Action::make('impersonate')
->label('Impersona')
->icon('heroicon-o-user-plus')
->color('warning')
->requiresConfirmation()
->modalHeading('Conferma Impersonificazione Amministratore')
->modalDescription('Stai per accedere al sistema impersonando lo studio dellamministratore selezionato. Tutte le azioni saranno tracciate nellaudit log.')
->visible(fn(Amministratore $record): bool => (bool) $record->user_id && $record->user_id !== Auth::id())
->action(function (Amministratore $record): void {
if ($record->user) {
session(['impersonator_id' => Auth::id()]);
Auth::login($record->user);
redirect()->to('/admin-filament');
}
}),
Action::make('delete')
->label('Elimina')
->icon('heroicon-o-trash')
->color('danger')
->requiresConfirmation()
->action(function (Amministratore $record): void {
if ($record->stabili()->exists()) {
throw new \RuntimeException('Impossibile eliminare: ci sono stabili collegati.');
}
if ($record->fornitori()->exists()) {
throw new \RuntimeException('Impossibile eliminare: ci sono fornitori collegati.');
}
$record->delete();
}),
]);
}
}