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; } }