netgescon-day0/app/Filament/Pages/Contabilita/Components/RateEmesseEmissioniTable.php

236 lines
8.5 KiB
PHP

<?php
namespace App\Filament\Pages\Contabilita\Components;
use App\Filament\Pages\Contabilita\RateEmesseArchivio;
use App\Models\GesconImport\RateEmissione;
use App\Models\RataEmessaNg;
use App\Models\User;
use App\Support\StabileContext;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions as HasActionsContract;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Support\Contracts\TranslatableContentDriver;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class RateEmesseEmissioniTable extends Component implements HasActionsContract, HasForms, HasTable
{
use InteractsWithTable;
use InteractsWithActions;
use InteractsWithForms;
/** @var array<int, array{count:int, total:float}> */
protected array $emissionStatsCache = [];
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
$user = Auth::user();
if (! $user instanceof User) {
return RateEmissione::query()->whereRaw('1 = 0');
}
$stabile = StabileContext::getActiveStabile($user);
$codStabile = $stabile?->codice_stabile ?? $stabile?->cod_stabile;
if (! $codStabile) {
return RateEmissione::query()->whereRaw('1 = 0');
}
return RateEmissione::query()
->where('cod_stabile', (string) $codStabile)
->orderBy('numero_emissione')
->orderBy('data_emissione');
}
public function table(Table $table): Table
{
return $table
->striped()
->paginated()
->paginationPageOptions([10, 25, 50, 100])
->defaultPaginationPageOption(10)
->recordUrl(function (RateEmissione $record): string {
return RateEmesseArchivio::getUrl(
panel: 'admin-filament',
parameters: [
'tab' => 'dettaglio',
'emissione_gen' => $record->id,
],
);
})
->filters([
SelectFilter::make('anno_emissione')
->label('Gestione')
->options(function (): array {
$user = Auth::user();
if (! $user instanceof User) {
return [];
}
$stabile = StabileContext::getActiveStabile($user);
$codStabile = $stabile?->codice_stabile ?? $stabile?->cod_stabile;
if (! $codStabile) {
return [];
}
return RateEmissione::query()
->where('cod_stabile', (string) $codStabile)
->whereNotNull('anno_emissione')
->select('anno_emissione')
->distinct()
->orderByDesc('anno_emissione')
->pluck('anno_emissione', 'anno_emissione')
->all();
})
->query(function (Builder $query, array $data): Builder {
$anno = $data['value'] ?? null;
if (blank($anno)) {
return $query;
}
return $query->where('anno_emissione', (string) $anno);
}),
])
->columns([
TextColumn::make('data_emissione')
->label('Emissione')
->date('d/m/Y')
->url(function (RateEmissione $record): string {
return RateEmesseArchivio::getUrl(
panel: 'admin-filament',
parameters: [
'tab' => 'dettaglio',
'emissione_gen' => $record->id,
],
);
})
->sortable(),
TextColumn::make('data_scadenza')
->label('Scadenza')
->date('d/m/Y')
->sortable(),
TextColumn::make('numero_emissione')
->label('N. Emissione')
->sortable(),
TextColumn::make('anno_emissione')
->label('Gestione')
->sortable(),
TextColumn::make('descrizione')
->label('Descrizione')
->wrap()
->searchable(),
TextColumn::make('numero_rate')
->label('N. rate')
->alignRight()
->state(function (RateEmissione $record): int {
$n = (int) ($record->numero_rate ?? 0);
return $n > 0 ? $n : $this->getEmissionStats($record)['count'];
}),
TextColumn::make('totale_rate')
->label('Totale')
->alignRight()
->money('EUR', locale: 'it')
->state(fn(RateEmissione $record): float => $this->getEmissionStats($record)['total']),
TextColumn::make('gestione_tipo')
->label('Gestione')
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('gestione_periodo')
->label('Periodo')
->wrap()
->toggleable(isToggledHiddenByDefault: true),
])
->defaultSort('numero_emissione', 'asc');
}
/**
* Statistiche su righe rate NG (rate_emesse) collegate all'emissione tramite (data_emissione, data_scadenza).
* Cache per evitare doppie query durante il rendering delle colonne.
*
* @return array{count:int, total:float}
*/
protected function getEmissionStats(RateEmissione $record): array
{
$id = (int) $record->getKey();
if (isset($this->emissionStatsCache[$id])) {
return $this->emissionStatsCache[$id];
}
$user = Auth::user();
if (! $user instanceof User) {
return $this->emissionStatsCache[$id] = ['count' => 0, 'total' => 0.0];
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return $this->emissionStatsCache[$id] = ['count' => 0, 'total' => 0.0];
}
$q = RataEmessaNg::query()
->whereHas('pianoRateizzazione', fn(Builder $sub) => $sub->where('stabile_id', (int) $activeStabileId));
// Preferisci match per numero emissione e anno (tracciati nelle note durante import EMES_DET).
// Le date possono coincidere tra emissioni diverse.
$numeroEmissione = (int) ($record->numero_emissione ?? 0);
if ($numeroEmissione > 0) {
$q->whereRaw(
"SUBSTRING_INDEX(SUBSTRING_INDEX(note, 'n_emissione=', -1), '|', 1) = ?",
[(string) $numeroEmissione]
);
$anno = trim((string) ($record->anno_emissione ?? ''));
if ($anno !== '') {
$q->whereRaw(
"SUBSTRING_INDEX(SUBSTRING_INDEX(note, 'anno_emissione=', -1), '|', 1) = ?",
[$anno]
);
}
} else {
if ($record->data_emissione) {
$q->whereDate('data_emissione', $record->data_emissione);
}
if ($record->data_scadenza) {
$q->whereDate('data_scadenza', $record->data_scadenza);
}
}
$row = $q
->selectRaw('COUNT(*) AS c, COALESCE(SUM(importo_addebitato_soggetto), 0) AS t')
->first();
return $this->emissionStatsCache[$id] = [
'count' => (int) ($row?->c ?? 0),
'total' => (float) ($row?->t ?? 0),
];
}
public function render()
{
return view('filament.pages.contabilita.components.rate-emesse-emissioni-table');
}
public function makeFilamentTranslatableContentDriver(): ?TranslatableContentDriver
{
return null;
}
}