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.
This commit is contained in:
2026-10-20 17:45:50 +02:00
parent 06617a985a
commit 8bef57b64b
27 changed files with 875 additions and 26 deletions
@@ -13,6 +13,13 @@
**Email:** {{ $preventivo->cliente?->email }}
**Telefono:** {{ $preventivo->cliente?->telefono ?: '—' }}
**Prodotti:** {{ $preventivo->items->count() }}
@if($preventivo->haSconti())
**Totale parziale:** € {{ number_format($preventivo->subtotale, 2, ',', '.') }}
**Sconti applicati:** {{ (float) $preventivo->sconto_1 }}% + {{ (float) $preventivo->sconto_2 }}% extra
@endif
@if($preventivo->trasporto)
**Trasporto:** {{ $preventivo->trasporto_etichetta }} — {{ $preventivo->trasportoDaQuantificare() ? 'da quantificare' : '€ '.number_format($preventivo->trasporto_importo, 2, ',', '.') }}
@endif
**Totale:** € {{ number_format($preventivo->totale, 2, ',', '.') }}
<x-mail::button :url="$adminUrl">
@@ -16,7 +16,11 @@ indicativo (prezzi IVA esclusa).
Un nostro consulente ti ricontatterà al più presto per finalizzare l'offerta.
**Totale indicativo:** € {{ number_format($preventivo->totale, 2, ',', '.') }}
**Totale indicativo (IVA esclusa{{ $preventivo->haSconti() ? ', sconti inclusi' : '' }}):** € {{ number_format($preventivo->totale, 2, ',', '.') }}
@if($preventivo->trasportoDaQuantificare())
{{ $preventivo->notaTrasporto() }}
@endif
Grazie,<br>
Il team di Krèios
@@ -0,0 +1,9 @@
<x-filament-panels::page>
<x-filament-panels::form wire:submit="save">
{{ $this->form }}
<x-filament-panels::form.actions :actions="[
\Filament\Actions\Action::make('save')->label('Salva')->submit('save'),
]" />
</x-filament-panels::form>
</x-filament-panels::page>
@@ -31,6 +31,12 @@
.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>
@@ -99,7 +105,35 @@
</div>
@endforeach
<div class="totale">Totale: € {{ number_format($preventivo->totale, 2, ',', '.') }}</div>
@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>