netgescon-day0/resources/views/filament/pages/contabilita/casse-banche-movimenti.blade.php

738 lines
57 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<x-filament-panels::page>
<div class="mx-auto max-w-7xl space-y-4">
<x-filament.components.page-breadcrumbs
:breadcrumbs="[
['label' => 'Contabilità', 'url' => null],
['label' => 'Casse e banche', 'url' => null],
]"
/>
@php
$stabile = $this->getActiveStabile();
$contiRows = $this->getHubContiRows();
$contiOptions = $this->getContiImportabili();
$hdr = $this->getHeaderSaldoInfo();
$periodo = $this->periodoTotali;
$periodoOptions = $this->periodoOptions;
$periodoRateOptions = $this->periodoRateOptions;
$periodoRate = $this->periodoRateTotali;
$contoImport = $this->getSelectedContoImportInfo();
$snapshotCards = $this->getSaldoSnapshotCards();
$saldoArchivio = $this->getSaldoArchivioByYear();
$ricStats = $this->getRiconciliazioneStats();
$ricQueue = $this->getRiconciliazioneQueue();
$ricCurrent = $this->getRiconciliazioneCurrent();
$ricCandidates = $this->getRiconciliazioneCandidates();
$archiveSummary = $this->getArchivioOperativoSummary();
$gestioniRilevate = $this->getGestioniContabiliRilevate();
$ricBuckets = $this->getRiconciliazioneBucketRows();
$tipoEstrattoOptions = [
'estratto_conto' => 'Estratto conto',
'saldo_banca' => 'Saldo banca',
'riconciliazione' => 'Riconciliazione',
'altro' => 'Altro',
];
@endphp
@if(! $stabile)
<x-filament::section>
<div class="text-sm text-gray-600">Seleziona uno stabile per importare e verificare i movimenti banca.</div>
</x-filament::section>
@else
<x-filament::section>
<div class="grid grid-cols-1 gap-4 xl:grid-cols-[minmax(0,1.4fr)_minmax(320px,0.8fr)]">
<div>
<div class="text-sm text-gray-500">Stabile attivo</div>
<div class="text-lg font-semibold text-gray-900">
{{ $stabile->codice_operatore ?? $stabile->codice_stabile ?? '—' }} {{ $stabile->denominazione ?? 'Stabile' }}
</div>
<div class="mt-1 text-xs text-gray-600">Hub operativo del conto corrente: conti, saldi ufficiali, movimenti importati e riconciliazione.</div>
</div>
<div class="rounded-xl border bg-slate-50 p-4">
<div class="text-xs font-medium uppercase tracking-wide text-slate-500">Conto attivo</div>
<div class="mt-2">
<select wire:model.live="contoId" class="w-full rounded-lg border-gray-300 text-sm">
<option value="">Seleziona conto</option>
@foreach($contiOptions as $conto)
<option value="{{ $conto['id'] }}">{{ $conto['label'] }}</option>
@endforeach
</select>
</div>
<div class="mt-3 text-sm text-slate-700">
@if($contoImport)
<div class="font-medium">{{ $contoImport['label'] }}</div>
@else
<div>Nessun conto selezionato.</div>
@endif
</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button size="sm" color="primary" type="button" wire:click="mountAction('importa_estratto_unificato')">
Importa estratto
</x-filament::button>
<x-filament::button size="sm" color="gray" type="button" wire:click="mountAction('registra_saldo_estratto')">
Registra saldo
</x-filament::button>
</div>
</div>
</div>
</x-filament::section>
<x-filament::tabs>
<x-filament::tabs.item :active="$this->hubTab === 'conti'" wire:click="goToHubTab('conti')">Conti</x-filament::tabs.item>
<x-filament::tabs.item :active="$this->hubTab === 'saldi'" wire:click="goToHubTab('saldi')">Saldi e estratti</x-filament::tabs.item>
<x-filament::tabs.item :active="$this->hubTab === 'movimenti'" wire:click="goToHubTab('movimenti')">Movimenti</x-filament::tabs.item>
<x-filament::tabs.item :active="$this->hubTab === 'struttura'" wire:click="goToHubTab('struttura')">Struttura e gestioni</x-filament::tabs.item>
<x-filament::tabs.item :active="$this->hubTab === 'riconciliazione'" wire:click="goToHubTab('riconciliazione')">Riconciliazione</x-filament::tabs.item>
<x-filament::tabs.item :active="$this->hubTab === 'associazione_causali'" wire:click="goToHubTab('associazione_causali')">Associazione Causali</x-filament::tabs.item>
</x-filament::tabs>
@if($this->hubTab === 'conti')
<x-filament::section>
<x-slot name="heading">Conti dello stabile</x-slot>
<x-slot name="description">Vista generale equivalente a “Casse e banche”, ma dentro l'hub operativo del conto corrente.</x-slot>
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
@forelse($contiRows as $row)
<div @class([
'rounded-xl border p-4',
'border-primary-300 bg-primary-50/40' => $row['selected'],
'bg-white' => ! $row['selected'],
])>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold text-slate-900">{{ $row['label'] }}</div>
<div class="mt-1 text-xs text-slate-600">
@if($row['snapshot_data'])
Ultimo saldo ufficiale: {{ $row['snapshot_data'] }}
@if($row['snapshot_tipo'])
· {{ $row['snapshot_tipo'] }}
@endif
@else
Nessun saldo ufficiale registrato.
@endif
</div>
</div>
@if($row['selected'])
<span class="rounded-full bg-primary-600 px-2.5 py-1 text-[11px] font-semibold text-white">Attivo</span>
@endif
</div>
<div class="mt-4 grid grid-cols-2 gap-3 text-sm">
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Saldo attuale</div>
<div class="mt-1 text-lg font-semibold text-slate-900">€ {{ number_format((float) ($row['saldo_attuale'] ?? 0), 2, ',', '.') }}</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Movimenti importati</div>
<div class="mt-1 text-lg font-semibold text-slate-900">{{ $row['movimenti_count'] ?? 0 }}</div>
<div class="text-xs text-slate-500">Ultima data: {{ $row['ultima_movimentazione'] ?? '' }}</div>
</div>
</div>
<div class="mt-4 flex flex-wrap gap-2">
<x-filament::button size="sm" color="gray" wire:click="selectContoAndTab({{ $row['id'] }}, 'saldi')">Saldi / estratti</x-filament::button>
<x-filament::button size="sm" color="primary" wire:click="selectContoAndTab({{ $row['id'] }}, 'movimenti')">Movimenti</x-filament::button>
<x-filament::button size="sm" color="success" wire:click="selectContoAndTab({{ $row['id'] }}, 'riconciliazione')">Riconciliazione</x-filament::button>
</div>
</div>
@empty
<div class="rounded-lg border border-dashed bg-white p-4 text-sm text-slate-500 lg:col-span-2">Nessun conto configurato per lo stabile attivo.</div>
@endforelse
</div>
</x-filament::section>
@elseif($this->hubTab === 'saldi')
<x-filament::section>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-lg font-semibold text-slate-900">Archivio saldi ufficiali ed estratti conto</div>
<div class="mt-1 text-sm text-slate-600">Vista annuale del conto selezionato, separata dal mastrino dei movimenti.</div>
@if($contoImport)
<div class="mt-2 text-xs font-medium text-slate-700">Conto: {{ $contoImport['label'] }}</div>
@endif
</div>
<x-filament::button type="button" color="primary" wire:click="mountAction('registra_saldo_estratto')">
Nuovo saldo / estratto
</x-filament::button>
</div>
<div class="mt-4 space-y-6">
@forelse($saldoArchivio as $yearBlock)
<div class="rounded-xl border bg-white p-4">
<div class="flex items-center justify-between gap-3">
<div class="text-base font-semibold text-slate-900">Anno {{ $yearBlock['year'] }}</div>
<div class="text-xs text-slate-500">{{ count($yearBlock['rows']) }} estratti / saldi</div>
</div>
<div class="mt-4 overflow-x-auto">
<table class="min-w-full text-sm">
<thead class="text-left text-slate-500">
<tr>
<th class="py-2 pr-4">Data saldo</th>
<th class="py-2 pr-4">Periodo</th>
<th class="py-2 pr-4">Esito</th>
<th class="py-2 pr-4">Tipo</th>
<th class="py-2 pr-4 text-right">Saldo</th>
<th class="py-2 pr-4">Documento</th>
<th class="py-2 pr-4">Note</th>
<th class="py-2 pr-0 text-right">Azioni</th>
</tr>
</thead>
<tbody class="divide-y">
@foreach($yearBlock['rows'] as $row)
<tr>
<td class="py-3 pr-4 font-medium text-slate-900">{{ $row['data'] }}</td>
<td class="py-3 pr-4">
<div>{{ $row['periodo_breve'] }}</div>
<div class="text-xs text-slate-500">{{ $row['periodo'] }}</div>
</td>
<td class="py-3 pr-4 align-top">
@if(($row['quadratura_status'] ?? 'neutral') === 'ok')
<div class="inline-flex items-center gap-1 rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-semibold text-emerald-700">
<x-heroicon-o-check-circle class="h-4 w-4" />
OK
</div>
@elseif(($row['quadratura_status'] ?? 'neutral') === 'anchor')
<div class="inline-flex items-center gap-1 rounded-full bg-sky-100 px-2.5 py-1 text-xs font-semibold text-sky-700">
<x-heroicon-o-flag class="h-4 w-4" />
Partenza
</div>
@elseif(($row['quadratura_status'] ?? 'neutral') === 'mismatch')
<div class="inline-flex items-center gap-1 rounded-full bg-amber-100 px-2.5 py-1 text-xs font-semibold text-amber-700">
<x-heroicon-o-exclamation-triangle class="h-4 w-4" />
Verifica
</div>
@else
<div class="inline-flex items-center gap-1 rounded-full bg-slate-100 px-2.5 py-1 text-xs font-semibold text-slate-600">
<x-heroicon-o-minus-circle class="h-4 w-4" />
N/D
</div>
@endif
<div class="mt-1 text-xs text-slate-500">{{ $row['quadratura_label'] ?? '' }}</div>
@if(($row['quadratura_status'] ?? null) === 'mismatch' && array_key_exists('quadratura_delta', $row))
<div class="mt-1 text-xs font-medium text-rose-700">
Scarto: € {{ number_format((float) ($row['quadratura_delta'] ?? 0), 2, ',', '.') }}
</div>
@endif
</td>
<td class="py-3 pr-4">{{ $row['tipo'] }}</td>
<td class="py-3 pr-4 text-right font-semibold">€ {{ number_format((float) $row['saldo'], 2, ',', '.') }}</td>
<td class="py-3 pr-4">
@if($row['documento_url'] && $row['documento_label'])
<button type="button" wire:click="openSaldoDocumento({{ $row['id'] }})" class="text-primary-600 hover:underline">{{ $row['documento_label'] }}</button>
@else
<span class="text-slate-400">—</span>
@endif
</td>
<td class="py-3 pr-4 text-slate-600">{{ $row['note'] !== '' ? $row['note'] : '' }}</td>
<td class="py-3 pr-0 text-right">
<div class="flex flex-wrap justify-end gap-2">
<x-filament::button size="sm" color="gray" wire:click="openSaldoPeriodo({{ $row['id'] }})">Apri movimenti</x-filament::button>
<x-filament::button size="sm" color="warning" wire:click="startEditingSaldo({{ $row['id'] }})">Modifica</x-filament::button>
@if(($this->confirmingDeleteSaldoId ?? null) === $row['id'])
<x-filament::button size="sm" color="danger" wire:click="deleteSaldo({{ $row['id'] }})">Conferma elimina</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="cancelDeleteSaldo">Annulla</x-filament::button>
@else
<x-filament::button size="sm" color="danger" wire:click="requestDeleteSaldo({{ $row['id'] }})">Elimina</x-filament::button>
@endif
</div>
</td>
</tr>
@if(($this->editingSaldoId ?? null) === $row['id'])
<tr class="bg-amber-50/60">
<td colspan="8" class="py-4 pr-0">
<div class="rounded-xl border border-amber-200 bg-white p-4">
<div class="text-sm font-semibold text-slate-900">Modifica saldo / estratto</div>
<div class="mt-1 text-xs text-slate-600">Puoi correggere data saldo, periodo, tipo e note del record gia memorizzato.</div>
<div class="mt-4 grid grid-cols-1 gap-3 lg:grid-cols-3">
<label class="text-xs text-slate-600">
<span class="mb-1 block">Data saldo</span>
<input type="date" wire:model.defer="editingSaldoData.data_saldo" class="w-full rounded-lg border-gray-300 text-sm" />
</label>
<label class="text-xs text-slate-600">
<span class="mb-1 block">Periodo dal</span>
<input type="date" wire:model.defer="editingSaldoData.periodo_da" class="w-full rounded-lg border-gray-300 text-sm" />
</label>
<label class="text-xs text-slate-600">
<span class="mb-1 block">Periodo al</span>
<input type="date" wire:model.defer="editingSaldoData.periodo_a" class="w-full rounded-lg border-gray-300 text-sm" />
</label>
<label class="text-xs text-slate-600">
<span class="mb-1 block">Saldo ufficiale</span>
<input type="text" wire:model.defer="editingSaldoData.saldo" class="w-full rounded-lg border-gray-300 text-sm" />
</label>
<label class="text-xs text-slate-600">
<span class="mb-1 block">Tipo riferimento</span>
<select wire:model.defer="editingSaldoData.tipo_estratto" class="w-full rounded-lg border-gray-300 text-sm">
<option value="">Saldo registrato</option>
@foreach($tipoEstrattoOptions as $tipoValue => $tipoLabel)
<option value="{{ $tipoValue }}">{{ $tipoLabel }}</option>
@endforeach
</select>
</label>
<label class="flex items-center gap-2 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-xs text-slate-700">
<input type="checkbox" wire:model.defer="editingSaldoData.is_partenza_contabile" class="rounded border-gray-300 text-primary-600" />
<span>Usa questo saldo come partenza contabile</span>
</label>
<label class="text-xs text-slate-600 lg:col-span-2">
<span class="mb-1 block">Note</span>
<input type="text" wire:model.defer="editingSaldoData.note" class="w-full rounded-lg border-gray-300 text-sm" />
</label>
</div>
<div class="mt-4 flex flex-wrap justify-end gap-2">
<x-filament::button size="sm" color="gray" wire:click="cancelEditingSaldo">Annulla</x-filament::button>
<x-filament::button size="sm" color="primary" wire:click="saveEditingSaldo">Salva modifiche</x-filament::button>
</div>
</div>
</td>
</tr>
@endif
@endforeach
</tbody>
</table>
</div>
</div>
@empty
<div class="rounded-lg border border-dashed bg-white p-4 text-sm text-slate-500">Nessun saldo ufficiale registrato per il conto selezionato.</div>
@endforelse
</div>
</x-filament::section>
@elseif($this->hubTab === 'struttura')
<x-filament::section>
<x-slot name="heading">Struttura operativa banca / FE</x-slot>
<x-slot name="description">Separiamo la struttura documentale e le gestioni dal tab movimenti, così loperatore vede subito il mastrino e gli import.</x-slot>
<div class="grid grid-cols-1 gap-4 xl:grid-cols-3">
<div class="rounded-xl border bg-slate-50 p-4">
<div class="text-xs font-medium uppercase tracking-wide text-slate-500">Struttura archivio banca</div>
<div class="mt-2 text-sm font-semibold text-slate-900">{{ $archiveSummary['banca_folder'] ?? 'banca_cc/<conto>/<anno>' }}</div>
<div class="mt-2 text-xs text-slate-600">Qui finiscono estratti, saldi, file importati e documenti conto in modo uniforme su tutti gli stabili.</div>
<div class="mt-3 rounded-lg border bg-white p-3 text-xs text-slate-700">
<div><span class="font-semibold">Base stabile:</span> {{ $archiveSummary['base_folder'] ?? '' }}</div>
<div class="mt-1"><span class="font-semibold">Anno operativo:</span> {{ $archiveSummary['reference_year'] ?? '' }}</div>
</div>
</div>
<div class="rounded-xl border bg-slate-50 p-4">
<div class="text-xs font-medium uppercase tracking-wide text-slate-500">Gestioni contabili</div>
<div class="mt-2 text-sm font-semibold text-slate-900">{{ $archiveSummary['gestione_label'] ?? 'Gestione da associare' }}</div>
<div class="mt-1 text-xs text-slate-600">Le gestioni storiche restano qui, fuori dal mastrino, così il tab movimenti resta leggibile anche con molte annualità.</div>
<div class="mt-3 max-h-80 space-y-2 overflow-y-auto pr-1">
@forelse($gestioniRilevate as $gestione)
<div class="rounded-lg border bg-white px-3 py-2 text-xs text-slate-700">
<div class="flex items-center justify-between gap-2">
<span class="font-semibold">{{ $gestione['folder'] }}</span>
<span class="rounded-full px-2 py-0.5 {{ $gestione['active'] ? 'bg-emerald-100 text-emerald-700' : 'bg-slate-100 text-slate-600' }}">{{ $gestione['stato'] !== '' ? $gestione['stato'] : 'attiva' }}</span>
</div>
<div class="mt-1">{{ $gestione['label'] }}</div>
</div>
@empty
<div class="rounded-lg border border-dashed bg-white px-3 py-3 text-xs text-slate-500">Nessuna gestione ordinaria/straordinaria rilevata.</div>
@endforelse
</div>
</div>
<div class="rounded-xl border bg-slate-50 p-4">
<div class="text-xs font-medium uppercase tracking-wide text-slate-500">Struttura FE pronta</div>
<div class="mt-2 space-y-2 text-xs text-slate-700">
<div class="rounded-lg border bg-white px-3 py-2">
<div class="font-semibold text-slate-900">{{ $archiveSummary['fatture_xml_folder'] ?? 'fatture_xml/<anno>' }}</div>
<div class="mt-1">XML originali per anno, indipendenti dal PDF.</div>
</div>
<div class="rounded-lg border bg-white px-3 py-2">
<div class="font-semibold text-slate-900">{{ $archiveSummary['fatture_pdf_folder'] ?? 'fatture/<gestione>' }}</div>
<div class="mt-1">PDF protocollati per gestione, pronti per ACL atomici su anno e tipo gestione.</div>
</div>
</div>
</div>
</div>
<div class="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-[minmax(0,1.1fr)_minmax(320px,0.9fr)]">
<div class="rounded-lg border bg-slate-50 p-3">
<div class="text-sm font-semibold text-slate-900">Criteri di riconciliazione e quadratura</div>
<div class="mt-1 text-xs text-slate-600">Questi bucket restano visibili come riferimento operativo, ma fuori dal tab movimenti.</div>
<div class="mt-3 grid grid-cols-1 gap-3 md:grid-cols-2">
@foreach($ricBuckets as $bucket)
<div class="rounded-lg border bg-white p-3 text-sm">
<div class="font-semibold text-slate-900">{{ $bucket['title'] }}</div>
<div class="mt-1 text-xs text-slate-600">{{ $bucket['detail'] }}</div>
</div>
@endforeach
</div>
</div>
<div class="rounded-lg border bg-slate-50 p-3">
<div class="text-sm font-semibold text-slate-900">Regole operative di struttura</div>
<div class="mt-3 space-y-2 text-xs text-slate-700">
<div class="rounded-lg border bg-white px-3 py-2">I movimenti banca restano sempre sul <span class="font-semibold">conto selezionato</span> e vanno associati a una <span class="font-semibold">gestione</span>.</div>
<div class="rounded-lg border bg-white px-3 py-2">Per questo stabile trattiamo solo <span class="font-semibold">ordinaria</span> e <span class="font-semibold">straordinaria</span>; il riscaldamento non entra nel flusso.</div>
<div class="rounded-lg border bg-white px-3 py-2">Le FE acqua possono confluire sulla voce <span class="font-semibold">ACQ</span> quando il PDF e il pagamento banca danno un aggancio coerente.</div>
</div>
</div>
</div>
</x-filament::section>
@elseif($this->hubTab === 'riconciliazione')
<x-filament::section>
<x-slot name="heading">Riconciliazione guidata</x-slot>
<x-slot name="description">Pre-riconciliazione automatica con candidati. Loperatore verifica un movimento alla volta e usa il mastrino dove il match non è certo.</x-slot>
<div class="grid grid-cols-2 gap-3 xl:grid-cols-4">
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Totale movimenti</div>
<div class="mt-1 text-lg font-semibold text-slate-900">{{ $ricStats['totale'] ?? 0 }}</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Senza prima nota</div>
<div class="mt-1 text-lg font-semibold text-slate-900">{{ $ricStats['senza_prima_nota'] ?? 0 }}</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Già collegati</div>
<div class="mt-1 text-lg font-semibold text-slate-900">{{ $ricStats['collegati'] ?? 0 }}</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-slate-500">Da confermare</div>
<div class="mt-1 text-lg font-semibold text-slate-900">{{ $ricStats['da_confermare'] ?? 0 }}</div>
</div>
</div>
@if(! $contoImport)
<div class="mt-4 rounded-lg border border-dashed bg-white p-4 text-sm text-slate-500">Seleziona un conto per avviare la riconciliazione.</div>
@elseif(! $ricCurrent)
<div class="mt-4 rounded-lg border border-dashed bg-white p-4 text-sm text-slate-500">Nessun movimento in coda. Il conto sembra già lavorato oppure i movimenti sono tutti collegati.</div>
@else
<div class="mt-4 grid grid-cols-1 gap-4 xl:grid-cols-[minmax(0,1fr)_minmax(340px,0.9fr)]">
<div class="rounded-xl border bg-slate-50 p-4">
<div class="flex items-center justify-between gap-3">
<div>
<div class="text-xs uppercase tracking-wide text-slate-500">Movimento in lavorazione</div>
<div class="mt-1 text-sm text-slate-600">{{ ($this->riconciliazioneOffset ?? 0) + 1 }} di {{ count($ricQueue) }}</div>
</div>
<div class="flex gap-2">
<x-filament::button size="sm" color="gray" wire:click="previousRiconciliazione">Precedente</x-filament::button>
<x-filament::button size="sm" color="gray" wire:click="nextRiconciliazione">Successivo</x-filament::button>
</div>
</div>
<div class="mt-4 rounded-lg border bg-white p-4">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold text-slate-900">{{ $ricCurrent['data'] }}</div>
<div class="mt-1 text-xs text-slate-500">Stato: {{ $ricCurrent['stato'] }}</div>
</div>
<div class="text-right text-lg font-semibold {{ $ricCurrent['importo'] >= 0 ? 'text-emerald-700' : 'text-rose-700' }}">
€ {{ number_format((float) $ricCurrent['importo'], 2, ',', '.') }}
</div>
</div>
<div class="mt-3 text-sm text-slate-700">{{ $ricCurrent['descrizione'] }}</div>
<div class="mt-4 flex flex-wrap gap-2">
<x-filament::button size="sm" color="primary" wire:click="goToHubTab('movimenti')">Apri nel mastrino</x-filament::button>
@if($ricCurrent['has_registrazione'])
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs font-medium text-emerald-700">Ha già una prima nota</span>
@elseif(! empty($ricCurrent['match_label']))
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs font-medium text-emerald-700">{{ $ricCurrent['match_label'] }}</span>
@else
<span class="rounded-full bg-amber-100 px-3 py-1 text-xs font-medium text-amber-700">Da collegare</span>
@endif
</div>
</div>
</div>
<div class="rounded-xl border bg-white p-4">
<div class="text-sm font-semibold text-slate-900">Candidati automatici</div>
<div class="mt-1 text-xs text-slate-600">
@if($ricCurrent['importo'] >= 0)
Match su canoni affitto e incassi registrati per importo, data e testo della causale.
@else
Match su fatture fornitore contabili per importo netto, data e denominazione del fornitore.
@endif
</div>
<div class="mt-4 space-y-3">
@forelse($ricCandidates as $candidate)
<div class="rounded-lg border bg-slate-50 p-3">
<div class="flex items-start justify-between gap-3">
<div>
<div class="text-xs uppercase tracking-wide text-slate-500">{{ $candidate['tipo'] }}</div>
<div class="mt-1 text-sm font-semibold text-slate-900">{{ $candidate['titolo'] }}</div>
</div>
<div class="rounded-full bg-primary-100 px-2.5 py-1 text-xs font-semibold text-primary-700">{{ $candidate['score'] }}%</div>
</div>
<div class="mt-2 text-sm text-slate-700">{{ $candidate['dettaglio'] }}</div>
<div class="mt-2 flex flex-wrap gap-4 text-xs text-slate-500">
<span>Data: {{ $candidate['data'] }}</span>
<span>Importo: € {{ number_format((float) $candidate['importo'], 2, ',', '.') }}</span>
</div>
<div class="mt-2 text-xs text-slate-600">{{ $candidate['motivo'] }}</div>
@if(($candidate['azione'] ?? null) === 'riconcilia_affitto')
<div class="mt-3">
<x-filament::button size="sm" color="success" wire:click="riconciliaCanoneAffitto({{ (int) $candidate['canone_dovuto_id'] }})">
Chiudi canone affitto
</x-filament::button>
</div>
@elseif(($candidate['azione'] ?? null) === 'riconcilia_pagamento_fornitore')
<div class="mt-3">
<x-filament::button size="sm" color="success" wire:click="riconciliaPagamentoFornitore({{ (int) $candidate['fattura_fornitore_id'] }})">
Registra pagamento fornitore
</x-filament::button>
</div>
@endif
</div>
@empty
<div class="rounded-lg border border-dashed bg-slate-50 p-4 text-sm text-slate-500">Nessun candidato convincente. In questo caso loperatore lavora dal mastrino e conferma manualmente il collegamento.</div>
@endforelse
</div>
</div>
</div>
@endif
</x-filament::section>
@elseif($this->hubTab === 'movimenti')
<x-filament::section>
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold">Import unico estratti</div>
<div class="mt-1 text-xs text-gray-600">
Seleziona il conto o la cassa corretta e importa il file nel formato relativo. Il collegamento al conto resta esplicito, senza inferenze dal file.
</div>
<div class="mt-2 text-xs text-slate-700">Per i file <span class="font-semibold">.qif</span> puliamo i movimenti nei gruppi operativi e leggiamo <span class="font-semibold">CBILL</span>, <span class="font-semibold">SIA</span>, commissioni e fornitore favorito per proporre subito il collegamento con fatture e prima nota.</div>
@if($contoImport)
<div class="mt-2 text-xs text-gray-700">
Conto selezionato: <span class="font-medium">{{ $contoImport['label'] }}</span>
</div>
@endif
</div>
<div class="flex flex-wrap gap-2">
<x-filament::button type="button" color="gray" wire:click="mountAction('aggiungi_movimento_manuale')">
Nuovo movimento manuale
</x-filament::button>
<x-filament::button type="button" color="primary" wire:click="mountAction('importa_estratto_unificato')">
Importa estratto
</x-filament::button>
</div>
</div>
</x-filament::section>
<x-filament::section>
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="text-sm font-medium">
{{ $hdr['label'] }}
@if($hdr['saldo'] !== null && $hdr['data'])
· saldo al: {{ $hdr['data'] }} € {{ number_format((float) $hdr['saldo'], 2, ',', '.') }}
@endif
</div>
<div class="text-xs text-gray-600">Filtra per periodo/gestione dai filtri tabella.</div>
</div>
@if($this->movimentiFocusFrom || $this->movimentiFocusTo)
<div class="mt-4 flex flex-wrap items-center justify-between gap-3 rounded-lg border bg-amber-50 p-3 text-sm text-amber-900">
<div>
Filtro rapido attivo sul periodo
<span class="font-semibold">{{ $this->movimentiFocusFrom ?: '' }}</span>
<span class="font-semibold">{{ $this->movimentiFocusTo ?: '' }}</span>
</div>
<x-filament::button size="sm" color="gray" wire:click="clearMovimentiFocus">Rimuovi focus</x-filament::button>
</div>
@endif
<div class="mt-4 grid grid-cols-1 gap-3 lg:grid-cols-4">
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-gray-500">Periodo</div>
<div class="mt-2 flex flex-wrap gap-2">
<select wire:model="periodoTipo" class="rounded border-gray-300 text-xs">
<option value="mese">Mese</option>
<option value="trimestre">Trimestre</option>
</select>
<select wire:model="periodoValore" class="rounded border-gray-300 text-xs">
@foreach(($periodoOptions[$periodoTipo] ?? []) as $val => $label)
<option value="{{ $val }}">{{ $label }}</option>
@endforeach
</select>
<input type="number" wire:model="periodoAnno" class="w-24 rounded border-gray-300 text-xs" min="2000" max="2100" />
</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-gray-500">Totali periodo ({{ $periodo['label'] ?? '' }})</div>
<div class="mt-2 text-xs">
<div>Movimenti: <span class="font-semibold">{{ $periodo['count'] ?? 0 }}</span></div>
<div>Entrate: <span class="font-semibold">€ {{ number_format((float)($periodo['entrate'] ?? 0), 2, ',', '.') }}</span></div>
<div>Uscite: <span class="font-semibold">€ {{ number_format((float)($periodo['uscite'] ?? 0), 2, ',', '.') }}</span></div>
</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-gray-500">Periodo rate (senza anno)</div>
<div class="mt-2 flex flex-wrap gap-2">
<select wire:model="periodoRate" class="rounded border-gray-300 text-xs">
<option value="">—</option>
@foreach($periodoRateOptions as $val => $label)
<option value="{{ $val }}">{{ $label }}</option>
@endforeach
</select>
</div>
<div class="mt-2 text-xs">
<div>Movimenti: <span class="font-semibold">{{ $periodoRate['count'] ?? 0 }}</span></div>
<div>Entrate: <span class="font-semibold">€ {{ number_format((float)($periodoRate['entrate'] ?? 0), 2, ',', '.') }}</span></div>
<div>Uscite: <span class="font-semibold">€ {{ number_format((float)($periodoRate['uscite'] ?? 0), 2, ',', '.') }}</span></div>
</div>
</div>
<div class="rounded-lg border bg-white p-3">
<div class="text-xs text-gray-500">Saldo periodo</div>
<div class="mt-3 text-lg font-semibold">€ {{ number_format((float)($periodo['saldo'] ?? 0), 2, ',', '.') }}</div>
</div>
</div>
<div class="mt-4 rounded-lg border bg-slate-50 p-3">
<div class="flex flex-wrap items-center justify-between gap-2">
<div>
<div class="text-sm font-semibold text-slate-900">Snapshot ufficiali / estratti conto</div>
<div class="text-xs text-slate-600">I saldi ufficiali ancorano il ricalcolo del conto anche quando il conto non ha IBAN.</div>
</div>
<x-filament::button type="button" size="sm" color="gray" wire:click="mountAction('registra_saldo_estratto')">
Registra saldo / estratto
</x-filament::button>
</div>
<div class="mt-3 grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
@forelse($snapshotCards as $card)
<div class="rounded-lg border bg-white p-3 text-sm">
<div class="flex items-start justify-between gap-2">
<div class="font-medium text-slate-900">{{ $card['tipo'] }}</div>
<div class="text-xs text-slate-500">{{ $card['data'] ?? '' }}</div>
</div>
@if(!empty($card['is_partenza_contabile']))
<div class="mt-2 inline-flex items-center gap-1 rounded-full bg-sky-100 px-2.5 py-1 text-[11px] font-semibold text-sky-700">
<x-heroicon-o-flag class="h-3.5 w-3.5" />
Partenza contabile
</div>
@endif
<div class="mt-2 text-lg font-semibold text-slate-900">€ {{ number_format((float) ($card['saldo'] ?? 0), 2, ',', '.') }}</div>
<div class="mt-1 text-xs text-slate-600">{{ $card['periodo'] }}</div>
@if(!empty($card['documento_url']) && !empty($card['documento_label']))
<button type="button" wire:click="openSaldoDocumento({{ $card['id'] }})" class="mt-2 inline-flex text-xs font-medium text-indigo-700 hover:underline">{{ $card['documento_label'] }}</button>
@endif
</div>
@empty
<div class="rounded-lg border border-dashed bg-white p-3 text-sm text-slate-500 md:col-span-2 xl:col-span-3">Nessuno snapshot ufficiale registrato per il conto selezionato.</div>
@endforelse
</div>
</div>
<div class="mt-4">
{{ $this->table }}
</div>
</x-filament::section>
@elseif($this->hubTab === 'associazione_causali')
<x-filament::section>
<x-slot name="heading">Associazione Causali e Regole Bancarie</x-slot>
<x-slot name="description">Configura i conti Dare e Avere per ciascun codice causale rilevato nei movimenti banca.</x-slot>
@php($assocRows = $this->getCausaliAssociazioneRows())
<div class="mt-4 overflow-x-auto rounded-lg border">
<table class="w-full text-left text-sm divide-y divide-gray-200 dark:divide-gray-800">
<thead class="bg-gray-50 dark:bg-gray-800">
<tr>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300">Causale bancaria</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300">Descrizione rilevata</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300 text-center">Movimenti</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300">Conto Dare (Entrate)</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300">Conto Avere (Uscite)</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300 text-center">Stato regola</th>
<th class="px-4 py-3 font-semibold text-gray-700 dark:text-gray-300 text-right">Azioni</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-800 bg-white dark:bg-gray-900">
@forelse($assocRows as $row)
<tr>
<td class="px-4 py-3 font-mono font-bold text-gray-900 dark:text-gray-100">
{{ $row['causale'] }}
</td>
<td class="px-4 py-3 text-gray-600 dark:text-gray-400">
{{ $row['descrizione'] }}
</td>
<td class="px-4 py-3 text-center font-semibold">
{{ $row['count'] }}
</td>
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">
@if($row['conto_dare'])
<span class="inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-900/30 px-2 py-1 text-xs font-medium text-blue-700 dark:text-blue-300 border border-blue-200 dark:border-blue-800">
{{ $row['conto_dare'] }}
</span>
@else
<span class="text-xs text-gray-400">—</span>
@endif
</td>
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">
@if($row['conto_avere'])
<span class="inline-flex items-center rounded-md bg-blue-50 dark:bg-blue-900/30 px-2 py-1 text-xs font-medium text-blue-700 dark:text-blue-300 border border-blue-200 dark:border-blue-800">
{{ $row['conto_avere'] }}
</span>
@else
<span class="text-xs text-gray-400">—</span>
@endif
</td>
<td class="px-4 py-3 text-center">
@if($row['attiva'])
<span class="inline-flex items-center gap-1 rounded-full bg-emerald-100 dark:bg-emerald-950/30 px-2.5 py-0.5 text-xs font-semibold text-emerald-800 dark:text-emerald-300 border border-emerald-200 dark:border-emerald-900">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
Attiva
</span>
@else
<span class="inline-flex items-center gap-1 rounded-full bg-amber-100 dark:bg-amber-950/30 px-2.5 py-0.5 text-xs font-semibold text-amber-800 dark:text-amber-300 border border-amber-200 dark:border-amber-900">
<span class="w-1.5 h-1.5 rounded-full bg-amber-500"></span>
Configurazione mancante
</span>
@endif
</td>
<td class="px-4 py-3 text-right">
<x-filament::button
size="sm"
color="{{ $row['attiva'] ? 'gray' : 'primary' }}"
wire:click="startConfiguringRegolaCausale('{{ $row['causale'] }}')"
>
{{ $row['attiva'] ? 'Modifica regola' : 'Configura regola' }}
</x-filament::button>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="px-4 py-6 text-center text-gray-500">
Nessun movimento banca importato con codici causale rilevati.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</x-filament::section>
@endif
@endif
</div>
@if($this->pdfViewerUrl)
<div class="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/70 p-4">
<div class="flex h-[92vh] w-full max-w-7xl flex-col overflow-hidden rounded-2xl bg-white shadow-2xl">
<div class="flex items-center justify-between border-b px-5 py-3">
<div>
<div class="text-sm font-semibold text-slate-900">{{ $this->pdfViewerTitle ?? 'Documento PDF' }}</div>
<div class="text-xs text-slate-500">Viewer PDF inline standard per saldi, estratti e documenti collegati.</div>
</div>
<div class="flex items-center gap-2">
@if($this->pdfViewerOpenUrl)
<a href="{{ $this->pdfViewerOpenUrl }}" target="_blank" rel="noopener" class="inline-flex items-center rounded-md bg-slate-800 px-3 py-1.5 text-xs font-medium text-white hover:bg-slate-700">Apri in nuova scheda</a>
@endif
<x-filament::button type="button" color="gray" size="sm" wire:click="closePdfViewer">Chiudi</x-filament::button>
</div>
</div>
<div class="min-h-0 flex-1 bg-slate-100 p-4">
@include('filament.modals.pdf-viewer', ['url' => $this->pdfViewerUrl, 'openUrl' => $this->pdfViewerOpenUrl, 'title' => $this->pdfViewerTitle])
</div>
</div>
</div>
@endif
<x-filament-actions::modals />
</x-filament-panels::page>