netgescon-day0/app/Filament/Pages/Contabilita/VoceSpesaMastrino.php

392 lines
14 KiB
PHP

<?php
namespace App\Filament\Pages\Contabilita;
use App\Models\GestioneContabile;
use App\Models\User;
use App\Models\VoceSpesa;
use App\Modules\Contabilita\Models\FatturaFornitore;
use App\Modules\Contabilita\Models\FatturaFornitoreRiga;
use App\Support\StabileContext;
use Filament\Actions\Action;
use Filament\Pages\Page;
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\Schema;
class VoceSpesaMastrino extends Page implements HasTable
{
use InteractsWithTable;
protected static ?string $title = 'Mastrino voce di spesa';
protected static ?string $slug = 'contabilita/voci-spesa/mastrino/{record}';
protected static bool $shouldRegisterNavigation = false;
protected string $view = 'filament.pages.contabilita.voce-spesa-mastrino';
public VoceSpesa $voce;
public ?int $gestioneContabileId = null;
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.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);
}
}