362 lines
15 KiB
PHP
Executable File
362 lines
15 KiB
PHP
Executable File
<?php
|
|
namespace App\Filament\Pages\Gescon;
|
|
|
|
use App\Models\GestioneContabile;
|
|
use App\Models\User;
|
|
use App\Support\GestioneVisibility;
|
|
use App\Support\ModuleVisibility;
|
|
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\Filter;
|
|
use Filament\Tables\Filters\SelectFilter;
|
|
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
|
|
{
|
|
return ModuleVisibility::canAccessGesconInternal(Auth::user());
|
|
}
|
|
|
|
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');
|
|
}),
|
|
Filter::make('mostra_storico_nascosto')
|
|
->label('Mostra storico nascosto')
|
|
->default(false)
|
|
->query(function (Builder $query, array $data): Builder {
|
|
if ((bool) ($data['mostra_storico_nascosto'] ?? false)) {
|
|
return $query;
|
|
}
|
|
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return $query;
|
|
}
|
|
|
|
$activeStabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $activeStabileId) {
|
|
return $query;
|
|
}
|
|
|
|
$fallbackYear = (int) date('Y');
|
|
$visibleYears = GestioneVisibility::policyForStabile((int) $activeStabileId, $fallbackYear)['visible_years'] ?? [];
|
|
|
|
return $visibleYears !== []
|
|
? $query->whereIn('anno_gestione', array_map('intval', $visibleYears))
|
|
: $query;
|
|
}),
|
|
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)),
|
|
]);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|