255 lines
9.8 KiB
PHP
255 lines
9.8 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Pages\Contabilita;
|
|
|
|
use App\Filament\Pages\Contabilita\FatturaElettronicaScheda;
|
|
use App\Models\FatturaElettronica;
|
|
use App\Models\Stabile;
|
|
use App\Models\User;
|
|
use App\Services\FattureElettroniche\FatturaElettronicaImporter;
|
|
use App\Services\FattureElettroniche\FatturaElettronicaXmlParser;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Actions\Action;
|
|
use Filament\Forms\Components\FileUpload;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\Toggle;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Tables\Columns\BadgeColumn;
|
|
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\Storage;
|
|
use UnitEnum;
|
|
|
|
class FattureElettronicheArchivio extends Page implements HasTable
|
|
{
|
|
use InteractsWithTable;
|
|
|
|
protected static bool $shouldRegisterNavigation = false;
|
|
|
|
protected static ?string $navigationLabel = 'Fatture ricevute (XML)';
|
|
|
|
protected static ?string $title = 'Fatture ricevute (XML)';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-document-text';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Contabilità';
|
|
|
|
protected static ?int $navigationSort = 35;
|
|
|
|
protected static ?string $slug = 'contabilita/fatture-ricevute';
|
|
|
|
protected string $view = 'filament.pages.contabilita.fatture-elettroniche-archivio';
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
|
|
if (! $user instanceof User) {
|
|
return false;
|
|
}
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin'])) {
|
|
return true;
|
|
}
|
|
|
|
return $user->can('contabilita.fatture-elettroniche');
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->redirect(FattureElettronicheP7mRicevute::getUrl(panel: 'admin-filament'));
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
Action::make('importa_xml')
|
|
->label('Importa XML')
|
|
->icon('heroicon-o-arrow-up-tray')
|
|
->form([
|
|
Select::make('stabile_id')
|
|
->label('Stabile')
|
|
->helperText('Di default usa lo stabile attivo; puoi forzare qui.')
|
|
->options(function () {
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return [];
|
|
}
|
|
|
|
return StabileContext::accessibleStabili($user)
|
|
->mapWithKeys(fn(Stabile $s) => [(string) $s->id => $s->codice_stabile . ' - ' . $s->denominazione])
|
|
->all();
|
|
})
|
|
->searchable()
|
|
->nullable(),
|
|
|
|
FileUpload::make('xml_files')
|
|
->label('File XML')
|
|
->acceptedFileTypes(['text/xml', 'application/xml'])
|
|
->directory(function (): string {
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return 'tmp/fatture-xml';
|
|
}
|
|
|
|
$stabile = StabileContext::getActiveStabile($user);
|
|
$adminCode = $stabile?->amministratore?->codice_amministratore;
|
|
$adminId = (int) ($stabile?->amministratore_id ?: 0);
|
|
$adminFolder = $adminCode ?: ('ID-' . $adminId);
|
|
|
|
return 'amministratori/' . $adminFolder . '/temp/upload/fatture-xml';
|
|
})
|
|
->disk('local')
|
|
->multiple()
|
|
->required(),
|
|
|
|
Toggle::make('create_fornitore_if_missing')
|
|
->label('Crea fornitore se non esiste')
|
|
->helperText('Se il fornitore non viene trovato (P.IVA/CF), crea una nuova anagrafica fornitore collegata allo stabile.')
|
|
->default(true),
|
|
|
|
Toggle::make('force_update_duplicates')
|
|
->label('Aggiorna se già importata (repair)')
|
|
->helperText('Se il file è già presente, forza aggiornamento e ripara le righe contabili (es. Cassa Previdenziale/Bollo fuori da DettaglioLinee).')
|
|
->default(false),
|
|
])
|
|
->action(function (array $data): void {
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
Notification::make()->title('Utente non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$fallbackStabileId = (int) ($data['stabile_id'] ?: StabileContext::resolveActiveStabileId($user) ?: 0);
|
|
if ($fallbackStabileId <= 0) {
|
|
Notification::make()->title('Seleziona uno stabile')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$forceStabileId = 0;
|
|
if ($user->hasAnyRole(['super-admin', 'admin']) && ! empty($data['stabile_id'])) {
|
|
$forceStabileId = $fallbackStabileId;
|
|
}
|
|
|
|
$paths = $data['xml_files'] ?? [];
|
|
$paths = is_array($paths) ? $paths : [$paths];
|
|
|
|
$importer = new FatturaElettronicaImporter(new FatturaElettronicaXmlParser());
|
|
|
|
$imported = 0;
|
|
$duplicates = 0;
|
|
$errors = 0;
|
|
|
|
foreach ($paths as $path) {
|
|
try {
|
|
$xml = Storage::disk('local')->get($path);
|
|
$result = $importer->importXml($xml, $fallbackStabileId, basename((string) $path), [
|
|
'user_id' => (int) $user->id,
|
|
'force_stabile_id' => $forceStabileId,
|
|
'create_fornitore_if_missing' => (bool) ($data['create_fornitore_if_missing'] ?? false),
|
|
'force_update' => (bool) ($data['force_update_duplicates'] ?? false),
|
|
'repair_contabilita' => (bool) ($data['force_update_duplicates'] ?? false),
|
|
]);
|
|
|
|
if (($result['status'] ?? null) === 'imported') {
|
|
$imported++;
|
|
} elseif (($result['status'] ?? null) === 'duplicate') {
|
|
$duplicates++;
|
|
} else {
|
|
$errors++;
|
|
}
|
|
} catch (\Throwable) {
|
|
$errors++;
|
|
} finally {
|
|
try {
|
|
Storage::disk('local')->delete($path);
|
|
} catch (\Throwable) {
|
|
// ignore
|
|
}
|
|
}
|
|
}
|
|
|
|
Notification::make()
|
|
->title('Import completato')
|
|
->body("Importate: {$imported} · Duplicate: {$duplicates} · Errori: {$errors}")
|
|
->success()
|
|
->send();
|
|
}),
|
|
];
|
|
}
|
|
|
|
protected function getTableQuery(): Builder
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return FatturaElettronica::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
$activeStabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $activeStabileId) {
|
|
return FatturaElettronica::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
return FatturaElettronica::query()
|
|
->where('stabile_id', $activeStabileId)
|
|
->orderByDesc('data_fattura')
|
|
->orderByDesc('id');
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->striped()
|
|
->columns([
|
|
TextColumn::make('fornitore_denominazione')
|
|
->label('Fornitore')
|
|
->searchable()
|
|
->wrap(),
|
|
|
|
TextColumn::make('numero_fattura')
|
|
->label('Numero')
|
|
->searchable()
|
|
->sortable(),
|
|
|
|
TextColumn::make('data_fattura')
|
|
->label('Data')
|
|
->date('d/m/Y')
|
|
->sortable(),
|
|
|
|
TextColumn::make('totale')
|
|
->label('Totale')
|
|
->money('EUR')
|
|
->sortable(),
|
|
|
|
BadgeColumn::make('stato')
|
|
->label('Stato')
|
|
->colors([
|
|
'warning' => 'ricevuta',
|
|
'success' => 'pagata',
|
|
'primary' => 'contabilizzata',
|
|
'danger' => 'rifiutata',
|
|
]),
|
|
|
|
TextColumn::make('nome_file_xml')
|
|
->label('File')
|
|
->toggleable(isToggledHiddenByDefault: true)
|
|
->wrap(),
|
|
])
|
|
->actions([
|
|
Action::make('apri')
|
|
->label('Apri')
|
|
->icon('heroicon-o-eye')
|
|
->url(fn(FatturaElettronica $record) => FatturaElettronicaScheda::getUrl([
|
|
'record' => $record->id,
|
|
'back' => url()->current(),
|
|
], panel: 'admin-filament')),
|
|
]);
|
|
}
|
|
}
|