704 lines
26 KiB
PHP
704 lines
26 KiB
PHP
<?php
|
|
namespace App\Filament\Pages\Contabilita;
|
|
|
|
use App\Models\DatiBancari;
|
|
use App\Models\DocumentoStabile;
|
|
use App\Models\GestioneContabile;
|
|
use App\Models\Stabile;
|
|
use App\Models\User;
|
|
use App\Modules\Contabilita\Models\MovimentoBanca;
|
|
use App\Modules\Contabilita\Models\SaldoConto;
|
|
use App\Services\Contabilita\ExcelMovimentiParser;
|
|
use App\Services\Contabilita\IntesaCsvParser;
|
|
use App\Services\Contabilita\MovimentiBancaImporter;
|
|
use App\Services\Contabilita\UnicreditWriParser;
|
|
use App\Support\AnnoGestioneContext;
|
|
use App\Support\GestioneContext;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Actions\Action;
|
|
use Filament\Forms\Components\DatePicker;
|
|
use Filament\Forms\Components\FileUpload;
|
|
use Filament\Forms\Components\Repeater;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\Textarea;
|
|
use Filament\Forms\Components\TextInput;
|
|
use Filament\Forms\Components\Toggle;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Concerns\InteractsWithTable;
|
|
use Filament\Tables\Contracts\HasTable;
|
|
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 Illuminate\Support\Facades\Storage;
|
|
use UnitEnum;
|
|
|
|
class CasseBancheRiepilogo extends Page implements HasTable
|
|
{
|
|
use InteractsWithTable;
|
|
|
|
protected static ?bool $supportsWindowFunctions = null;
|
|
|
|
protected static ?string $navigationLabel = 'Casse e banche';
|
|
|
|
protected static ?string $title = 'Casse e banche';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-banknotes';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Contabilità';
|
|
|
|
protected static ?int $navigationSort = 10;
|
|
|
|
protected static ?string $slug = 'contabilita/casse-banche';
|
|
|
|
protected string $view = 'filament.pages.contabilita.casse-banche-riepilogo';
|
|
|
|
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.casse-banche');
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->mountInteractsWithTable();
|
|
}
|
|
|
|
public function getActiveStabile(): ?Stabile
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
return StabileContext::getActiveStabile($user);
|
|
}
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
Action::make('importa_unicredit_wri')
|
|
->label('Importa estratto (Unicredit WRI)')
|
|
->icon('heroicon-o-arrow-up-tray')
|
|
->modalWidth('7xl')
|
|
->form([
|
|
Select::make('iban')
|
|
->label('Conto (IBAN)')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn(): array=> $this->getIbanOptions())
|
|
->helperText('Opzionale: se non selezionato, l\'import prova a rilevare il conto dai dati.'),
|
|
|
|
Select::make('gestione_id')
|
|
->label('Gestione (opzionale)')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn(): array=> $this->getGestioniOptions())
|
|
->default(fn(): ?string => $this->resolveDefaultGestioneId()),
|
|
|
|
FileUpload::make('file')
|
|
->label('File estratto')
|
|
->directory('tmp/banca')
|
|
->disk('local')
|
|
->required(),
|
|
|
|
Toggle::make('replace')
|
|
->label('Sostituisci import nel periodo (consigliato se hai già importato con valori “slittati”)')
|
|
->helperText('Elimina SOLO i movimenti importati e NON riconciliati (registrazione vuota) per lo stesso conto e per l\'intervallo date del file, poi reimporta.')
|
|
->default(false),
|
|
])
|
|
->action(function (array $data): void {
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
Notification::make()->title('Utente non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
Notification::make()->title('Seleziona uno stabile')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$path = (string) ($data['file'] ?? '');
|
|
if ($path === '') {
|
|
Notification::make()->title('Seleziona un file')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$content = Storage::disk('local')->get($path);
|
|
$importer = new MovimentiBancaImporter(new UnicreditWriParser(), new IntesaCsvParser(), new ExcelMovimentiParser());
|
|
$res = $importer->importUnicreditWri(
|
|
$content,
|
|
$stabileId,
|
|
basename($path),
|
|
isset($data['iban']) && is_string($data['iban']) && trim($data['iban']) !== '' ? trim((string) $data['iban']) : null,
|
|
isset($data['gestione_id']) && is_numeric($data['gestione_id']) ? (int) $data['gestione_id'] : null,
|
|
isset($data['replace']) ? (bool) $data['replace'] : false,
|
|
);
|
|
|
|
Notification::make()
|
|
->title('Import completato')
|
|
->body('Importati: ' . ($res['imported'] ?? 0) . ' · Duplicati: ' . ($res['duplicates'] ?? 0))
|
|
->success()
|
|
->send();
|
|
} catch (\Throwable $e) {
|
|
Notification::make()->title('Errore import')->body($e->getMessage())->danger()->send();
|
|
} finally {
|
|
try {
|
|
Storage::disk('local')->delete($path);
|
|
} catch (\Throwable) {
|
|
// ignore
|
|
}
|
|
}
|
|
}),
|
|
|
|
Action::make('inserisci_saldi')
|
|
->label('Inserisci saldi (periodo)')
|
|
->icon('heroicon-o-scale')
|
|
->modalWidth('7xl')
|
|
->form([
|
|
Select::make('iban')
|
|
->label('Conto (IBAN)')
|
|
->native(false)
|
|
->searchable()
|
|
->options(fn(): array=> $this->getIbanOptions())
|
|
->required(),
|
|
|
|
Textarea::make('note')
|
|
->label('Note (opzionale)')
|
|
->rows(2)
|
|
->maxLength(255),
|
|
|
|
Repeater::make('saldi')
|
|
->label('Saldi')
|
|
->defaultItems(1)
|
|
->reorderable(true)
|
|
->schema([
|
|
DatePicker::make('data_saldo')
|
|
->label('Data')
|
|
->required(),
|
|
|
|
TextInput::make('saldo')
|
|
->label('Saldo')
|
|
->numeric()
|
|
->required(),
|
|
])
|
|
->columns(2)
|
|
->required(),
|
|
])
|
|
->action(function (array $data): void {
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
Notification::make()->title('Utente non valido')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
Notification::make()->title('Seleziona uno stabile')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$iban = isset($data['iban']) && is_string($data['iban']) ? trim((string) $data['iban']) : '';
|
|
if ($iban === '') {
|
|
Notification::make()->title('Seleziona un IBAN')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$rows = $data['saldi'] ?? [];
|
|
if (! is_array($rows) || $rows === []) {
|
|
Notification::make()->title('Inserisci almeno un saldo')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$note = isset($data['note']) && is_string($data['note']) ? trim((string) $data['note']) : '';
|
|
|
|
$contoId = null;
|
|
try {
|
|
if (DB::getSchemaBuilder()->hasTable('dati_bancari') && DB::getSchemaBuilder()->hasColumn('contabilita_saldi_conti', 'conto_id')) {
|
|
$contoId = DatiBancari::query()
|
|
->where('stabile_id', (int) $stabileId)
|
|
->where('iban', $iban)
|
|
->orderBy('id')
|
|
->value('id');
|
|
$contoId = is_numeric($contoId) ? (int) $contoId : null;
|
|
}
|
|
} catch (\Throwable) {
|
|
$contoId = null;
|
|
}
|
|
|
|
$created = 0;
|
|
DB::transaction(function () use ($rows, $stabileId, $contoId, $iban, $note, &$created, $user): void {
|
|
foreach ($rows as $row) {
|
|
$date = $row['data_saldo'] ?? null;
|
|
$saldo = $row['saldo'] ?? null;
|
|
|
|
if (! $date || ! is_numeric($saldo)) {
|
|
continue;
|
|
}
|
|
|
|
SaldoConto::query()->create([
|
|
'stabile_id' => (int) $stabileId,
|
|
'conto_id' => $contoId,
|
|
'iban' => $iban,
|
|
'data_saldo' => $date,
|
|
'saldo' => (float) $saldo,
|
|
'note' => $note !== '' ? $note : null,
|
|
'created_by' => (int) ($user->id ?? 0) ?: null,
|
|
'updated_by' => (int) ($user->id ?? 0) ?: null,
|
|
]);
|
|
$created++;
|
|
}
|
|
});
|
|
|
|
Notification::make()
|
|
->title('Saldi salvati')
|
|
->body('Inseriti: ' . $created)
|
|
->success()
|
|
->send();
|
|
}),
|
|
];
|
|
}
|
|
|
|
protected function getTableQuery(): Builder
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return DatiBancari::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return DatiBancari::query()->whereRaw('1 = 0');
|
|
}
|
|
|
|
return DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->orderBy('stato_conto')
|
|
->orderBy('denominazione_banca')
|
|
->orderBy('iban')
|
|
->orderBy('id');
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->striped()
|
|
->filters([
|
|
Filter::make('periodo')
|
|
->label('Periodo')
|
|
->form([
|
|
DatePicker::make('from')->label('Dal'),
|
|
DatePicker::make('to')->label('Al'),
|
|
]),
|
|
|
|
Filter::make('gestioni')
|
|
->label('Gestioni')
|
|
->form([
|
|
Select::make('gestione_ids')
|
|
->label('Gestione')
|
|
->multiple()
|
|
->options(fn(): array=> $this->getGestioniOptions())
|
|
->searchable(),
|
|
]),
|
|
])
|
|
->columns([
|
|
TextColumn::make('denominazione_banca')
|
|
->label('Banca')
|
|
->searchable()
|
|
->wrap(),
|
|
|
|
TextColumn::make('tipo_conto')
|
|
->label('Tipo')
|
|
->toggleable(isToggledHiddenByDefault: true),
|
|
|
|
TextColumn::make('intestazione_conto')
|
|
->label('Intestazione')
|
|
->wrap()
|
|
->toggleable(isToggledHiddenByDefault: true),
|
|
|
|
TextColumn::make('iban')
|
|
->label('IBAN')
|
|
->searchable()
|
|
->copyable(),
|
|
|
|
TextColumn::make('saldo_calcolato')
|
|
->label('Saldo')
|
|
->alignEnd()
|
|
->getStateUsing(fn(DatiBancari $record): ?float => $this->resolveSaldoConto($record))
|
|
->formatStateUsing(fn($state) => $state !== null ? ('€ ' . number_format((float) $state, 2, ',', '.')) : '—'),
|
|
|
|
TextColumn::make('saldo_ufficiale')
|
|
->label('Saldo ufficiale')
|
|
->alignEnd()
|
|
->getStateUsing(fn(DatiBancari $record): ?float => $this->resolveLatestSaldoSnapshotValue($record))
|
|
->formatStateUsing(fn($state) => $state !== null ? ('€ ' . number_format((float) $state, 2, ',', '.')) : '—')
|
|
->toggleable(),
|
|
|
|
TextColumn::make('ultimo_estratto')
|
|
->label('Ultimo estratto')
|
|
->getStateUsing(fn(DatiBancari $record): string => $this->resolveLatestSaldoSnapshotLabel($record))
|
|
->wrap()
|
|
->toggleable(),
|
|
|
|
TextColumn::make('stato_conto')
|
|
->label('Stato')
|
|
->toggleable(isToggledHiddenByDefault: true),
|
|
])
|
|
->actions([
|
|
Action::make('movimenti')
|
|
->label('Movimenti')
|
|
->icon('heroicon-o-arrow-right')
|
|
->url(function (DatiBancari $record): string {
|
|
return CasseBancheMovimenti::getUrl(panel: 'admin-filament') . '?conto_id=' . (int) $record->id;
|
|
}),
|
|
]);
|
|
}
|
|
|
|
public function getTotaleDisponibilita(): ?float
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return null;
|
|
}
|
|
|
|
$periodo = $this->getTableFilterState('periodo');
|
|
$from = is_array($periodo) ? ($periodo['from'] ?? null) : null;
|
|
$to = is_array($periodo) ? ($periodo['to'] ?? null) : null;
|
|
|
|
$gestioni = $this->getTableFilterState('gestioni');
|
|
$gestioneIds = is_array($gestioni) ? ($gestioni['gestione_ids'] ?? null) : null;
|
|
$gestioneIds = is_array($gestioneIds) ? array_values(array_filter(array_map('intval', $gestioneIds), fn(int $v) => $v > 0)) : [];
|
|
|
|
$conti = DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->get();
|
|
|
|
if ($conti->isEmpty()) {
|
|
return 0.0;
|
|
}
|
|
|
|
$total = 0.0;
|
|
foreach ($conti as $c) {
|
|
$saldo = $this->resolveSaldoConto($c);
|
|
if ($saldo !== null) {
|
|
$total += $saldo;
|
|
}
|
|
}
|
|
|
|
return $total;
|
|
}
|
|
|
|
protected function resolveSaldoConto(DatiBancari $record): ?float
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return null;
|
|
}
|
|
|
|
$iban = is_string($record->iban) ? trim((string) $record->iban) : '';
|
|
|
|
$periodo = $this->getTableFilterState('periodo');
|
|
$from = is_array($periodo) ? ($periodo['from'] ?? null) : null;
|
|
$to = is_array($periodo) ? ($periodo['to'] ?? null) : null;
|
|
|
|
$gestioni = $this->getTableFilterState('gestioni');
|
|
$gestioneIds = is_array($gestioni) ? ($gestioni['gestione_ids'] ?? null) : null;
|
|
$gestioneIds = is_array($gestioneIds) ? array_values(array_filter(array_map('intval', $gestioneIds), fn(int $v) => $v > 0)) : [];
|
|
|
|
$saldoIniziale = is_numeric($record->saldo_iniziale) ? (float) $record->saldo_iniziale : 0.0;
|
|
|
|
$q = MovimentoBanca::query()
|
|
->where('stabile_id', $stabileId)
|
|
->when($record->id, fn($q) => $q->where('conto_id', (int) $record->id))
|
|
->when($iban !== '', fn($q) => $q->where('iban', $iban));
|
|
|
|
if ($from) {
|
|
$q->whereDate('data', '>=', $from);
|
|
}
|
|
if ($to) {
|
|
$q->whereDate('data', '<=', $to);
|
|
}
|
|
if ($gestioneIds !== []) {
|
|
$q->whereIn('gestione_id', $gestioneIds);
|
|
}
|
|
|
|
// Base da saldi intermedi: se c'è un saldo <= from (se filtrato) o altrimenti ultimo saldo disponibile.
|
|
$baseSaldo = null;
|
|
$baseDate = null;
|
|
if (DB::getSchemaBuilder()->hasTable('contabilita_saldi_conti')) {
|
|
$qSaldo = SaldoConto::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('conto_id', (int) $record->id);
|
|
|
|
if ($from) {
|
|
$qSaldo->whereDate('data_saldo', '<=', (string) $from);
|
|
}
|
|
|
|
$row = $qSaldo->orderByDesc('data_saldo')->orderByDesc('id')->first(['data_saldo', 'saldo']);
|
|
if ($row) {
|
|
$baseSaldo = (float) $row->saldo;
|
|
$baseDate = $row->data_saldo->toDateString();
|
|
}
|
|
}
|
|
|
|
if ($from && $baseSaldo !== null) {
|
|
// Se filtrato da una data, la base è già il saldo al from (o più vicino precedente).
|
|
$saldoIniziale = $baseSaldo;
|
|
}
|
|
|
|
if ($baseSaldo !== null && ! $from) {
|
|
// Non filtrato: usa ultimo saldo inserito come base.
|
|
$saldoIniziale = $baseSaldo;
|
|
}
|
|
|
|
if ($baseDate && ! $from) {
|
|
$q->whereDate('data', '>', $baseDate);
|
|
}
|
|
|
|
$sum = (float) ($q->sum('importo') ?? 0.0);
|
|
return $saldoIniziale + $sum;
|
|
}
|
|
|
|
protected function resolveSaldoIniziale(int $stabileId, string $iban, string $fromDate): ?float
|
|
{
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_saldi_conti')) {
|
|
return null;
|
|
}
|
|
|
|
$row = SaldoConto::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('iban', $iban)
|
|
->whereDate('data_saldo', '<=', $fromDate)
|
|
->orderByDesc('data_saldo')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
return $row ? (float) $row->saldo : null;
|
|
}
|
|
|
|
protected function resolveLatestSaldoSnapshot(DatiBancari $record): ?SaldoConto
|
|
{
|
|
static $cache = [];
|
|
|
|
$cacheKey = (int) $record->id;
|
|
if (array_key_exists($cacheKey, $cache)) {
|
|
return $cache[$cacheKey];
|
|
}
|
|
|
|
if (! DB::getSchemaBuilder()->hasTable('contabilita_saldi_conti')) {
|
|
return $cache[$cacheKey] = null;
|
|
}
|
|
|
|
return $cache[$cacheKey] = SaldoConto::query()
|
|
->with('documento')
|
|
->where('stabile_id', (int) $record->stabile_id)
|
|
->where('conto_id', (int) $record->id)
|
|
->orderByDesc('data_saldo')
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
protected function resolveLatestSaldoSnapshotValue(DatiBancari $record): ?float
|
|
{
|
|
$snapshot = $this->resolveLatestSaldoSnapshot($record);
|
|
|
|
return $snapshot ? (float) $snapshot->saldo : null;
|
|
}
|
|
|
|
protected function resolveLatestSaldoSnapshotLabel(DatiBancari $record): string
|
|
{
|
|
$snapshot = $this->resolveLatestSaldoSnapshot($record);
|
|
if (! $snapshot) {
|
|
return 'Nessuno estratto registrato';
|
|
}
|
|
|
|
$parts = [];
|
|
$parts[] = $snapshot->tipo_estratto
|
|
? ($this->getTipoEstrattoOptions()[$snapshot->tipo_estratto] ?? 'Saldo registrato')
|
|
: 'Saldo registrato';
|
|
if ($snapshot->periodo_da || $snapshot->periodo_a) {
|
|
$from = $snapshot->periodo_da?->format('d/m/Y');
|
|
$to = $snapshot->periodo_a?->format('d/m/Y');
|
|
$parts[] = trim(($from ?: '...') . ' - ' . ($to ?: '...'));
|
|
}
|
|
if ($snapshot->documento instanceof DocumentoStabile) {
|
|
$parts[] = $snapshot->documento->nome_originale ?: 'Documento allegato';
|
|
}
|
|
|
|
return implode(' · ', $parts);
|
|
}
|
|
|
|
protected function getTipoEstrattoOptions(): array
|
|
{
|
|
return [
|
|
'estratto_conto' => 'Estratto conto',
|
|
'saldo_banca' => 'Saldo banca',
|
|
'riconciliazione' => 'Riconciliazione',
|
|
'altro' => 'Altro',
|
|
];
|
|
}
|
|
|
|
protected function getContiOptions(): array
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return [];
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return [];
|
|
}
|
|
|
|
return DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->orderBy('denominazione_banca')
|
|
->orderBy('legacy_cod_cassa')
|
|
->orderBy('numero_conto')
|
|
->orderBy('id')
|
|
->get(['id', 'denominazione_banca', 'iban', 'legacy_cod_cassa', 'numero_conto'])
|
|
->mapWithKeys(function (DatiBancari $conto): array {
|
|
$parts = [];
|
|
$parts[] = trim((string) ($conto->denominazione_banca ?: 'Conto'));
|
|
|
|
$legacyCodCassa = is_string($conto->legacy_cod_cassa) ? trim((string) $conto->legacy_cod_cassa) : '';
|
|
$numeroConto = is_string($conto->numero_conto) ? trim((string) $conto->numero_conto) : '';
|
|
$iban = is_string($conto->iban) ? trim((string) $conto->iban) : '';
|
|
|
|
if ($legacyCodCassa !== '') {
|
|
$parts[] = 'cassa ' . strtoupper($legacyCodCassa);
|
|
}
|
|
if ($iban !== '') {
|
|
$parts[] = $iban;
|
|
} elseif ($numeroConto !== '') {
|
|
$parts[] = 'n. ' . $numeroConto;
|
|
}
|
|
|
|
return [(int) $conto->id => implode(' · ', $parts)];
|
|
})
|
|
->all();
|
|
}
|
|
|
|
/** @return array<string,string> */
|
|
protected function getIbanOptions(): array
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return [];
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return [];
|
|
}
|
|
|
|
return DatiBancari::query()
|
|
->where('stabile_id', $stabileId)
|
|
->whereNotNull('iban')
|
|
->where('iban', '!=', '')
|
|
->orderBy('denominazione_banca')
|
|
->orderBy('iban')
|
|
->limit(500)
|
|
->get(['iban', 'denominazione_banca'])
|
|
->mapWithKeys(fn(DatiBancari $r) => [
|
|
trim((string) $r->iban) => trim((string) ($r->denominazione_banca ?: 'Conto') . ' · ' . (string) $r->iban),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
/** @return array<string,string> */
|
|
protected function getGestioniOptions(): array
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return [];
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return [];
|
|
}
|
|
|
|
if (! DB::getSchemaBuilder()->hasTable('gestioni_contabili')) {
|
|
return [];
|
|
}
|
|
|
|
return GestioneContabile::query()
|
|
->where('stabile_id', $stabileId)
|
|
->orderByDesc('anno_gestione')
|
|
->orderBy('tipo_gestione')
|
|
->orderByDesc('id')
|
|
->get(['id', 'denominazione', 'protocollo_prefix', 'stato'])
|
|
->mapWithKeys(fn(GestioneContabile $g) => [
|
|
(string) $g->id => trim(($g->protocollo_prefix ? $g->protocollo_prefix . ' · ' : '') . $g->denominazione) . ($g->stato !== 'aperta' ? (' (' . $g->stato . ')') : ''),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
protected function resolveDefaultGestioneId(): ?string
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return null;
|
|
}
|
|
|
|
if (! DB::getSchemaBuilder()->hasTable('gestioni_contabili')) {
|
|
return null;
|
|
}
|
|
|
|
$anno = AnnoGestioneContext::resolveActiveAnno();
|
|
$tipo = GestioneContext::resolveActiveGestione();
|
|
|
|
$match = GestioneContabile::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('anno_gestione', $anno)
|
|
->where('tipo_gestione', $tipo)
|
|
->where('stato', 'aperta')
|
|
->orderByDesc('gestione_attiva')
|
|
->orderByDesc('id')
|
|
->first();
|
|
|
|
if (! $match) {
|
|
$match = GestioneContabile::query()
|
|
->where('stabile_id', $stabileId)
|
|
->where('stato', 'aperta')
|
|
->orderByDesc('gestione_attiva')
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
return $match ? (string) $match->id : null;
|
|
}
|
|
}
|