netgescon-day0/app/Livewire/Condomini/StabileDatiBancariTable.php

423 lines
16 KiB
PHP

<?php
namespace App\Livewire\Condomini;
use App\Filament\Pages\Contabilita\CasseBancheMovimenti;
use App\Filament\Pages\Gescon\RubricaUniversaleScheda;
use App\Models\DatiBancari;
use App\Models\RubricaUniversale;
use App\Models\Stabile;
use App\Models\User;
use App\Services\GesconImport\StabileEnrichmentService;
use App\Support\StabileContext;
use Filament\Actions\Action;
use Filament\Forms\Components\DatePicker;
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\Support\Contracts\TranslatableContentDriver;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Tables\TableComponent;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
class StabileDatiBancariTable extends TableComponent
{
public int $stabileId;
public function mount(int $stabileId): void
{
$this->stabileId = $stabileId;
$this->mountInteractsWithTable();
}
protected function getTableQuery(): Builder
{
$user = Auth::user();
if (! $user instanceof User) {
return DatiBancari::query()->whereRaw('1 = 0');
}
$allowed = StabileContext::accessibleStabili($user)->pluck('id')->map(fn($v) => (int) $v)->all();
if (! in_array((int) $this->stabileId, $allowed, true)) {
return DatiBancari::query()->whereRaw('1 = 0');
}
return DatiBancari::query()
->with(['contatto'])
->where('stabile_id', (int) $this->stabileId)
->orderByDesc('is_nostro_conto')
->orderBy('denominazione_banca')
->orderByDesc('id');
}
public function table(Table $table): Table
{
return $table
->striped()
->columns([
TextColumn::make('denominazione_banca')
->label('Banca / Cassa')
->wrap()
->searchable(),
TextColumn::make('tipo_conto')
->label('Tipo')
->sortable(),
TextColumn::make('iban')
->label('IBAN')
->copyable()
->toggleable(),
IconColumn::make('is_nostro_conto')
->label('Nostro')
->boolean()
->toggleable(),
TextColumn::make('stato_conto')
->label('Stato')
->sortable(),
TextColumn::make('saldo_iniziale')
->label('Saldo iniz.')
->money('EUR')
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('data_saldo_iniziale')
->label('Data saldo')
->date('d/m/Y')
->toggleable(isToggledHiddenByDefault: true),
TextColumn::make('contatto.nome_completo')
->label('Contatto')
->wrap()
->toggleable(isToggledHiddenByDefault: true),
])
->headerActions([
Action::make('importa_da_stabili_mdb')
->label('Importa da Stabili.mdb')
->icon('heroicon-o-arrow-down-tray')
->color('warning')
->requiresConfirmation()
->action(function (): void {
$user = Auth::user();
if (! $user instanceof User) {
Notification::make()->title('Utente non valido')->danger()->send();
return;
}
$stabile = Stabile::query()->with('amministratore')->find((int) $this->stabileId);
if (! $stabile) {
Notification::make()->title('Stabile non trovato')->danger()->send();
return;
}
$amm = $stabile->amministratore;
$adminCode = $amm ? (string) ($amm->codice_univoco ?: $amm->codice_amministratore ?: '') : '';
$adminCode = trim($adminCode);
if ($adminCode === '') {
$adminCode = $amm ? ('ID' . $amm->id) : 'ID0';
}
$adminCode = preg_replace('/[^A-Za-z0-9_-]+/', '_', $adminCode) ?: $adminCode;
$adminCode = trim((string) $adminCode, '_');
if ($adminCode === '') {
$adminCode = $amm ? ('ID' . $amm->id) : 'ID0';
}
$basePath = '/mnt/gescon-archives/gescon/' . $adminCode;
$legacyCode = (string) ($stabile->codice_stabile ?? ($stabile->cod_stabile ?? ''));
$legacyCode = str_pad(trim($legacyCode), 4, '0', STR_PAD_LEFT);
try {
(new StabileEnrichmentService())->enrich($legacyCode, $basePath);
} catch (\Throwable $e) {
Notification::make()
->title('Import fallito')
->body($e->getMessage())
->danger()
->send();
return;
}
Notification::make()
->title('Import completato')
->body('Dati bancari aggiornati da Stabili.mdb')
->success()
->send();
}),
Action::make('nuovo_conto')
->label('Nuovo conto')
->icon('heroicon-o-plus')
->color('success')
->modalHeading('Nuovo conto')
->form($this->formSchema())
->action(function (array $data): void {
$user = Auth::user();
$uid = $user instanceof User ? (int) $user->id : null;
$payload = $this->normalizePayload($data);
$payload['stabile_id'] = (int) $this->stabileId;
if ($uid) {
$payload['creato_da'] = $uid;
$payload['modificato_da'] = $uid;
}
DatiBancari::create($payload);
Notification::make()
->title('Conto creato')
->success()
->send();
}),
])
->actions([
Action::make('movimenti')
->label('Movimenti')
->icon('heroicon-o-receipt-percent')
->url(function (DatiBancari $record): string {
$base = CasseBancheMovimenti::getUrl(panel: 'admin-filament');
$iban = is_string($record->iban ?? null) ? trim((string) $record->iban) : '';
if ($iban === '') {
return $base;
}
return $base . '?' . http_build_query([
'tableFilters' => [
'conto' => [
'ibans' => [$iban],
],
],
]);
})
->openUrlInNewTab(),
Action::make('contatto')
->label('Contatto')
->icon('heroicon-o-identification')
->visible(fn(DatiBancari $record): bool => (int) ($record->contatto_id ?? 0) > 0)
->url(fn(DatiBancari $record): string => RubricaUniversaleScheda::getUrl([
'record' => (int) $record->contatto_id,
], panel: 'admin-filament')),
Action::make('modifica')
->label('Modifica')
->icon('heroicon-o-pencil-square')
->modalHeading('Modifica conto')
->fillForm(fn(DatiBancari $record): array => [
'denominazione_banca' => $record->denominazione_banca,
'tipo_conto' => $record->tipo_conto,
'stato_conto' => $record->stato_conto,
'iban' => $record->iban,
'numero_conto' => $record->numero_conto,
'abi' => $record->abi,
'cab' => $record->cab,
'cin' => $record->cin,
'bic_swift' => $record->bic_swift,
'cuc' => $record->cuc,
'sia' => $record->sia,
'intestazione_conto' => $record->intestazione_conto,
'data_saldo_iniziale' => $record->data_saldo_iniziale,
'saldo_iniziale' => $record->saldo_iniziale,
'valuta' => $record->valuta,
'is_nostro_conto' => (bool) $record->is_nostro_conto,
'contatto_id' => $record->contatto_id,
'note' => $record->note,
])
->form($this->formSchema())
->action(function (DatiBancari $record, array $data): void {
$user = Auth::user();
$uid = $user instanceof User ? (int) $user->id : null;
$payload = $this->normalizePayload($data);
if ($uid) {
$payload['modificato_da'] = $uid;
}
$record->fill($payload);
if ($record->isDirty()) {
$record->save();
}
Notification::make()
->title('Conto aggiornato')
->success()
->send();
}),
Action::make('elimina')
->label('Elimina')
->icon('heroicon-o-trash')
->color('danger')
->requiresConfirmation()
->action(function (DatiBancari $record): void {
$record->delete();
Notification::make()
->title('Conto eliminato')
->success()
->send();
}),
]);
}
public function makeFilamentTranslatableContentDriver(): ?TranslatableContentDriver
{
return null;
}
/**
* @return array<int, \Filament\Forms\Components\Component>
*/
private function formSchema(): array
{
return [
TextInput::make('denominazione_banca')
->label('Denominazione banca/cassa')
->required()
->maxLength(255),
Select::make('tipo_conto')
->label('Tipo conto')
->options([
'corrente' => 'Corrente',
'deposito' => 'Deposito',
'risparmio' => 'Risparmio',
])
->default('corrente')
->required(),
Select::make('stato_conto')
->label('Stato')
->options([
'attivo' => 'Attivo',
'sospeso' => 'Sospeso',
'chiuso' => 'Chiuso',
])
->default('attivo')
->required(),
TextInput::make('iban')
->label('IBAN')
->maxLength(64),
TextInput::make('numero_conto')
->label('Numero conto')
->maxLength(64),
TextInput::make('abi')
->label('ABI')
->maxLength(16),
TextInput::make('cab')
->label('CAB')
->maxLength(16),
TextInput::make('cin')
->label('CIN')
->maxLength(8),
TextInput::make('bic_swift')
->label('BIC / SWIFT')
->maxLength(32),
TextInput::make('cuc')
->label('CUC')
->maxLength(32),
TextInput::make('sia')
->label('SIA')
->maxLength(32),
TextInput::make('intestazione_conto')
->label('Intestazione conto')
->maxLength(255),
DatePicker::make('data_saldo_iniziale')
->label('Data saldo iniziale'),
TextInput::make('saldo_iniziale')
->label('Saldo iniziale')
->numeric()
->default(0),
TextInput::make('valuta')
->label('Valuta')
->maxLength(8)
->default('EUR'),
Toggle::make('is_nostro_conto')
->label('Nostro conto')
->default(false),
Select::make('contatto_id')
->label('Contatto banca (rubrica)')
->searchable()
->options(function (): array {
$records = RubricaUniversale::query()
->categoria('banca')
->attivi()
->orderBy('ragione_sociale')
->orderBy('cognome')
->orderBy('nome')
->get(['id', 'ragione_sociale', 'nome', 'cognome']);
return $records
->mapWithKeys(function (RubricaUniversale $r): array {
$label = trim((string) ($r->nome_completo ?? ''));
if ($label === '') {
$label = trim((string) ($r->ragione_sociale ?? ''));
}
if ($label === '') {
$label = trim((string) (($r->cognome ?? '') . ' ' . ($r->nome ?? '')));
}
if ($label === '') {
$label = 'Contatto #' . (int) $r->id;
}
return [(int) $r->id => $label];
})
->all();
})
->placeholder('—'),
Textarea::make('note')
->label('Note')
->rows(3),
];
}
/**
* @param array<string,mixed> $data
* @return array<string,mixed>
*/
private function normalizePayload(array $data): array
{
return [
'denominazione_banca' => isset($data['denominazione_banca']) ? trim((string) $data['denominazione_banca']) : null,
'tipo_conto' => isset($data['tipo_conto']) ? (string) $data['tipo_conto'] : null,
'stato_conto' => isset($data['stato_conto']) ? (string) $data['stato_conto'] : null,
'iban' => isset($data['iban']) ? trim((string) $data['iban']) : null,
'numero_conto' => isset($data['numero_conto']) ? trim((string) $data['numero_conto']) : null,
'abi' => isset($data['abi']) ? trim((string) $data['abi']) : null,
'cab' => isset($data['cab']) ? trim((string) $data['cab']) : null,
'cin' => isset($data['cin']) ? trim((string) $data['cin']) : null,
'bic_swift' => isset($data['bic_swift']) ? trim((string) $data['bic_swift']) : null,
'cuc' => isset($data['cuc']) ? trim((string) $data['cuc']) : null,
'sia' => isset($data['sia']) ? trim((string) $data['sia']) : null,
'intestazione_conto' => isset($data['intestazione_conto']) ? trim((string) $data['intestazione_conto']) : null,
'data_saldo_iniziale' => $data['data_saldo_iniziale'] ?? null,
'saldo_iniziale' => $data['saldo_iniziale'] ?? null,
'valuta' => isset($data['valuta']) ? trim((string) $data['valuta']) : null,
'is_nostro_conto' => (bool) ($data['is_nostro_conto'] ?? false),
'contatto_id' => ! empty($data['contatto_id']) ? (int) $data['contatto_id'] : null,
'note' => isset($data['note']) ? trim((string) $data['note']) : null,
];
}
}