netgescon-day0/app/Filament/Pages/Contabilita/CaricamentoDatiBanca.php

228 lines
7.7 KiB
PHP

<?php
namespace App\Filament\Pages\Contabilita;
use App\Models\GestioneContabile;
use App\Models\User;
use App\Models\DatiBancari;
use App\Services\Contabilita\IntesaCsvParser;
use App\Services\Contabilita\ExcelMovimentiParser;
use App\Services\Contabilita\MovimentiBancaImporter;
use App\Services\Contabilita\UnicreditWriParser;
use App\Support\StabileContext;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use UnitEnum;
class CaricamentoDatiBanca extends Page
{
protected static ?string $navigationLabel = 'Caricamento dati banca';
protected static ?string $title = 'Caricamento dati banca';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-arrow-up-tray';
protected static UnitEnum|string|null $navigationGroup = 'Contabilità';
protected static ?int $navigationSort = 15;
protected static ?string $slug = 'contabilita/caricamento-dati-banca';
protected string $view = 'filament.pages.contabilita.caricamento-dati-banca';
protected function getHeaderActions(): array
{
return [
Action::make('importa_unicredit_wri')
->label('Importa estratto (Unicredit WRI)')
->icon('heroicon-o-arrow-up-tray')
->modalWidth('7xl')
->form($this->getImportFormSchema())
->action(function (array $data): void {
$this->runImport('unicredit', $data);
}),
Action::make('importa_intesa_csv')
->label('Importa estratto (Intesa CSV)')
->icon('heroicon-o-arrow-up-tray')
->modalWidth('7xl')
->form($this->getImportFormSchema())
->action(function (array $data): void {
$this->runImport('intesa', $data);
}),
];
}
private function getImportFormSchema(): array
{
return [
Select::make('iban')
->label('Conto (IBAN)')
->native(false)
->searchable()
->options(fn(): array => $this->getIbanOptions())
->helperText('Consigliato: seleziona il conto per associare i movimenti.'),
Select::make('gestione_id')
->label('Gestione (opzionale)')
->native(false)
->searchable()
->options(fn(): array => $this->getGestioneOptions())
->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')
->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),
];
}
private function runImport(string $tipo, 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());
$iban = isset($data['iban']) && is_string($data['iban']) && trim($data['iban']) !== '' ? trim((string) $data['iban']) : null;
$gestioneId = isset($data['gestione_id']) && is_numeric($data['gestione_id']) ? (int) $data['gestione_id'] : null;
$replace = isset($data['replace']) ? (bool) $data['replace'] : false;
if ($tipo === 'intesa') {
$res = $importer->importIntesaCsv($content, $stabileId, basename($path), $iban, $gestioneId, $replace);
} else {
$res = $importer->importUnicreditWri($content, $stabileId, basename($path), $iban, $gestioneId, $replace);
}
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
}
}
}
private function getIbanOptions(): array
{
$user = Auth::user();
if (! $user instanceof User) {
return [];
}
$stabileId = StabileContext::resolveActiveStabileId($user);
if (! $stabileId) {
return [];
}
$opts = [];
foreach (
DatiBancari::query()
->where('stabile_id', $stabileId)
->orderBy('denominazione_banca')
->orderBy('iban')
->get(['iban', 'denominazione_banca']) as $c
) {
$iban = is_string($c->iban) ? trim($c->iban) : '';
if ($iban === '') {
continue;
}
$label = trim(($c->denominazione_banca ?: 'Banca') . ' · ' . $iban);
$opts[$iban] = $label;
}
return $opts;
}
private function getGestioneOptions(): 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();
}
private 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;
}
$g = GestioneContabile::query()
->where('stabile_id', $stabileId)
->orderByDesc('anno_gestione')
->orderByDesc('id')
->first(['id']);
return $g ? (string) $g->id : null;
}
}