609 lines
43 KiB
PHP
Executable File
609 lines
43 KiB
PHP
Executable File
<x-filament-panels::page>
|
||
<div class="mx-auto max-w-7xl space-y-4" x-data="{ openDocumentoModal: false }">
|
||
<x-filament.components.page-breadcrumbs
|
||
:breadcrumbs="collect($this->getBreadcrumbs())->map(fn ($url, $label) => ['label' => $label, 'url' => $url])->values()->all()"
|
||
:back-url="$this->getBackUrl()"
|
||
/>
|
||
|
||
<div class="rounded-xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900">
|
||
<div class="flex flex-wrap items-start justify-between gap-4">
|
||
<div>
|
||
<div class="text-sm font-semibold text-slate-900 dark:text-slate-100">Hub fattura ricevuta</div>
|
||
<div class="mt-1 text-xs text-slate-500 dark:text-slate-400">La scheda è organizzata per TAB operative: quadro generale, documento, acqua e XML. Le azioni non stanno più tutte nell’header.</div>
|
||
</div>
|
||
<div class="flex flex-wrap gap-2">
|
||
<button type="button" wire:click="setHubTab('overview')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $hubTab === 'overview' ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}">Quadro</button>
|
||
<button type="button" wire:click="setHubTab('documento')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $hubTab === 'documento' ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}">Documento</button>
|
||
<button type="button" wire:click="setHubTab('acqua')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $hubTab === 'acqua' ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}">Acqua</button>
|
||
<button type="button" wire:click="setHubTab('xml')" class="inline-flex items-center rounded-md px-3 py-1.5 text-xs font-medium {{ $hubTab === 'xml' ? 'bg-slate-900 text-white' : 'bg-slate-100 text-slate-700 hover:bg-slate-200' }}">XML</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-4 grid gap-3 lg:grid-cols-4">
|
||
<div class="rounded-lg border border-slate-200 bg-slate-50 p-3">
|
||
<div class="text-[11px] uppercase tracking-wide text-slate-500">Documento</div>
|
||
<div class="mt-3 flex flex-wrap gap-2">
|
||
<button type="button" wire:click="mountAction('visualizza_pdf_modal')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-slate-700 ring-1 ring-inset ring-slate-300 hover:bg-slate-100">Vedi PDF</button>
|
||
<button type="button" wire:click="mountAction('rigenera_pdf')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-slate-700 ring-1 ring-inset ring-slate-300 hover:bg-slate-100">Rigenera PDF</button>
|
||
<button type="button" wire:click="mountAction('estrai_testo_pdf')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-slate-700 ring-1 ring-inset ring-slate-300 hover:bg-slate-100">Estrai testo</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-lg border border-sky-200 bg-sky-50 p-3">
|
||
<div class="text-[11px] uppercase tracking-wide text-sky-700">Acqua</div>
|
||
<div class="mt-3 flex flex-wrap gap-2">
|
||
<button type="button" wire:click="mountAction('leggi_pdf_acqua_guidata')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-sky-700 ring-1 ring-inset ring-sky-300 hover:bg-sky-100">Leggi PDF guidata</button>
|
||
<button type="button" wire:click="mountAction('estrai_dati_acqua')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-sky-700 ring-1 ring-inset ring-sky-300 hover:bg-sky-100">Estrai dati</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-lg border border-amber-200 bg-amber-50 p-3">
|
||
<div class="text-[11px] uppercase tracking-wide text-amber-700">Anagrafica</div>
|
||
<div class="mt-3 flex flex-wrap gap-2">
|
||
<button type="button" wire:click="mountAction('modifica')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-300 hover:bg-amber-100">Modifica</button>
|
||
@if((int) ($fattura->fornitore_id ?? 0) > 0)
|
||
<button type="button" wire:click="mountAction('apri_fornitore')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-300 hover:bg-amber-100">Apri fornitore</button>
|
||
@else
|
||
<button type="button" wire:click="mountAction('crea_fornitore')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-amber-700 ring-1 ring-inset ring-amber-300 hover:bg-amber-100">Crea fornitore</button>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-lg border border-emerald-200 bg-emerald-50 p-3">
|
||
<div class="text-[11px] uppercase tracking-wide text-emerald-700">Contabilità</div>
|
||
<div class="mt-3 flex flex-wrap gap-2">
|
||
@if($this->needsCompleta())
|
||
<button type="button" wire:click="mountAction('completa')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-emerald-700 ring-1 ring-inset ring-emerald-300 hover:bg-emerald-100">Completa</button>
|
||
@endif
|
||
@if(! empty($this->contabilitaFatturaId))
|
||
<button type="button" wire:click="mountAction('apri_contabilita')" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-emerald-700 ring-1 ring-inset ring-emerald-300 hover:bg-emerald-100">Apri contabilità</button>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@if($hubTab === 'overview')
|
||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-3">
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="text-sm text-gray-500 dark:text-gray-400">Fattura</div>
|
||
<div class="mt-1 text-xl font-semibold">
|
||
{{ $fattura->numero_fattura }}
|
||
</div>
|
||
|
||
<dl class="mt-4 space-y-2 text-sm">
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Data</dt>
|
||
<dd class="font-medium">{{ optional($fattura->data_fattura)->format('d/m/Y') }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Scadenza</dt>
|
||
<dd class="font-medium">{{ optional($fattura->data_scadenza)->format('d/m/Y') ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Stato</dt>
|
||
<dd class="font-medium">{{ $fattura->stato }}</dd>
|
||
</div>
|
||
|
||
@php
|
||
$modalitaLabel = $this->getPagamentoModalitaXsdLabel();
|
||
@endphp
|
||
@if(is_string($fattura->pagamento_modalita) && trim($fattura->pagamento_modalita) !== '')
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Modalità pagamento</dt>
|
||
<dd class="font-medium text-right">
|
||
<div>{{ trim($fattura->pagamento_modalita) }}</div>
|
||
@if($modalitaLabel)
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">{{ $modalitaLabel }}</div>
|
||
@endif
|
||
@if(auth()->user()?->hasRole('super-admin'))
|
||
<div class="text-xs">
|
||
<a class="underline" href="{{ \App\Filament\Pages\SuperAdmin\CodiciFatturaElettronicaXsd::getUrl(panel: 'admin-filament') }}?domain={{ urlencode('ModalitaPagamentoType') }}" target="_blank" rel="noopener">Vedi codici</a>
|
||
</div>
|
||
@endif
|
||
</dd>
|
||
</div>
|
||
@endif
|
||
|
||
@if(!empty($fattura->consumo_valore) || (is_string($fattura->consumo_riferimento) && trim($fattura->consumo_riferimento) !== ''))
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Consumo (acqua)</dt>
|
||
<dd class="font-medium text-right">
|
||
<div>
|
||
{{ $fattura->consumo_valore !== null ? number_format((float) $fattura->consumo_valore, 3, ',', '.') : '—' }}
|
||
{{ $fattura->consumo_unita ?: 'mc' }}
|
||
</div>
|
||
@if(is_string($fattura->consumo_riferimento) && trim($fattura->consumo_riferimento) !== '')
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">{{ trim($fattura->consumo_riferimento) }}</div>
|
||
@endif
|
||
</dd>
|
||
</div>
|
||
@endif
|
||
</dl>
|
||
</div>
|
||
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="text-sm text-gray-500 dark:text-gray-400">Fornitore (da XML)</div>
|
||
<div class="mt-1 text-lg font-semibold">
|
||
{{ $fattura->fornitore_denominazione }}
|
||
</div>
|
||
<dl class="mt-4 space-y-2 text-sm">
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">P.IVA</dt>
|
||
<dd class="font-medium">{{ $fattura->fornitore_piva ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">C.F.</dt>
|
||
<dd class="font-medium">{{ $fattura->fornitore_cf ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Fornitore agganciato</dt>
|
||
<dd class="font-medium">{{ $this->getFornitoreAgganciatoLabel() ?: '—' }}</dd>
|
||
</div>
|
||
</dl>
|
||
|
||
@php
|
||
$xmlOk = is_string($fattura->xml_content ?? null) ? trim((string) $fattura->xml_content) !== '' : false;
|
||
$pdfOk = (is_string($fattura->allegato_pdf_path ?? null) && trim((string) $fattura->allegato_pdf_path) !== '')
|
||
|| (is_string($fattura->allegato_pdf_hash ?? null) && trim((string) $fattura->allegato_pdf_hash) !== '')
|
||
|| (isset($this->documento) && $this->documento);
|
||
@endphp
|
||
|
||
<div class="mt-4 flex flex-wrap gap-3 text-sm">
|
||
@if($pdfOk)
|
||
<a class="underline" href="{{ route('admin.fatture-elettroniche.download-pdf', ['fattura' => $fattura->id]) }}" target="_blank" rel="noopener">Scarica PDF</a>
|
||
@endif
|
||
@if($xmlOk)
|
||
<a class="underline" href="{{ route('admin.fatture-elettroniche.download-xml', ['fattura' => $fattura->id]) }}" target="_blank" rel="noopener">Scarica FE XML</a>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="text-sm text-gray-500 dark:text-gray-400">Importi</div>
|
||
<dl class="mt-4 space-y-2 text-sm">
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Imponibile</dt>
|
||
<dd class="font-medium">€ {{ number_format((float) $fattura->imponibile, 2, ',', '.') }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">IVA</dt>
|
||
<dd class="font-medium">€ {{ number_format((float) $fattura->iva, 2, ',', '.') }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Totale</dt>
|
||
<dd class="text-base font-semibold">€ {{ number_format((float) $fattura->totale, 2, ',', '.') }}</dd>
|
||
</div>
|
||
|
||
@php
|
||
$ritenuta = is_array($xmlDetails['ritenuta'] ?? null) ? $xmlDetails['ritenuta'] : [];
|
||
$ritenutaImporto = (float) ($ritenuta['importo'] ?? 0);
|
||
$ritenutaAliquota = $ritenuta['aliquota'] ?? null;
|
||
$ritenutaTipo = $ritenuta['tipo'] ?? null;
|
||
$ritenutaCausale = $ritenuta['causale'] ?? null;
|
||
$nettoDaPagare = round(((float) $fattura->totale) - $ritenutaImporto, 2);
|
||
|
||
$scadenzaVersamento = null;
|
||
if ($ritenutaImporto > 0 && $fattura->data_fattura) {
|
||
$scadenzaVersamento = optional($fattura->data_fattura)->copy()->addMonthNoOverflow()->day(16);
|
||
}
|
||
@endphp
|
||
|
||
@if($ritenutaImporto > 0)
|
||
<div class="pt-2">
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Ritenuta d'acconto</div>
|
||
<div class="mt-1 space-y-2">
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Importo</dt>
|
||
<dd class="font-medium">€ {{ number_format($ritenutaImporto, 2, ',', '.') }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Aliquota</dt>
|
||
<dd class="font-medium">{{ $ritenutaAliquota !== null ? number_format((float) $ritenutaAliquota, 2, ',', '.') . '%' : '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Tipo</dt>
|
||
<dd class="font-medium">{{ $ritenutaTipo ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Causale</dt>
|
||
<dd class="font-medium">{{ $ritenutaCausale ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Netto da pagare</dt>
|
||
<dd class="font-medium">€ {{ number_format($nettoDaPagare, 2, ',', '.') }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Versamento (indicativo)</dt>
|
||
<dd class="font-medium">{{ $scadenzaVersamento ? $scadenzaVersamento->format('d/m/Y') : '—' }}</dd>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
</dl>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
@if($hubTab === 'documento')
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="flex items-center justify-between gap-3">
|
||
<div>
|
||
<div class="text-sm font-medium">Documento</div>
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">PDF allegato (se presente) oppure prospetto generato</div>
|
||
@if($this->documento)
|
||
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||
Protocollo: <span class="font-medium">{{ $this->documentoProtocolloConAnno ?: $this->documento->numero_protocollo }}</span>
|
||
·
|
||
<button
|
||
type="button"
|
||
class="underline"
|
||
x-on:click="openDocumentoModal = true"
|
||
>Apri Documento</button>
|
||
</div>
|
||
|
||
@php
|
||
$ocr = is_string($this->documento->contenuto_ocr ?? null)
|
||
? trim((string) $this->documento->contenuto_ocr)
|
||
: '';
|
||
@endphp
|
||
@if($ocr !== '')
|
||
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||
Testo PDF estratto: <span class="font-medium">presente</span> ({{ number_format(mb_strlen($ocr), 0, ',', '.') }} caratteri)
|
||
</div>
|
||
@endif
|
||
@else
|
||
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">Nessun Documento collegato</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
|
||
@php
|
||
$pdfPath = is_string($fattura->allegato_pdf_path) ? trim($fattura->allegato_pdf_path) : '';
|
||
$pdfHash = is_string($fattura->allegato_pdf_hash ?? null) ? trim((string) $fattura->allegato_pdf_hash) : '';
|
||
$hasXml = is_string($fattura->xml_content ?? null) ? trim((string) $fattura->xml_content) !== '' : false;
|
||
|
||
$docPdfPath = '';
|
||
if ($this->documento) {
|
||
$docPdfPath = is_string($this->documento->percorso_file) ? trim($this->documento->percorso_file) : '';
|
||
if ($docPdfPath === '') {
|
||
$docPdfPath = is_string($this->documento->path_file) ? trim($this->documento->path_file) : '';
|
||
}
|
||
}
|
||
|
||
// Se abbiamo un riferimento (path/hash) o l'XML, proviamo comunque a mostrare l'iframe:
|
||
// l'endpoint download-pdf fa auto-repair/rigenerazione se lo storage è stato pulito.
|
||
// Evita di mostrare l'iframe quando non c'è alcun PDF agganciato: in quel caso la rotta scarica-pdf andrà in 404.
|
||
$pdfOk = ($pdfPath !== '' || $docPdfPath !== '' || $pdfHash !== '');
|
||
$righe = is_array($xmlDetails['righe'] ?? null) ? $xmlDetails['righe'] : [];
|
||
$escludiRigheFe = (bool) ($fattura->fornitore?->escludi_righe_fe ?? false);
|
||
@endphp
|
||
|
||
@if($pdfOk)
|
||
<div class="mt-3 overflow-hidden rounded-lg border border-gray-200 dark:border-gray-800">
|
||
<iframe
|
||
title="PDF fattura"
|
||
class="h-[60vh] w-full"
|
||
src="{{ route('admin.fatture-elettroniche.download-pdf', ['fattura' => $fattura->id]) }}?inline=1"
|
||
></iframe>
|
||
</div>
|
||
@else
|
||
<div class="mt-3 rounded-lg border border-gray-200 bg-white p-4 text-sm dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="text-sm text-gray-600 dark:text-gray-300">
|
||
PDF non disponibile (mancante o non ancora spostato nel percorso corretto). Usa “Completa” per riparare/aggiornare.
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
@if($this->documento)
|
||
<div
|
||
x-cloak
|
||
x-show="openDocumentoModal"
|
||
class="fixed inset-0 z-[70]"
|
||
x-on:keydown.escape.window="openDocumentoModal = false"
|
||
>
|
||
<div class="absolute inset-0 bg-black/70" x-on:click="openDocumentoModal = false"></div>
|
||
<div class="relative mx-auto mt-6 h-[92vh] w-[96vw] max-w-7xl overflow-hidden rounded-xl bg-white shadow-2xl dark:bg-gray-900">
|
||
<div class="flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-800">
|
||
<div class="text-sm font-semibold">Documento protocollato (PDF)</div>
|
||
<button
|
||
type="button"
|
||
class="rounded-md px-2 py-1 text-sm text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800"
|
||
x-on:click="openDocumentoModal = false"
|
||
>Chiudi</button>
|
||
</div>
|
||
<iframe
|
||
title="Documento protocollato"
|
||
class="h-[calc(92vh-56px)] w-full"
|
||
src="{{ route('filament.documenti.download', ['documento' => $this->documento->id]) }}?inline=1"
|
||
></iframe>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
<div class="mt-3 rounded-lg border border-gray-200 bg-white p-4 text-sm dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="flex items-start justify-between gap-4">
|
||
<div>
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Fornitore</div>
|
||
<div class="text-base font-semibold">{{ $fattura->fornitore_denominazione }}</div>
|
||
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">P.IVA {{ $fattura->fornitore_piva ?: '—' }} · CF {{ $fattura->fornitore_cf ?: '—' }}</div>
|
||
</div>
|
||
<div class="text-right">
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Fattura</div>
|
||
<div class="text-base font-semibold">{{ $fattura->numero_fattura }}</div>
|
||
<div class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ optional($fattura->data_fattura)->format('d/m/Y') }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
@if($escludiRigheFe)
|
||
<div class="mt-3 text-xs text-gray-500 dark:text-gray-400">
|
||
Righe FE non visualizzate: il fornitore ha attiva l'opzione “Escludi righe FE”.
|
||
</div>
|
||
@elseif(count($righe) > 0)
|
||
<div class="mt-4 overflow-auto">
|
||
<table class="min-w-full text-left text-xs">
|
||
<thead class="text-gray-500 dark:text-gray-400">
|
||
<tr>
|
||
<th class="py-2 pr-3">Riga</th>
|
||
<th class="py-2 pr-3">Descrizione</th>
|
||
<th class="py-2 pr-3">Q.tà</th>
|
||
<th class="py-2 pr-3">Totale</th>
|
||
<th class="py-2 pr-3">IVA%</th>
|
||
<th class="py-2">RA</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="divide-y divide-gray-100 dark:divide-gray-800">
|
||
@foreach($righe as $r)
|
||
<tr>
|
||
<td class="py-2 pr-3 align-top">{{ $r['numero_linea'] ?? '—' }}</td>
|
||
<td class="py-2 pr-3 align-top">{{ $r['descrizione'] ?? '—' }}</td>
|
||
<td class="py-2 pr-3 align-top">{{ isset($r['quantita']) ? number_format((float) $r['quantita'], 2, ',', '.') : '—' }}</td>
|
||
<td class="py-2 pr-3 align-top">€ {{ isset($r['prezzo_totale']) ? number_format((float) $r['prezzo_totale'], 2, ',', '.') : '—' }}</td>
|
||
<td class="py-2 pr-3 align-top">{{ isset($r['aliquota_iva']) ? number_format((float) $r['aliquota_iva'], 2, ',', '.') : '—' }}</td>
|
||
<td class="py-2 align-top">{{ ($r['ritenuta'] ?? false) ? 'SI' : '—' }}</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
@endif
|
||
|
||
<div class="mt-4 flex justify-end">
|
||
<div class="text-right">
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Totale documento</div>
|
||
<div class="text-base font-semibold">€ {{ number_format((float) $fattura->totale, 2, ',', '.') }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
@if($hubTab === 'overview')
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<div class="flex items-center justify-between gap-3">
|
||
<div>
|
||
<div class="text-sm font-medium">Dati destinatario</div>
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Da XML (DatiTrasmissione / CessionarioCommittente) + riferimenti stabile</div>
|
||
</div>
|
||
</div>
|
||
|
||
@php
|
||
$cfStabileNorm = strtoupper(str_replace(' ', '', (string) ($fattura->stabile?->codice_fiscale ?? '')));
|
||
$cfDestNorm = strtoupper(str_replace(' ', '', (string) ($fattura->destinatario_cf ?? '')));
|
||
$cfOk = ($cfStabileNorm !== '' && $cfDestNorm !== '' && $cfStabileNorm === $cfDestNorm);
|
||
@endphp
|
||
|
||
<div class="mt-3 rounded-lg border px-3 py-2 text-xs {{ $cfOk ? 'border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/50 dark:bg-emerald-950/40 dark:text-emerald-200' : 'border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/50 dark:bg-amber-950/40 dark:text-amber-200' }}">
|
||
@if($cfOk)
|
||
Filtro CF stabile: OK. Questa FE e coerente con lo stabile attivo.
|
||
@else
|
||
Filtro CF stabile: non allineato. La lettura guidata PDF acqua viene bloccata finche CF stabile e CF destinatario FE non coincidono.
|
||
@endif
|
||
</div>
|
||
|
||
<dl class="mt-4 grid grid-cols-1 gap-3 text-sm sm:grid-cols-2">
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Stabile</dt>
|
||
<dd class="font-medium">{{ $fattura->stabile?->codice_stabile ? ($fattura->stabile->codice_stabile . ' - ' . $fattura->stabile->denominazione) : '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">CF stabile</dt>
|
||
<dd class="font-medium">{{ $fattura->stabile?->codice_fiscale ?: '—' }}</dd>
|
||
</div>
|
||
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">CF destinatario</dt>
|
||
<dd class="font-medium">{{ $fattura->destinatario_cf ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Destinatario</dt>
|
||
<dd class="font-medium">{{ $fattura->destinatario_denominazione ?: '—' }}</dd>
|
||
</div>
|
||
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Codice destinatario</dt>
|
||
<dd class="font-medium">{{ $fattura->codice_destinatario ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">PEC destinatario</dt>
|
||
<dd class="font-medium">{{ $fattura->pec_destinatario ?: '—' }}</dd>
|
||
</div>
|
||
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">SDI stabile</dt>
|
||
<dd class="font-medium">{{ $fattura->stabile?->codice_destinatario_sdi ?: '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">PEC stabile</dt>
|
||
<dd class="font-medium">{{ $fattura->stabile?->pec_condominio ?: ($fattura->stabile?->pec_amministratore ?: '—') }}</dd>
|
||
</div>
|
||
|
||
@php
|
||
$tx = is_array($xmlDetails['trasmissione'] ?? null) ? $xmlDetails['trasmissione'] : [];
|
||
$idPaese = $tx['id_paese'] ?? null;
|
||
$idCodice = $tx['id_codice'] ?? null;
|
||
$progressivo = $tx['progressivo_invio'] ?? null;
|
||
$formato = $tx['formato_trasmissione'] ?? null;
|
||
@endphp
|
||
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">IdTrasmittente</dt>
|
||
<dd class="font-medium">{{ ($idPaese && $idCodice) ? ($idPaese . $idCodice) : '—' }}</dd>
|
||
</div>
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Progressivo invio</dt>
|
||
<dd class="font-medium">{{ $progressivo ?: '—' }}</dd>
|
||
</div>
|
||
|
||
<div class="flex justify-between gap-4">
|
||
<dt class="text-gray-500 dark:text-gray-400">Formato trasmissione</dt>
|
||
<dd class="font-medium">{{ $formato ?: '—' }}</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
@endif
|
||
|
||
@if($hubTab === 'xml' && !empty($fattura->xml_content))
|
||
<div class="rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-900">
|
||
<details>
|
||
<summary class="cursor-pointer text-sm font-medium">XML importato</summary>
|
||
<pre class="mt-3 overflow-auto rounded-lg bg-gray-50 p-3 text-xs dark:bg-gray-950">{{ $fattura->xml_content }}</pre>
|
||
</details>
|
||
</div>
|
||
@endif
|
||
|
||
@php
|
||
$preview = is_array($acquaPdfPreview ?? null) ? $acquaPdfPreview : [];
|
||
$rawText = is_string($preview['raw_text'] ?? null) ? $preview['raw_text'] : '';
|
||
$parsed = is_array($preview['parsed'] ?? null) ? $preview['parsed'] : [];
|
||
$acquaData = is_array($this->acquaStructuredData ?? null) ? $this->acquaStructuredData : [];
|
||
$acquaCodici = is_array($acquaData['codici'] ?? null) ? $acquaData['codici'] : [];
|
||
$acquaContatore = is_array($acquaData['contatore'] ?? null) ? $acquaData['contatore'] : [];
|
||
$acquaGenerale = is_array($acquaData['generale'] ?? null) ? $acquaData['generale'] : [];
|
||
$acquaPagamento = is_array($acquaData['pagamento'] ?? null) ? $acquaData['pagamento'] : [];
|
||
$acquaFinestra = is_array($acquaData['finestra_autolettura'] ?? null) ? $acquaData['finestra_autolettura'] : [];
|
||
$acquaLetture = is_array($acquaData['riepilogo_letture'] ?? null) ? $acquaData['riepilogo_letture'] : [];
|
||
$acquaConsumo = is_array($acquaData['consumo'] ?? null) ? $acquaData['consumo'] : [];
|
||
@endphp
|
||
|
||
@if($hubTab === 'acqua' || $preview !== [])
|
||
<div class="rounded-xl border border-sky-200 bg-sky-50 p-4 dark:border-sky-900/50 dark:bg-sky-950/20">
|
||
<div class="grid gap-3 md:grid-cols-4">
|
||
<a href="{{ \App\Filament\Pages\Condomini\ServiziStabileArchivio::getUrl(panel: 'admin-filament') }}?tab=fatture" class="rounded-lg border border-sky-200 bg-white p-3 text-sm text-sky-900 hover:bg-sky-100 dark:border-sky-800 dark:bg-gray-900 dark:text-sky-100">
|
||
<div class="text-[11px] uppercase tracking-wide text-sky-600">Servizi acqua</div>
|
||
<div class="mt-1 font-semibold">Fatture per gestione</div>
|
||
</a>
|
||
<a href="{{ \App\Filament\Pages\Supporto\TicketAcquaGenerale::getUrl(panel: 'admin-filament') }}" class="rounded-lg border border-sky-200 bg-white p-3 text-sm text-sky-900 hover:bg-sky-100 dark:border-sky-800 dark:bg-gray-900 dark:text-sky-100">
|
||
<div class="text-[11px] uppercase tracking-wide text-sky-600">Contatore generale</div>
|
||
<div class="mt-1 font-semibold">Ticket acqua generale</div>
|
||
</a>
|
||
<a href="{{ \App\Filament\Pages\Supporto\TicketAcquaLight::getUrl(panel: 'admin-filament') }}" class="rounded-lg border border-sky-200 bg-white p-3 text-sm text-sky-900 hover:bg-sky-100 dark:border-sky-800 dark:bg-gray-900 dark:text-sky-100">
|
||
<div class="text-[11px] uppercase tracking-wide text-sky-600">Letture unità</div>
|
||
<div class="mt-1 font-semibold">Ticket acqua light</div>
|
||
</a>
|
||
<a href="{{ \App\Filament\Pages\Condomini\ContrattiHub::getUrl(panel: 'admin-filament') }}" class="rounded-lg border border-sky-200 bg-white p-3 text-sm text-sky-900 hover:bg-sky-100 dark:border-sky-800 dark:bg-gray-900 dark:text-sky-100">
|
||
<div class="text-[11px] uppercase tracking-wide text-sky-600">Contratti</div>
|
||
<div class="mt-1 font-semibold">Contratti hub</div>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
@if($hubTab === 'acqua')
|
||
<div class="grid gap-4 xl:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]">
|
||
<div class="rounded-xl border border-cyan-200 bg-white p-4 dark:border-cyan-900/50 dark:bg-gray-900">
|
||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Contratto e codici FE acqua</div>
|
||
<div class="mt-3 grid gap-3 sm:grid-cols-2 text-sm">
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Utenza</div><div class="mt-1 font-medium">{{ $acquaCodici['utenza'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Cliente</div><div class="mt-1 font-medium">{{ $acquaCodici['cliente'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Contratto</div><div class="mt-1 font-medium">{{ $acquaCodici['contratto'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Matricola</div><div class="mt-1 font-medium">{{ $acquaContatore['matricola'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">CBILL</div><div class="mt-1 font-medium">{{ $acquaPagamento['cbill'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Codice avviso</div><div class="mt-1 font-medium break-all">{{ $acquaPagamento['codice_avviso'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Cod. SIA</div><div class="mt-1 font-medium">{{ $acquaPagamento['sia'] ?: '—' }}</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-xl border border-cyan-200 bg-white p-4 dark:border-cyan-900/50 dark:bg-gray-900">
|
||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Sintesi operativa contratto</div>
|
||
<div class="mt-3 grid gap-3 sm:grid-cols-2 text-sm">
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Consumo FE</div><div class="mt-1 font-medium">{{ $acquaConsumo['valore'] !== null ? number_format((float) $acquaConsumo['valore'], 3, ',', '.') . ' ' . (($acquaConsumo['unita'] ?? '') ?: 'mc') : '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Riferimento</div><div class="mt-1 font-medium">{{ $acquaConsumo['riferimento'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Tariffa</div><div class="mt-1 font-medium">{{ $acquaGenerale['tariffa_applicata'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Periodicita</div><div class="mt-1 font-medium">{{ $acquaGenerale['periodicita_fatturazione'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Componenti</div><div class="mt-1 font-medium">{{ $acquaGenerale['numero_componenti_totali'] ?: '—' }}</div></div>
|
||
<div><div class="text-xs uppercase tracking-wide text-gray-500">Unita abitative</div><div class="mt-1 font-medium">{{ $acquaGenerale['numero_unita_abitative'] ?: '—' }}</div></div>
|
||
</div>
|
||
<div class="mt-3 rounded-lg bg-cyan-50 px-3 py-2 text-xs text-cyan-900 dark:bg-cyan-950/40 dark:text-cyan-100">
|
||
Finestra autolettura: {{ !empty($acquaFinestra['dal']) || !empty($acquaFinestra['al']) ? (($acquaFinestra['dal'] ?: '—') . ' / ' . ($acquaFinestra['al'] ?: '—')) : '—' }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="rounded-xl border border-cyan-200 bg-white p-4 dark:border-cyan-900/50 dark:bg-gray-900">
|
||
<div class="text-sm font-medium text-gray-900 dark:text-gray-100">Riepilogo letture estratte</div>
|
||
<div class="mt-3 overflow-x-auto">
|
||
<table class="min-w-full text-xs">
|
||
<thead>
|
||
<tr class="border-b border-gray-200 dark:border-gray-800">
|
||
<th class="px-2 py-2 text-left">Tipo</th>
|
||
<th class="px-2 py-2 text-left">Da</th>
|
||
<th class="px-2 py-2 text-left">A</th>
|
||
<th class="px-2 py-2 text-right">Consumo</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@forelse($acquaLetture as $lettura)
|
||
<tr class="border-b border-gray-100 dark:border-gray-800">
|
||
<td class="px-2 py-2">{{ $lettura['tipologia'] ?? '—' }}</td>
|
||
<td class="px-2 py-2">{{ (($lettura['valore_da'] ?? null) !== null ? number_format((float) $lettura['valore_da'], 3, ',', '.') : '—') }} @if(!empty($lettura['data_da'])) · {{ $lettura['data_da'] }} @endif</td>
|
||
<td class="px-2 py-2">{{ (($lettura['valore_a'] ?? null) !== null ? number_format((float) $lettura['valore_a'], 3, ',', '.') : '—') }} @if(!empty($lettura['data_a'])) · {{ $lettura['data_a'] }} @endif</td>
|
||
<td class="px-2 py-2 text-right">{{ ($lettura['consumo'] ?? null) !== null ? number_format((float) $lettura['consumo'], 3, ',', '.') . ' ' . (($lettura['unita'] ?? '') ?: 'mc') : '—' }}</td>
|
||
</tr>
|
||
@empty
|
||
<tr>
|
||
<td colspan="4" class="px-2 py-4 text-center text-gray-500 dark:text-gray-400">Nessun riepilogo letture disponibile su questa FE.</td>
|
||
</tr>
|
||
@endforelse
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
|
||
@if($preview !== [])
|
||
<div class="rounded-xl border border-blue-200 bg-white p-4 dark:border-blue-900/50 dark:bg-gray-900">
|
||
<div class="flex items-center justify-between gap-3">
|
||
<div>
|
||
<div class="text-sm font-medium">Lettura PDF Acqua (Guidata)</div>
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">Anteprima dati estratti dalla FE #{{ $preview['fattura_id'] ?? $fattura->id }} del {{ $preview['generated_at'] ?? '—' }}</div>
|
||
</div>
|
||
<div class="text-xs text-gray-500 dark:text-gray-400">
|
||
CF stabile: <span class="font-medium">{{ $preview['stabile_cf'] ?? '—' }}</span>
|
||
· CF destinatario FE: <span class="font-medium">{{ $preview['destinatario_cf'] ?? '—' }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mt-3 space-y-4">
|
||
<div>
|
||
<div class="text-xs font-medium text-gray-600 dark:text-gray-300">JSON parser acqua (ordinato)</div>
|
||
<pre class="mt-1 max-h-[45vh] overflow-auto whitespace-pre-wrap break-words rounded-lg bg-gray-50 p-3 text-xs dark:bg-gray-950">{{ json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) }}</pre>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="text-xs font-medium text-gray-600 dark:text-gray-300">Testo OCR PDF estratto (completo anteprima)</div>
|
||
<div class="mt-1 text-[11px] text-gray-500 dark:text-gray-400">
|
||
Caratteri: {{ number_format((int) ($preview['chars'] ?? 0), 0, ',', '.') }}
|
||
@if(($preview['truncated'] ?? false) === true)
|
||
· mostrati i primi {{ number_format(mb_strlen($rawText), 0, ',', '.') }}
|
||
@endif
|
||
</div>
|
||
<pre class="mt-1 max-h-[70vh] overflow-auto whitespace-pre-wrap break-words rounded-lg bg-gray-50 p-3 text-xs dark:bg-gray-950">{{ $rawText }}</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
<x-filament-actions::modals />
|
||
</x-filament-panels::page>
|