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

198 lines
9.1 KiB
PHP
Executable File

<?php
namespace App\Filament\Pages\SuperAdmin;
use App\Models\AreraOperatore;
use App\Models\AreraSettoreAttivita;
use App\Models\User;
use App\Services\Arera\AreraOperatoriImportService;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use UnitEnum;
class OperatoriArera extends Page implements HasTable
{
use InteractsWithTable;
protected static ?string $navigationLabel = 'Operatori ARERA';
protected static ?string $title = 'Operatori ARERA';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-building-office-2';
protected static UnitEnum|string|null $navigationGroup = 'Super Admin';
protected static ?int $navigationSort = 26;
protected static ?string $slug = 'superadmin/operatori-arera';
protected string $view = 'filament.pages.gescon.table';
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasRole('super-admin')
&& Schema::hasTable('arera_operatori');
}
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
return AreraOperatore::query()->with(['naturaGiuridica', 'settori']);
}
public function table(Table $table): Table
{
return $table
->striped()
->defaultSort('societa')
->columns([
TextColumn::make('societa')
->label('Società')
->formatStateUsing(fn($state, AreraOperatore $record): string => trim((string) $state) !== '' ? trim((string) $state) : ('P.IVA ' . (string) ($record->partita_iva ?: $record->partita_iva_normalizzata)))
->searchable()
->sortable()
->wrap(),
TextColumn::make('partita_iva')->label('P.IVA')->searchable()->sortable(),
TextColumn::make('naturaGiuridica.nome')->label('Natura')->toggleable()->sortable(),
TextColumn::make('settori.nome')->label('Settori')->badge()->separator(',')->searchable(),
TextColumn::make('sito_internet')->label('Sito')->url(fn(AreraOperatore $record): ?string => $record->sito_internet)->openUrlInNewTab()->toggleable(),
TextColumn::make('sede_legale_citta')->label('Città')->searchable()->toggleable(),
TextColumn::make('sede_legale_provincia')->label('Prov.')->searchable()->toggleable(),
TextColumn::make('updated_at')->label('Aggiornato')->dateTime('d/m/Y H:i')->toggleable(isToggledHiddenByDefault: true),
])
->filters([
SelectFilter::make('settore')
->label('Settore')
->options(fn(): array=> AreraSettoreAttivita::query()->orderBy('nome')->pluck('nome', 'id')->all())
->query(function (Builder $query, array $data): Builder {
$value = (int) ($data['value'] ?? 0);
if ($value <= 0) {
return $query;
}
return $query->whereHas('settori', fn(Builder $q): Builder => $q->whereKey($value));
}),
])
->headerActions([
Action::make('scarica_zip_arera')
->label('Scarica ZIP ARERA')
->icon('heroicon-o-cloud-arrow-down')
->modalWidth('4xl')
->form([
Select::make('preset_url')
->label('Fonte rapida')
->options([
'https://www.arera.it/fileadmin/ricercaoperatori/operatori-export-29_06_2026_09_00_10.zip' => 'Operatori - export completo (29/06/2026)',
'https://www.arera.it/fileadmin/ricercaoperatori/export-mercato-vend29_06_2026_09_35_02.zip' => 'Mercato vendita (29/06/2026)',
'https://www.arera.it/fileadmin/ricercaoperatori/export-gas-vend29_06_2026_09_30_02.zip' => 'Gas vendita (29/06/2026)',
])
->native(false)
->helperText('I nomi file ARERA cambiano nel tempo: se il preset non e aggiornato, incolla sotto il nuovo URL ZIP.')
->reactive(),
TextInput::make('custom_url')
->label('URL ZIP ARERA')
->placeholder('https://www.arera.it/fileadmin/ricercaoperatori/operatori-export-...zip')
->url()
->maxLength(1000),
])
->action(function (array $data): void {
$url = trim((string) ($data['custom_url'] ?? ''));
if ($url === '') {
$url = trim((string) ($data['preset_url'] ?? ''));
}
if ($url === '') {
Notification::make()->title('Indica un URL ZIP ARERA')->danger()->send();
return;
}
try {
$result = app(AreraOperatoriImportService::class)->importZipFromUrl($url);
$body = 'File Excel: ' . $result['files']
. ' · Righe: ' . $result['rows']
. ' · Nuovi: ' . $result['imported']
. ' · Aggiornati: ' . $result['updated']
. ' · Saltati: ' . $result['skipped']
. ' · Settori: ' . $result['sectors'];
if (! empty($result['errors'])) {
$body .= "\n" . implode("\n", $result['errors']);
}
Notification::make()->title('Download/import ARERA completato')->body($body)->success()->send();
} catch (\Throwable $e) {
report($e);
Notification::make()->title('Errore download ARERA')->body($e->getMessage())->danger()->send();
}
}),
Action::make('importa_excel')
->label('Importa Excel ARERA')
->icon('heroicon-o-arrow-up-tray')
->modalWidth('3xl')
->form([
FileUpload::make('xlsx_file')
->label('File operatori-export.xlsx')
->disk('local')
->directory('tmp/arera-operatori')
->acceptedFileTypes([
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-excel',
'.xlsx',
'.xls',
])
->required(),
])
->action(function (array $data): void {
$path = (string) ($data['xlsx_file'] ?? '');
if ($path === '') {
Notification::make()->title('Seleziona un file Excel')->danger()->send();
return;
}
try {
$result = app(AreraOperatoriImportService::class)->importXlsx(
Storage::disk('local')->path($path),
basename($path),
);
$body = 'Righe: ' . $result['rows']
. ' · Nuovi: ' . $result['imported']
. ' · Aggiornati: ' . $result['updated']
. ' · Saltati: ' . $result['skipped']
. ' · Settori: ' . $result['sectors'];
if (! empty($result['errors'])) {
$body .= "\n" . implode("\n", $result['errors']);
}
Notification::make()->title('Import ARERA completato')->body($body)->success()->send();
} catch (\Throwable $e) {
report($e);
Notification::make()->title('Errore import ARERA')->body($e->getMessage())->danger()->send();
}
}),
]);
}
}