394 lines
15 KiB
PHP
Executable File
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');
|
|
}
|
|
}
|