392 lines
14 KiB
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);
|
|
}
|
|
} |