netgescon-day0/app/Filament/Pages/Gescon/GestioniArchivio.php

338 lines
14 KiB
PHP

<?php
namespace App\Filament\Pages\Gescon;
use App\Models\GestioneContabile;
use App\Models\User;
use App\Support\StabileContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use UnitEnum;
class GestioniArchivio extends Page implements HasTable
{
use InteractsWithTable;
protected static ?string $navigationLabel = 'Gestioni (archivio)';
protected static ?string $title = 'Gestioni (archivio NetGescon)';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-calendar-days';
protected static UnitEnum|string|null $navigationGroup = 'GESCON';
protected static ?int $navigationSort = 13;
protected static ?string $slug = 'gescon/anagrafica/gestioni';
protected string $view = 'filament.pages.gescon.table';
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
}
public function mount(): void
{
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
$user = Auth::user();
if (! $user instanceof User) {
return GestioneContabile::query()->whereRaw('1 = 0');
}
$activeStabileId = StabileContext::resolveActiveStabileId($user);
if (! $activeStabileId) {
return GestioneContabile::query()->whereRaw('1 = 0');
}
return GestioneContabile::query()
->where('stabile_id', $activeStabileId);
}
public function table(Table $table): Table
{
return $table
->striped()
->defaultSort('anno_gestione', 'desc')
->paginationPageOptions([25, 50, 100, 250])
->defaultPaginationPageOption(100)
->headerActions([
Action::make('pulizia_gestioni')
->label('Pulizia gestioni')
->icon('heroicon-o-trash')
->color('warning')
->requiresConfirmation()
->modalHeading('Pulizia gestioni duplicate')
->modalDescription('Rimuove i duplicati senza movimenti collegati e riallinea date/denominazioni. I record con movimenti non vengono eliminati.')
->action(function (): void {
$user = Auth::user();
if (! $user instanceof User) {
return;
}
$stabileId = StabileContext::resolveActiveStabileId($user);
if (! $stabileId) {
return;
}
$gestioni = GestioneContabile::query()
->where('stabile_id', $stabileId)
->orderBy('anno_gestione')
->orderBy('tipo_gestione')
->orderBy('numero_straordinaria')
->orderBy('id')
->get();
$removed = 0;
$updated = 0;
DB::transaction(function () use ($gestioni, &$removed, &$updated): void {
$groups = $gestioni->groupBy(function (GestioneContabile $g): string {
return implode('|', [
$g->stabile_id,
$g->anno_gestione,
$g->tipo_gestione,
$g->numero_straordinaria ?? 0,
]);
});
foreach ($groups as $group) {
if ($group->count() < 2) {
$g = $group->first();
if ($g && $this->fixGestioneDefaults($g)) {
$updated++;
}
continue;
}
$ranked = $group->map(function (GestioneContabile $g): array {
$score = $g->operazioni()->count()
+ $g->incassi()->count()
+ $g->ritenuteAcconto()->count()
+ $g->incassiEstrattoConto()->count();
return ['gestione' => $g, 'score' => $score];
})->sortByDesc('score')->values();
$keep = $ranked->first()['gestione'] ?? $group->first();
if ($keep && $this->fixGestioneDefaults($keep)) {
$updated++;
}
foreach ($ranked as $item) {
$g = $item['gestione'];
if ($g->getKey() === $keep->getKey()) {
continue;
}
if ($item['score'] > 0) {
if ($this->fixGestioneDefaults($g)) {
$updated++;
}
continue;
}
$g->delete();
$removed++;
}
}
});
Notification::make()
->title('Pulizia completata')
->body("Rimossi duplicati: {$removed}. Gestioni riallineate: {$updated}.")
->success()
->send();
}),
])
->filters([
Filter::make('mostra_riscaldamento')
->label('Mostra riscaldamento')
->default(false)
->query(function (Builder $query, array $data): Builder {
$state = (bool) ($data['mostra_riscaldamento'] ?? false);
return $state ? $query : $query->where('tipo_gestione', '!=', 'riscaldamento');
}),
SelectFilter::make('tipo_gestione')
->label('Tipo')
->options([
'ordinaria' => 'Ordinaria',
'riscaldamento' => 'Riscaldamento',
'straordinaria' => 'Straordinaria',
]),
])
->columns([
TextColumn::make('anno_gestione')
->label('Anno')
->sortable(),
TextColumn::make('tipo_gestione')
->label('Tipo')
->sortable(),
TextColumn::make('numero_straordinaria')
->label('N° Straord.')
->sortable()
->toggleable(isToggledHiddenByDefault: false),
TextColumn::make('denominazione')
->label('Denominazione')
->searchable()
->wrap(),
TextColumn::make('stato')
->label('Stato')
->sortable(),
TextColumn::make('data_inizio')
->label('Dal')
->date('d/m/Y')
->sortable(),
TextColumn::make('data_fine')
->label('Al')
->date('d/m/Y')
->sortable(),
IconColumn::make('gestione_attiva')
->label('Attiva')
->boolean(),
TextColumn::make('mesi_rate')
->label('Mesi rate')
->getStateUsing(function (GestioneContabile $record): string {
$mesi = match ($record->tipo_gestione) {
'ordinaria' => (array) ($record->mesi_rate_ordinaria ?? []),
'riscaldamento' => (array) ($record->mesi_rate_riscaldamento ?? []),
'straordinaria' => (array) ($record->mesi_rate_straordinaria ?? []),
default => [],
};
$mesi = array_values(array_unique(array_map('intval', $mesi)));
sort($mesi);
return $mesi ? implode(', ', $mesi) : '—';
})
->wrap(),
])
->actions([
Action::make('imposta_mesi_rate')
->label('Mesi rate')
->icon('heroicon-o-calendar')
->modalHeading('Imposta mesi emissione rate')
->fillForm(function (GestioneContabile $record): array {
$mesi = match ($record->tipo_gestione) {
'ordinaria' => (array) ($record->mesi_rate_ordinaria ?? []),
'riscaldamento' => (array) ($record->mesi_rate_riscaldamento ?? []),
'straordinaria' => (array) ($record->mesi_rate_straordinaria ?? []),
default => [],
};
$mesi = array_values(array_unique(array_map('intval', $mesi)));
sort($mesi);
return [
'mesi' => $mesi,
'replica_tutti_anni' => true,
];
})
->form([
CheckboxList::make('mesi')
->label('Mesi in cui emettere le rate')
->options([
1 => 'Gen',
2 => 'Feb',
3 => 'Mar',
4 => 'Apr',
5 => 'Mag',
6 => 'Giu',
7 => 'Lug',
8 => 'Ago',
9 => 'Set',
10 => 'Ott',
11 => 'Nov',
12 => 'Dic',
])
->columns(6)
->required(),
Toggle::make('replica_tutti_anni')
->label('Replica questi mesi su tutti gli anni (stesso tipo)')
->default(true),
])
->action(function (GestioneContabile $record, array $data): void {
$mesi = array_values(array_unique(array_map('intval', (array) ($data['mesi'] ?? []))));
sort($mesi);
$field = match ($record->tipo_gestione) {
'ordinaria' => 'mesi_rate_ordinaria',
'riscaldamento' => 'mesi_rate_riscaldamento',
'straordinaria' => 'mesi_rate_straordinaria',
default => 'mesi_rate_ordinaria',
};
$query = GestioneContabile::query()
->where('stabile_id', $record->stabile_id)
->where('tipo_gestione', $record->tipo_gestione);
if (empty($data['replica_tutti_anni'])) {
$query->whereKey($record->getKey());
}
$query->each(function (GestioneContabile $g) use ($field, $mesi): void {
$g->{$field} = $mesi;
$g->save();
});
}),
Action::make('apri_stabile_classica')
->label('Apri stabile (UI classica)')
->icon('heroicon-o-arrow-top-right-on-square')
->url(fn(GestioneContabile $record) => route('admin.stabili.show', $record->stabile_id), shouldOpenInNewTab: true),
]);
}
private function fixGestioneDefaults(GestioneContabile $g): bool
{
$changed = false;
if (empty($g->denominazione)) {
$g->denominazione = 'Gestione ' . $g->anno_gestione . ' ' . ($g->tipo_gestione ?? 'ordinaria');
$changed = true;
}
$anno = (int) $g->anno_gestione;
if ($anno > 0) {
$start = sprintf('%d-01-01', $anno);
$end = sprintf('%d-12-31', $anno);
if (empty($g->data_inizio) || $g->data_inizio->format('Y-m-d') !== $start) {
$g->data_inizio = $start;
$changed = true;
}
if (empty($g->data_fine) || $g->data_fine->format('Y-m-d') !== $end) {
$g->data_fine = $end;
$changed = true;
}
}
if ($changed) {
$g->save();
}
return $changed;
}
}