hasAnyRole(['super-admin', 'admin'])) { return true; } return $user->can('contabilita.voci-spesa'); } public function mount(int|string $record): void { $user = Auth::user(); if (! $user instanceof User) { abort(403); } $this->voce = VoceSpesa::query()->with('tabellaMillesimaleDefault')->findOrFail((int) $record); $stabileId = StabileContext::resolveActiveStabileId($user); if (! $stabileId || (int) $this->voce->stabile_id !== (int) $stabileId) { abort(404); } $gestione = request()->query('gestione'); $this->gestioneContabileId = is_numeric($gestione) ? (int) $gestione : (is_numeric($this->voce->gestione_contabile_id ?? null) ? (int) $this->voce->gestione_contabile_id : null); $this->mountInteractsWithTable(); } public function getBreadcrumbs(): array { return [ 'Contabilità' => null, 'Voci di spesa' => VociSpesaArchivio::getUrl(panel: 'admin-filament'), $this->getVoceLabel() => null, ]; } protected function getHeaderActions(): array { return [ Action::make('torna') ->label('Torna alle voci') ->icon('heroicon-o-arrow-left') ->url(VociSpesaArchivio::getUrl(panel: 'admin-filament')), ]; } /** @return array{totale: float, imponibile: float, iva: float, consumo: float, consumo_unita: string, fatture: int, gestione: string} */ public function getHeaderSummary(): array { $user = Auth::user(); if (! $user instanceof User) { return [ 'totale' => 0.0, 'imponibile' => 0.0, 'iva' => 0.0, 'consumo' => 0.0, 'consumo_unita' => '', 'fatture' => 0, 'gestione' => '—', ]; } $stabileId = StabileContext::resolveActiveStabileId($user); if (! $stabileId) { return [ 'totale' => 0.0, 'imponibile' => 0.0, 'iva' => 0.0, 'consumo' => 0.0, 'consumo_unita' => '', 'fatture' => 0, 'gestione' => '—', ]; } $righe = FatturaFornitoreRiga::query() ->join('contabilita_fatture_fornitori as cf', 'cf.id', '=', 'contabilita_fatture_fornitori_righe.fattura_id') ->where('contabilita_fatture_fornitori_righe.voce_spesa_id', (int) $this->voce->id) ->where('cf.stabile_id', $stabileId); $righe->whereNotNull('cf.registrazione_id'); if ($this->gestioneContabileId) { $gestioneId = (int) $this->gestioneContabileId; if (Schema::hasColumn('contabilita_fatture_fornitori_righe', 'gestione_id')) { $righe->where(function (Builder $q) use ($gestioneId) { $q->where('contabilita_fatture_fornitori_righe.gestione_id', $gestioneId) ->orWhere('cf.gestione_id', $gestioneId); }); } else { $righe->where('cf.gestione_id', $gestioneId); } } $totale = (float) $righe->sum('contabilita_fatture_fornitori_righe.totale_euro'); $imponibile = (float) $righe->sum('contabilita_fatture_fornitori_righe.imponibile_euro'); $iva = (float) $righe->sum('contabilita_fatture_fornitori_righe.iva_euro'); $fattureQuery = FatturaFornitore::query() ->where('contabilita_fatture_fornitori.stabile_id', $stabileId) ->whereNotNull('contabilita_fatture_fornitori.registrazione_id') ->whereHas('righe', fn (Builder $q) => $q->where('voce_spesa_id', (int) $this->voce->id)); if ($this->gestioneContabileId) { $fattureQuery->where('gestione_id', (int) $this->gestioneContabileId); } $fattureCount = (int) $fattureQuery->count(); $consumoQuery = (clone $fattureQuery) ->leftJoin('fatture_elettroniche as fe', 'fe.id', '=', 'contabilita_fatture_fornitori.fattura_elettronica_id'); $consumo = (float) $consumoQuery->sum('fe.consumo_valore'); $consumoUnita = (string) ($consumoQuery->whereNotNull('fe.consumo_unita')->value('fe.consumo_unita') ?? ''); $gestioneLabel = '—'; if ($this->gestioneContabileId) { $g = GestioneContabile::query()->select(['anno_gestione', 'tipo_gestione', 'denominazione', 'protocollo_prefix'])->find($this->gestioneContabileId); if ($g) { $gestioneLabel = trim((string) ($g->denominazione ?? '')); if ($gestioneLabel === '') { $gestioneLabel = (string) $g->anno_gestione . ' - ' . (string) $g->tipo_gestione; } $prefix = trim((string) ($g->protocollo_prefix ?? '')); if ($prefix !== '') { $gestioneLabel = $prefix . ' — ' . $gestioneLabel; } } } return [ 'totale' => round($totale, 2), 'imponibile' => round($imponibile, 2), 'iva' => round($iva, 2), 'consumo' => round($consumo, 3), 'consumo_unita' => $consumoUnita, 'fatture' => $fattureCount, 'gestione' => $gestioneLabel, ]; } public function table(Table $table): Table { return $table ->striped() ->paginated() ->paginationPageOptions([25, 50, 100]) ->query($this->getTableQuery()) ->columns([ TextColumn::make('fattura.data_documento') ->label('Data') ->getStateUsing(fn (FatturaFornitoreRiga $record) => optional($record->fattura?->data_documento)->format('d/m/Y') ?: '—') ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('fattura.numero_documento') ->label('Numero') ->getStateUsing(fn (FatturaFornitoreRiga $record) => (string) ($record->fattura?->numero_documento ?? '—')) ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('fattura.fornitore') ->label('Fornitore') ->getStateUsing(fn (FatturaFornitoreRiga $record) => $this->formatFornitoreLabel($record)) ->wrap() ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('descrizione') ->label('Descrizione riga') ->wrap() ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('imponibile_euro') ->label('Imponibile') ->formatStateUsing(fn ($state) => number_format((float) ($state ?? 0), 2, ',', '.')) ->alignRight() ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('iva_euro') ->label('IVA') ->formatStateUsing(fn ($state) => number_format((float) ($state ?? 0), 2, ',', '.')) ->alignRight() ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('totale_euro') ->label('Totale') ->formatStateUsing(fn ($state) => number_format((float) ($state ?? 0), 2, ',', '.')) ->alignRight() ->extraAttributes(['class' => 'text-[11px] font-semibold']), TextColumn::make('consumo') ->label('Consumo') ->getStateUsing(fn (FatturaFornitoreRiga $record) => $this->formatConsumoLabel($record)) ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('riferimento') ->label('Rif. consumo') ->getStateUsing(fn (FatturaFornitoreRiga $record) => $this->formatConsumoRiferimento($record)) ->extraAttributes(['class' => 'text-[11px]']), TextColumn::make('codici') ->label('Codici') ->getStateUsing(fn (FatturaFornitoreRiga $record) => $this->formatConsumoCodici($record)) ->wrap() ->extraAttributes(['class' => 'text-[11px]']), ]) ->actions([ Action::make('apri_fattura') ->label('Apri') ->icon('heroicon-o-arrow-top-right-on-square') ->url(fn (FatturaFornitoreRiga $record) => $record->fattura ? FatturaFornitoreScheda::getUrl(['record' => (int) $record->fattura->id], panel: 'admin-filament') : null) ->visible(fn (FatturaFornitoreRiga $record) => (bool) $record->fattura), ]); } protected function getTableQuery(): Builder { $user = Auth::user(); if (! $user instanceof User) { return FatturaFornitoreRiga::query()->whereRaw('1 = 0'); } $stabileId = StabileContext::resolveActiveStabileId($user); if (! $stabileId) { return FatturaFornitoreRiga::query()->whereRaw('1 = 0'); } $query = FatturaFornitoreRiga::query() ->where('voce_spesa_id', (int) $this->voce->id) ->whereHas('fattura', fn (Builder $q) => $q->where('stabile_id', $stabileId)->whereNotNull('registrazione_id')) ->with([ 'fattura.fornitore', 'fattura.gestione', 'fattura.fatturaElettronica', 'tabellaMillesimale', ]); if ($this->gestioneContabileId) { $gestioneId = (int) $this->gestioneContabileId; if (Schema::hasColumn('contabilita_fatture_fornitori_righe', 'gestione_id')) { $query->where(function (Builder $q) use ($gestioneId) { $q->where('gestione_id', $gestioneId) ->orWhereHas('fattura', fn (Builder $qq) => $qq->where('gestione_id', $gestioneId)); }); } else { $query->whereHas('fattura', fn (Builder $qq) => $qq->where('gestione_id', $gestioneId)); } } return $query; } private function getVoceLabel(): string { $code = trim((string) ($this->voce->codice ?? '')); $desc = trim((string) ($this->voce->descrizione ?? '')); if ($code !== '' && $desc !== '') { return $code . ' — ' . $desc; } return $desc !== '' ? $desc : ('Voce #' . (int) $this->voce->id); } private function formatFornitoreLabel(FatturaFornitoreRiga $record): string { $f = $record->fattura?->fornitore; if (! $f) { return '—'; } $ragione = trim((string) ($f->ragione_sociale ?? '')); if ($ragione !== '') { return $ragione; } $nome = trim((string) ($f->nome ?? '')); $cognome = trim((string) ($f->cognome ?? '')); $full = trim($nome . ' ' . $cognome); if ($full !== '') { return $full; } $code = trim((string) ($f->codice_univoco ?? '')); return $code !== '' ? $code : ('Fornitore #' . (int) $f->id); } private function formatConsumoLabel(FatturaFornitoreRiga $record): string { $fe = $record->fattura?->fatturaElettronica; if (! $fe) { return '—'; } if (! is_numeric($fe->consumo_valore ?? null)) { return '—'; } $unit = trim((string) ($fe->consumo_unita ?? '')); $value = number_format((float) $fe->consumo_valore, 3, ',', '.'); return $unit !== '' ? ($value . ' ' . $unit) : $value; } private function formatConsumoRiferimento(FatturaFornitoreRiga $record): string { $fe = $record->fattura?->fatturaElettronica; $ref = is_string($fe?->consumo_riferimento ?? null) ? trim((string) $fe->consumo_riferimento) : ''; return $ref !== '' ? $ref : '—'; } private function formatConsumoCodici(FatturaFornitoreRiga $record): string { $fe = $record->fattura?->fatturaElettronica; $raw = is_string($fe?->consumo_raw ?? null) ? trim((string) $fe->consumo_raw) : ''; if ($raw === '') { return '—'; } $data = json_decode($raw, true); if (! is_array($data)) { return '—'; } $codici = is_array($data['codici'] ?? null) ? $data['codici'] : []; $contatore = is_array($data['contatore'] ?? null) ? $data['contatore'] : []; $parts = []; $utenza = trim((string) ($codici['utenza'] ?? '')); if ($utenza !== '') { $parts[] = 'Utenza: ' . $utenza; } $cliente = trim((string) ($codici['cliente'] ?? '')); if ($cliente !== '') { $parts[] = 'Cliente: ' . $cliente; } $contratto = trim((string) ($codici['contratto'] ?? '')); if ($contratto !== '') { $parts[] = 'Contratto: ' . $contratto; } $matricola = trim((string) ($contatore['matricola'] ?? '')); if ($matricola !== '') { $parts[] = 'Contatore: ' . $matricola; } return $parts === [] ? '—' : implode(' · ', $parts); } }