*/ private array $feExistsCache = []; /** @var array */ 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'); } }