netgescon-day0/app/Livewire/Contabilita/StgFattureAdeTable.php

394 lines
15 KiB
PHP
Executable File

<?php
namespace App\Livewire\Contabilita;
use App\Models\FatturaElettronica;
use App\Models\Stabile;
use App\Models\StgFatturaAde;
use App\Models\User;
use App\Support\StabileContext;
use Filament\Support\Contracts\TranslatableContentDriver;
use Filament\Actions\Action;
use Filament\Actions\BulkAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Filament\Tables\TableComponent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Filament\Notifications\Notification;
class StgFattureAdeTable extends TableComponent
{
/** @var array<string, bool> */
private array $feExistsCache = [];
/** @var array<string, bool> */
private array $contabilizzataCache = [];
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
$user = Auth::user();
if (! $user instanceof User) {
return StgFatturaAde::query()->whereRaw('1 = 0');
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return StgFatturaAde::query()->whereRaw('1 = 0');
}
$stabile = Stabile::query()->select(['id', 'amministratore_id'])->find($activeStabileId);
$amministratoreId = (int) ($stabile?->amministratore_id ?: 0);
if ($amministratoreId <= 0) {
return StgFatturaAde::query()->whereRaw('1 = 0');
}
return StgFatturaAde::query()
->where('amministratore_id', $amministratoreId)
->where(function (Builder $q) use ($activeStabileId): void {
$q->where('stabile_id', $activeStabileId)
->orWhereNull('stabile_id');
})
->orderByDesc('data_emissione')
->orderByDesc('id');
}
public function table(Table $table): Table
{
return $table
->striped()
->columns([
IconColumn::make('fe_presente')
->label('FE')
->boolean()
->getStateUsing(fn(StgFatturaAde $record): bool => $this->existsFeForStg($record)),
IconColumn::make('contabilizzata')
->label('Contab.')
->boolean()
->getStateUsing(fn(StgFatturaAde $record): bool => $this->isContabilizzataForStg($record)),
TextColumn::make('data_emissione')
->label('Data')
->date('d/m/Y')
->sortable(),
TextColumn::make('numero_documento')
->label('Numero')
->searchable()
->sortable(),
TextColumn::make('denominazione_fornitore')
->label('Fornitore')
->searchable()
->wrap(),
TextColumn::make('imponibile')
->label('Imponibile')
->money('EUR')
->sortable(),
TextColumn::make('imposta')
->label('Imposta')
->money('EUR')
->sortable(),
TextColumn::make('sdi_file')
->label('Sdi/file')
->searchable()
->toggleable(isToggledHiddenByDefault: true)
->wrap(),
TextColumn::make('cartella_legacy')
->label('Cartella')
->toggleable(isToggledHiddenByDefault: true)
->wrap(),
TextColumn::make('source_file')
->label('Source')
->toggleable(isToggledHiddenByDefault: true)
->wrap(),
])
->filters([
SelectFilter::make('anno')
->label('Anno')
->options(function (): array {
$years = $this->getTableQuery()
->reorder()
->whereNotNull('data_emissione')
->selectRaw('YEAR(data_emissione) as y')
->distinct()
->orderByDesc('y')
->pluck('y')
->filter(fn($v) => $v !== null && $v !== '')
->map(fn($v) => (string) $v)
->all();
return array_combine($years, $years) ?: [];
})
->query(function (Builder $query, array $data): Builder {
$year = trim((string) ($data['value'] ?? ''));
if ($year === '') {
return $query;
}
return $query->whereYear('data_emissione', (int) $year);
}),
SelectFilter::make('trimestre')
->label('Trimestre')
->options([
'Q1' => 'Q1 (01/01 - 31/03)',
'Q2' => 'Q2 (01/04 - 30/06)',
'Q3' => 'Q3 (01/07 - 30/09)',
'Q4' => 'Q4 (01/10 - 31/12)',
])
->query(function (Builder $query, array $data): Builder {
$q = (string) ($data['value'] ?? '');
[$mFrom, $mTo] = match ($q) {
'Q1' => [1, 3],
'Q2' => [4, 6],
'Q3' => [7, 9],
'Q4' => [10, 12],
default => [0, 0],
};
if ($mFrom === 0) {
return $query;
}
return $query
->whereMonth('data_emissione', '>=', $mFrom)
->whereMonth('data_emissione', '<=', $mTo);
}),
])
->headerActions([
Action::make('svuota_lista_ade')
->label('Svuota Lista AdE')
->icon('heroicon-o-trash')
->color('danger')
->requiresConfirmation()
->action(function (): void {
$user = Auth::user();
if (! $user instanceof User) {
Notification::make()->title('Utente non valido')->danger()->send();
return;
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
Notification::make()->title('Stabile non selezionato')->warning()->send();
return;
}
$stabile = Stabile::query()->select(['id', 'amministratore_id'])->find($activeStabileId);
$amministratoreId = (int) ($stabile?->amministratore_id ?: 0);
if ($amministratoreId <= 0) {
Notification::make()->title('Amministratore non valido')->danger()->send();
return;
}
$deleted = StgFatturaAde::query()
->where('amministratore_id', $amministratoreId)
->where(function (Builder $q) use ($activeStabileId): void {
$q->where('stabile_id', $activeStabileId)->orWhereNull('stabile_id');
})
->delete();
Notification::make()
->title('Lista AdE svuotata')
->body('Eliminati ' . (int) $deleted . ' record.')
->success()
->send();
}),
])
->bulkActions([
BulkAction::make('elimina_selezionati')
->label('Elimina selezionati')
->icon('heroicon-o-trash')
->color('danger')
->requiresConfirmation()
->deselectRecordsAfterCompletion()
->action(function (Collection $records): void {
$count = 0;
foreach ($records as $record) {
if ($record instanceof StgFatturaAde) {
$record->delete();
$count++;
}
}
Notification::make()
->title('Record eliminati')
->body('Eliminati ' . $count . ' record dalla Lista AdE.')
->success()
->send();
}),
]);
}
public function makeFilamentTranslatableContentDriver(): ?TranslatableContentDriver
{
return null;
}
private function existsFeForStg(StgFatturaAde $record): bool
{
$key = implode('|', [
(string) ($record->stabile_id ?? '0'),
(string) ($record->sdi_file ?? ''),
(string) ($record->numero_documento ?? ''),
(string) ($record->data_emissione?->format('Y-m-d') ?? ''),
(string) ($record->identificativo_fornitore ?? ''),
]);
if (array_key_exists($key, $this->feExistsCache)) {
return $this->feExistsCache[$key];
}
$user = Auth::user();
if (! $user instanceof User) {
return $this->feExistsCache[$key] = false;
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return $this->feExistsCache[$key] = false;
}
$sdi = trim((string) ($record->sdi_file ?? ''));
if ($sdi !== '') {
if (FatturaElettronica::query()->where('stabile_id', $activeStabileId)->where('sdi_file', $sdi)->exists()) {
return $this->feExistsCache[$key] = true;
}
// Fallback legacy (prima dell'introduzione di sdi_file): match su nome file.
$existsByFilename = FatturaElettronica::query()
->where('stabile_id', $activeStabileId)
->where(function (Builder $qq) use ($sdi): void {
$qq->where('nome_file_xml', 'like', '%' . $sdi . '%')
->orWhere('nome_file_p7m', 'like', '%' . $sdi . '%');
})
->exists();
if ($existsByFilename) {
return $this->feExistsCache[$key] = true;
}
}
$numero = trim((string) ($record->numero_documento ?? ''));
$data = $record->data_emissione;
$idForn = strtoupper(trim((string) ($record->identificativo_fornitore ?? '')));
if ($numero !== '' && $data && $idForn !== '') {
$exists = FatturaElettronica::query()
->where('stabile_id', $activeStabileId)
->whereDate('data_fattura', $data)
->where('numero_fattura', $numero)
->where(function (Builder $qq) use ($idForn): void {
$qq->whereRaw("REPLACE(UPPER(fornitore_piva), ' ', '') = ?", [str_replace(' ', '', $idForn)])
->orWhereRaw("REPLACE(UPPER(fornitore_cf), ' ', '') = ?", [str_replace(' ', '', $idForn)]);
})
->exists();
return $this->feExistsCache[$key] = $exists;
}
return $this->feExistsCache[$key] = false;
}
private function isContabilizzataForStg(StgFatturaAde $record): bool
{
$key = implode('|', [
(string) ($record->stabile_id ?? '0'),
(string) ($record->sdi_file ?? ''),
(string) ($record->numero_documento ?? ''),
(string) ($record->data_emissione?->format('Y-m-d') ?? ''),
(string) ($record->identificativo_fornitore ?? ''),
]);
if (array_key_exists($key, $this->contabilizzataCache)) {
return $this->contabilizzataCache[$key];
}
$user = Auth::user();
if (! $user instanceof User) {
return $this->contabilizzataCache[$key] = false;
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return $this->contabilizzataCache[$key] = false;
}
// Match preferenziale su SDI/file (se presente) e fallback sui dati documento.
$sdi = trim((string) ($record->sdi_file ?? ''));
if ($sdi !== '') {
$exists = FatturaElettronica::query()
->where('stabile_id', $activeStabileId)
->where('sdi_file', $sdi)
->where(function (Builder $qq): void {
$qq->whereNotNull('registrazione_contabile_id')
->orWhere('stato', 'contabilizzata');
})
->exists();
if ($exists) {
return $this->contabilizzataCache[$key] = true;
}
// Fallback legacy: match su nome file.
$existsByFilename = FatturaElettronica::query()
->where('stabile_id', $activeStabileId)
->where(function (Builder $qq) use ($sdi): void {
$qq->where('nome_file_xml', 'like', '%' . $sdi . '%')
->orWhere('nome_file_p7m', 'like', '%' . $sdi . '%');
})
->where(function (Builder $qq): void {
$qq->whereNotNull('registrazione_contabile_id')
->orWhere('stato', 'contabilizzata');
})
->exists();
if ($existsByFilename) {
return $this->contabilizzataCache[$key] = true;
}
}
$numero = trim((string) ($record->numero_documento ?? ''));
$data = $record->data_emissione;
$idForn = strtoupper(trim((string) ($record->identificativo_fornitore ?? '')));
if ($numero !== '' && $data && $idForn !== '') {
$exists = FatturaElettronica::query()
->where('stabile_id', $activeStabileId)
->whereDate('data_fattura', $data)
->where('numero_fattura', $numero)
->where(function (Builder $qq) use ($idForn): void {
$qq->whereRaw("REPLACE(UPPER(fornitore_piva), ' ', '') = ?", [str_replace(' ', '', $idForn)])
->orWhereRaw("REPLACE(UPPER(fornitore_cf), ' ', '') = ?", [str_replace(' ', '', $idForn)]);
})
->where(function (Builder $qq): void {
$qq->whereNotNull('registrazione_contabile_id')
->orWhere('stato', 'contabilizzata');
})
->exists();
return $this->contabilizzataCache[$key] = $exists;
}
return $this->contabilizzataCache[$key] = false;
}
public function render()
{
return view('livewire.contabilita.stg-fatture-ade-table');
}
}