315 lines
22 KiB
PHP
315 lines
22 KiB
PHP
<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' => 'Hub Pagamenti', 'url' => null],
|
|
]"
|
|
/>
|
|
|
|
@php
|
|
$stabile = $this->getActiveStabile();
|
|
@endphp
|
|
|
|
@if(! $stabile)
|
|
<x-filament::section>
|
|
<div class="text-sm text-gray-600 dark:text-gray-400">Seleziona uno stabile per vedere l'Hub Pagamenti.</div>
|
|
</x-filament::section>
|
|
@else
|
|
<!-- Info stabile attivo -->
|
|
<x-filament::section>
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div class="space-y-1">
|
|
<div class="text-sm text-gray-500">Stabile attivo</div>
|
|
<div class="text-lg font-semibold text-gray-900 dark:text-gray-100">
|
|
{{ $stabile->codice_operatore ?? $stabile->codice_stabile ?? '—' }} — {{ $stabile->denominazione ?? 'Stabile' }}
|
|
</div>
|
|
</div>
|
|
<div class="text-right">
|
|
<div class="text-xs text-gray-500">IBAN principale</div>
|
|
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">{{ $stabile->iban_principale ?? '—' }}</div>
|
|
</div>
|
|
</div>
|
|
</x-filament::section>
|
|
|
|
<!-- Navigazione Tab Premium -->
|
|
<div class="border-b border-gray-200 dark:border-gray-800">
|
|
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
|
|
<button type="button"
|
|
wire:click="setTab('debiti')"
|
|
class="whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-all {{ $activeTab === 'debiti' ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700' }}">
|
|
Da Pagare (Scadenze)
|
|
</button>
|
|
<button type="button"
|
|
wire:click="setTab('movimenti')"
|
|
class="whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-all {{ $activeTab === 'movimenti' ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700' }}">
|
|
Movimenti Bancari (Quadratura)
|
|
</button>
|
|
<button type="button"
|
|
wire:click="setTab('stato_debiti')"
|
|
class="whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-all {{ $activeTab === 'stato_debiti' ? 'border-cyan-500 text-cyan-600 dark:text-cyan-400' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700' }}">
|
|
Stato Debiti a Data
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
|
|
<!-- Tab 1: Da Pagare -->
|
|
@if($activeTab === 'debiti')
|
|
<x-filament::section>
|
|
<x-slot name="heading">
|
|
<div class="flex items-center justify-between">
|
|
<span>Fatture Fornitori in Scadenza</span>
|
|
<span class="rounded-full bg-cyan-100 dark:bg-cyan-900/30 px-3 py-1 text-xs font-semibold text-cyan-800 dark:text-cyan-400">
|
|
{{ count($debiti) }} scadenze pendenti
|
|
</span>
|
|
</div>
|
|
</x-slot>
|
|
|
|
<x-slot name="description">
|
|
Copia rapidamente l'IBAN e la causale con tag `FAT-ID:{id}` per effettuare i bonifici e consentire la riconciliazione automatica degli estratti conto.
|
|
</x-slot>
|
|
|
|
<div class="overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-800">
|
|
<table class="min-w-full divide-y divide-gray-200 text-sm dark:divide-gray-800">
|
|
<thead class="bg-gray-50 text-left text-xs font-semibold text-gray-600 dark:bg-gray-900 dark:text-gray-300">
|
|
<tr>
|
|
<th class="px-4 py-3">Fornitore & Scadenza</th>
|
|
<th class="px-4 py-3 text-right">Netto da Pagare</th>
|
|
<th class="px-4 py-3">IBAN Beneficiario</th>
|
|
<th class="px-4 py-3">Causale Bonifico (Max 140 car.)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
@forelse($debiti as $d)
|
|
<tr class="hover:bg-cyan-50/20 dark:hover:bg-cyan-950/10 transition-colors">
|
|
<td class="px-4 py-3 align-top">
|
|
<div class="font-medium text-gray-900 dark:text-gray-100">{{ $d['fornitore_ragione_sociale'] }}</div>
|
|
<div class="mt-0.5 text-xs text-gray-500">
|
|
Doc. n. <span class="font-semibold">{{ $d['numero_documento'] }}</span> del {{ $d['data_documento'] }} (ID: #{{ $d['id'] }})
|
|
</div>
|
|
</td>
|
|
<td class="px-4 py-3 text-right font-semibold text-gray-900 dark:text-gray-100 align-top whitespace-nowrap">
|
|
€ {{ number_format($d['netto_da_pagare'], 2, ',', '.') }}
|
|
</td>
|
|
<td class="px-4 py-3 align-top whitespace-nowrap">
|
|
@if($d['iban'])
|
|
<div class="flex items-center gap-2">
|
|
<code class="rounded bg-gray-100 dark:bg-gray-800 px-2 py-1 text-xs font-semibold text-cyan-800 dark:text-cyan-400">
|
|
{{ $d['iban'] }}
|
|
</code>
|
|
<button type="button"
|
|
onclick="copyTextToClipboard(this, '{{ $d['iban'] }}')"
|
|
class="inline-flex items-center rounded-md bg-white dark:bg-gray-850 px-2 py-1 text-xs font-medium text-cyan-800 dark:text-cyan-400 ring-1 ring-inset ring-cyan-300 dark:ring-cyan-800 hover:bg-cyan-50/30 transition shadow-sm">
|
|
<span>Copia</span>
|
|
</button>
|
|
</div>
|
|
@else
|
|
<span class="text-xs text-amber-600 font-semibold bg-amber-50 dark:bg-amber-950/20 px-2 py-1 rounded">IBAN non registrato</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-4 py-3 align-top">
|
|
<div class="flex items-start gap-2">
|
|
<div class="flex-1 max-w-xs text-xs bg-gray-50 dark:bg-gray-900 px-2 py-1 rounded border border-gray-100 dark:border-gray-800 break-all select-all font-mono">
|
|
{{ $d['descrizione_bonifico'] }}
|
|
</div>
|
|
<button type="button"
|
|
onclick="copyTextToClipboard(this, '{{ addslashes($d['descrizione_bonifico']) }}')"
|
|
class="inline-flex items-center rounded-md bg-white dark:bg-gray-850 px-2 py-1 text-xs font-medium text-cyan-800 dark:text-cyan-400 ring-1 ring-inset ring-cyan-300 dark:ring-cyan-800 hover:bg-cyan-50/30 transition shadow-sm">
|
|
<span>Copia</span>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="4" class="px-4 py-6 text-center text-gray-500">
|
|
Nessun debito da pagare trovato per questo stabile.
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</x-filament::section>
|
|
@endif
|
|
|
|
<!-- Tab 2: Movimenti Bancari -->
|
|
@if($activeTab === 'movimenti')
|
|
<x-filament::section>
|
|
<x-slot name="heading">Quadratura Movimenti Bancari</x-slot>
|
|
<x-slot name="description">
|
|
Monitora l'estratto conto importato. I movimenti quadrati sono associati alla prima nota o al pagamento delle fatture, mentre quelli da quadrare indicano i flussi ancora da registrare.
|
|
</x-slot>
|
|
|
|
<div class="overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-800">
|
|
<table class="min-w-full divide-y divide-gray-200 text-sm dark:divide-gray-800">
|
|
<thead class="bg-gray-50 text-left text-xs font-semibold text-gray-600 dark:bg-gray-900 dark:text-gray-300">
|
|
<tr>
|
|
<th class="px-4 py-3">Data</th>
|
|
<th class="px-4 py-3">Descrizione Movimento</th>
|
|
<th class="px-4 py-3 text-right">Importo</th>
|
|
<th class="px-4 py-3">Stato Riconciliazione</th>
|
|
<th class="px-4 py-3">Note / Collegamenti</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
@forelse($movimenti as $m)
|
|
<tr class="hover:bg-cyan-50/20 dark:hover:bg-cyan-950/10 transition-colors">
|
|
<td class="px-4 py-3 align-top whitespace-nowrap">{{ $m['data'] }}</td>
|
|
<td class="px-4 py-3 align-top">
|
|
<div class="font-medium text-gray-900 dark:text-gray-100">{{ $m['descrizione'] }}</div>
|
|
</td>
|
|
<td class="px-4 py-3 text-right font-semibold align-top whitespace-nowrap {{ $m['importo'] < 0 ? 'text-red-600 dark:text-red-400' : 'text-green-600 dark:text-green-400' }}">
|
|
€ {{ number_format($m['importo'], 2, ',', '.') }}
|
|
</td>
|
|
<td class="px-4 py-3 align-top whitespace-nowrap">
|
|
@if($m['stato'] === 'quadrato')
|
|
<span class="inline-flex items-center gap-1.5 rounded-full bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-semibold text-emerald-800 dark:text-emerald-400">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-emerald-500"></span>
|
|
Quadrato
|
|
</span>
|
|
@else
|
|
<span class="inline-flex items-center gap-1.5 rounded-full bg-amber-100 dark:bg-amber-900/30 px-2 py-1 text-xs font-semibold text-amber-800 dark:text-amber-400">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-amber-500"></span>
|
|
Da quadrare
|
|
</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-4 py-3 align-top text-xs text-gray-500">
|
|
@if($m['stato'] === 'quadrato')
|
|
@if($m['invoice_id'])
|
|
<span class="font-semibold text-gray-700 dark:text-gray-300">Pagata Fattura #{{ $m['invoice_number'] }}</span>
|
|
@if($m['fornitore'])
|
|
di <span class="font-medium">{{ $m['fornitore'] }}</span>
|
|
@endif
|
|
@else
|
|
<span class="italic text-gray-400">Registrato in prima nota</span>
|
|
@endif
|
|
@else
|
|
<span class="text-amber-700 dark:text-amber-500 leading-normal">{{ $m['advice'] }}</span>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="5" class="px-4 py-6 text-center text-gray-500">
|
|
Nessun movimento bancario trovato.
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</x-filament::section>
|
|
@endif
|
|
|
|
<!-- Tab 3: Stato Debiti a Data -->
|
|
@if($activeTab === 'stato_debiti')
|
|
<x-filament::section>
|
|
<x-slot name="heading">
|
|
<div class="flex items-center justify-between">
|
|
<span>Situazione Debiti ad una Data Specifica</span>
|
|
<div class="flex items-center gap-2">
|
|
<label for="targetDate" class="text-xs text-gray-500">Analizza alla data:</label>
|
|
<input type="date"
|
|
id="targetDate"
|
|
wire:model.live="targetDate"
|
|
class="rounded-md border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-xs text-gray-900 dark:text-gray-100 shadow-sm focus:border-cyan-500 focus:ring-cyan-500" />
|
|
</div>
|
|
</div>
|
|
</x-slot>
|
|
|
|
<x-slot name="description">
|
|
Questo report mostra tutti i debiti (fatture fornitori) che erano aperti alla data indicata (es. data di fine gestione) e indica quando sono stati pagati (data di chiusura del debito), consentendo di analizzare i pagamenti avvenuti dopo il termine.
|
|
</x-slot>
|
|
|
|
<!-- Card Riepilogativa Saldo Debiti -->
|
|
<div class="mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
<div class="rounded-lg border border-gray-200 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-900/50 p-4">
|
|
<div class="text-sm font-medium text-gray-500">Esposizione Debitoria Complessiva alla data</div>
|
|
<div class="mt-2 text-2xl font-bold text-gray-900 dark:text-gray-100">
|
|
€ {{ number_format($totaleDebitiStorici, 2, ',', '.') }}
|
|
</div>
|
|
<div class="mt-1 text-xs text-gray-400">Somma delle fatture con data documento antecedente o uguale al {{ \Illuminate\Support\Carbon::parse($targetDate)->format('d/m/Y') }} e non ancora liquidate a quella data.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto rounded-lg border border-gray-200 dark:border-gray-800">
|
|
<table class="min-w-full divide-y divide-gray-200 text-sm dark:divide-gray-800">
|
|
<thead class="bg-gray-50 text-left text-xs font-semibold text-gray-600 dark:bg-gray-900 dark:text-gray-300">
|
|
<tr>
|
|
<th class="px-4 py-3">Fornitore</th>
|
|
<th class="px-4 py-3">Dettagli Fattura</th>
|
|
<th class="px-4 py-3 text-right">Importo Residuo</th>
|
|
<th class="px-4 py-3">Stato Corrente</th>
|
|
<th class="px-4 py-3">Data Chiusura Debito</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-800">
|
|
@forelse($debitiStorici as $ds)
|
|
<tr class="hover:bg-cyan-50/20 dark:hover:bg-cyan-950/10 transition-colors">
|
|
<td class="px-4 py-3 align-top font-medium text-gray-900 dark:text-gray-100">{{ $ds['fornitore'] }}</td>
|
|
<td class="px-4 py-3 align-top">
|
|
Doc. n. <span class="font-semibold">{{ $ds['numero_documento'] }}</span> del {{ $ds['data_documento'] }}
|
|
</td>
|
|
<td class="px-4 py-3 text-right font-semibold text-gray-900 dark:text-gray-100 align-top whitespace-nowrap">
|
|
€ {{ number_format($ds['netto_da_pagare'], 2, ',', '.') }}
|
|
</td>
|
|
<td class="px-4 py-3 align-top whitespace-nowrap">
|
|
@if($ds['stato_corrente'] === 'pagato')
|
|
<span class="rounded bg-emerald-100 dark:bg-emerald-900/30 px-2 py-0.5 text-xs font-semibold text-emerald-800 dark:text-emerald-400">
|
|
Pagato oggi
|
|
</span>
|
|
@else
|
|
<span class="rounded bg-amber-100 dark:bg-amber-900/30 px-2 py-0.5 text-xs font-semibold text-amber-800 dark:text-amber-400">
|
|
In attesa
|
|
</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-4 py-3 align-top font-medium whitespace-nowrap">
|
|
@if($ds['data_chiusura'] === 'Ancora aperto')
|
|
<span class="text-amber-600 dark:text-amber-500 bg-amber-50 dark:bg-amber-950/20 px-2 py-0.5 rounded text-xs">Ancora aperto</span>
|
|
@else
|
|
<span class="text-green-700 dark:text-green-400 bg-green-50 dark:bg-green-950/20 px-2 py-0.5 rounded text-xs">
|
|
Chiuso il {{ $ds['data_chiusura'] }}
|
|
</span>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="5" class="px-4 py-6 text-center text-gray-500">
|
|
Nessun debito aperto rilevato alla data del {{ \Illuminate\Support\Carbon::parse($targetDate)->format('d/m/Y') }}.
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</x-filament::section>
|
|
@endif
|
|
@endif
|
|
</div>
|
|
|
|
<script>
|
|
function copyTextToClipboard(button, text) {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
const span = button.querySelector('span');
|
|
const originalText = span.textContent;
|
|
|
|
span.textContent = 'Copiato!';
|
|
button.classList.remove('text-cyan-800', 'ring-cyan-300');
|
|
button.classList.add('text-green-700', 'ring-green-400', 'bg-green-50');
|
|
|
|
setTimeout(() => {
|
|
span.textContent = originalText;
|
|
button.classList.add('text-cyan-800', 'ring-cyan-300');
|
|
button.classList.remove('text-green-700', 'ring-green-400', 'bg-green-50');
|
|
}, 1200);
|
|
}).catch(err => {
|
|
console.error('Could not copy text: ', err);
|
|
});
|
|
}
|
|
</script>
|
|
</x-filament-panels::page>
|