296 lines
16 KiB
PHP
296 lines
16 KiB
PHP
<?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('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();
|
|
}),
|
|
]);
|
|
}
|
|
}
|