Files
kreios/backoffice/resources/views/pdf/preventivo.blade.php
carmine.savino 8bef57b64b feat: implement discount and transport features in the quote system
- Added maximum discount settings configurable by the administrator.
- Implemented discount calculations in the quote confirmation process.
- Introduced transport options with associated costs, including handling for exceeding maximum piece limits.
- Updated frontend to display discounts and transport information in the quote summary.
- Created new database migrations for storing discount and transport settings.
- Developed a new Filament page for managing global discount settings.
- Enhanced email templates to include discount and transport details.
- Added tests to ensure proper functionality of discounts and transport calculations.
2026-10-20 17:45:50 +02:00

140 lines
7.7 KiB
PHP
Raw Permalink 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.
@php
use App\Support\ConfigurazioneFormatter;
use Illuminate\Support\Facades\Storage;
$cliente = $preventivo->cliente;
$logoPath = public_path('images/kreios-logo.jpg');
$logoBase64 = file_exists($logoPath) ? base64_encode(file_get_contents($logoPath)) : null;
@endphp
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="utf-8">
<style>
* { font-family: DejaVu Sans, sans-serif; }
body { color: #222; font-size: 12px; margin: 0; }
.header { border-bottom: 3px solid #12373C; padding-bottom: 10px; margin-bottom: 18px; }
.header table { width: 100%; }
.header .logo { width: 70px; vertical-align: middle; }
.header .logo img { width: 60px; height: auto; }
.header h1 { color: #12373C; margin: 0; font-size: 22px; }
.header .meta { color: #666; font-size: 11px; margin-top: 4px; }
h2 { color: #12373C; font-size: 14px; border-bottom: 1px solid #ddd; padding-bottom: 4px; margin: 18px 0 8px; }
table { width: 100%; border-collapse: collapse; }
.cliente td { padding: 3px 6px; vertical-align: top; }
.cliente td.k { color: #666; width: 130px; }
.item { border: 1px solid #ddd; border-radius: 4px; margin-bottom: 12px; padding: 10px; page-break-inside: avoid; }
.item .titolo { font-weight: bold; font-size: 13px; color: #12373C; margin-bottom: 6px; }
.item .body { }
.item .foto { width: 150px; vertical-align: top; padding-right: 12px; }
.item .foto img { width: 150px; height: auto; border: 1px solid #eee; }
.conf td { padding: 2px 6px; border-bottom: 1px solid #f0f0f0; }
.conf td.k { color: #666; width: 45%; }
.prezzo-riga { margin-top: 6px; text-align: right; font-size: 12px; }
.totale { margin-top: 14px; text-align: right; font-size: 16px; font-weight: bold; color: #12373C; }
.riepilogo { width: 62%; margin: 14px 0 0 auto; }
.riepilogo td { padding: 3px 0; text-align: right; color: #444; vertical-align: top; }
.riepilogo td + td { width: 110px; padding-left: 12px; white-space: nowrap; }
.riepilogo .dettaglio { color: #888; font-size: 10px; }
.riepilogo tr.forte td { font-weight: bold; border-top: 1px solid #ddd; }
.avviso-trasporto { margin-top: 10px; padding: 8px 10px; border: 1px solid #e6c200; background: #fff8d6; font-size: 11px; }
.nota { color: #888; font-size: 10px; text-align: right; }
</style>
</head>
<body>
<div class="header">
<table>
<tr>
@if($logoBase64)
<td class="logo"><img src="data:image/jpeg;base64,{{ $logoBase64 }}" alt="Krèios"></td>
@endif
<td>
<h1>Preventivo n. {{ $preventivo->numero }}</h1>
<div class="meta">
Krèios Infissi &middot; Emesso il {{ optional($preventivo->confirmed_at)->format('d/m/Y') ?? now()->format('d/m/Y') }}
</div>
</td>
</tr>
</table>
</div>
<h2>Dati cliente</h2>
<table class="cliente">
<tr><td class="k">Nominativo</td><td>{{ $cliente?->nome_completo }}</td></tr>
@if($cliente?->ragione_sociale)
<tr><td class="k">Ragione sociale</td><td>{{ $cliente->ragione_sociale }}</td></tr>
@endif
<tr><td class="k">Email</td><td>{{ $cliente?->email }}</td></tr>
<tr><td class="k">Telefono</td><td>{{ $cliente?->telefono ?: '—' }}</td></tr>
<tr><td class="k">Indirizzo</td><td>{{ trim(($cliente?->indirizzo ?: '').' '.($cliente?->cap ?: '').' '.($cliente?->citta ?: '').' '.($cliente?->provincia ? '('.$cliente->provincia.')' : '')) ?: '—' }}</td></tr>
@if($cliente?->note)
<tr><td class="k">Note</td><td>{{ $cliente->note }}</td></tr>
@endif
</table>
<h2>Configurazioni ({{ $preventivo->items->count() }})</h2>
@foreach($preventivo->items as $i => $item)
@php
$imgAbs = $item->immagine_path && Storage::disk('public')->exists($item->immagine_path)
? Storage::disk('public')->path($item->immagine_path) : null;
$rows = ConfigurazioneFormatter::toRows($item->payload);
@endphp
<div class="item">
<div class="titolo">{{ $i + 1 }}. {{ $item->nome_modello ?: 'Prodotto' }}
@if($item->sistema) <span style="color:#888;font-weight:normal;">({{ ucfirst($item->sistema) }})</span> @endif
</div>
<table class="body">
<tr>
@if($imgAbs)
<td class="foto">
<img src="data:image/png;base64,{{ base64_encode(file_get_contents($imgAbs)) }}" alt="">
</td>
@endif
<td>
<table class="conf">
@foreach($rows as $row)
<tr><td class="k">{{ $row['label'] }}</td><td>{{ $row['value'] }}</td></tr>
@endforeach
</table>
</td>
</tr>
</table>
<div class="prezzo-riga">
Quantità: {{ $item->quantita }} &nbsp;&times;&nbsp; € {{ number_format($item->prezzo_unitario, 2, ',', '.') }}
= <strong>€ {{ number_format($item->prezzo_totale, 2, ',', '.') }}</strong>
</div>
</div>
@endforeach
@php $importi = $preventivo->importiSconto(); @endphp
@if($preventivo->haSconti() || $preventivo->trasporto)
<table class="riepilogo">
<tr><td>Totale parziale</td><td>€ {{ number_format($preventivo->subtotale, 2, ',', '.') }}</td></tr>
@if((float) $preventivo->sconto_1 > 0)
<tr><td>1° sconto concesso ({{ rtrim(rtrim(number_format($preventivo->sconto_1, 2, ',', ''), '0'), ',') }}%)</td><td>− € {{ number_format($importi['sconto_1'], 2, ',', '.') }}</td></tr>
@endif
@if((float) $preventivo->sconto_2 > 0)
<tr><td>2° sconto extra ({{ rtrim(rtrim(number_format($preventivo->sconto_2, 2, ',', ''), '0'), ',') }}%)</td><td>− € {{ number_format($importi['sconto_2'], 2, ',', '.') }}</td></tr>
@endif
@if($preventivo->trasporto)
<tr class="forte"><td>Totale imponibile offerta</td><td>€ {{ number_format($importi['imponibile'], 2, ',', '.') }}</td></tr>
<tr>
{{-- A capo dopo "Campania": "Contributo trasporto Campania / entro 150 km". --}}
<td>
{!! preg_replace('/(Campania)\s+/u', '$1<br>', e($preventivo->trasporto_etichetta)) !!}
@unless($preventivo->trasportoDaQuantificare())
<br><span class="dettaglio">{{ $preventivo->items->sum('quantita') }} pz × € {{ number_format(config("preventivi.trasporto.zone.{$preventivo->trasporto}.importo"), 2, ',', '.') }}</span>
@endunless
</td>
<td>{{ $preventivo->trasporto === \App\Models\Preventivo::TRASPORTO_OLTRE_MAX ? '—' : ($preventivo->trasportoDaQuantificare() ? 'da quantificare' : '€ '.number_format($preventivo->trasporto_importo, 2, ',', '.')) }}</td>
</tr>
@endif
</table>
@endif
<div class="totale">{{ $preventivo->trasporto ? 'Totale' : 'Totale imponibile' }}: € {{ number_format($preventivo->totale, 2, ',', '.') }}</div>
@if($preventivo->trasportoDaQuantificare())
<div class="avviso-trasporto">{{ $preventivo->notaTrasporto() }}</div>
@endif
<div class="nota">Prezzi IVA esclusa. Preventivo indicativo, salvo verifica tecnica e rilievo misure.</div>
</body>
</html>