- 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.
140 lines
7.7 KiB
PHP
140 lines
7.7 KiB
PHP
@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 · 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 }} × € {{ 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>
|