feat: add previous configuration handling for user selections in quotes

- Implemented session storage management for the last configuration choices made by the user.
- Added functionality to prompt users when changing models to retain their previous selections.
- Introduced methods to apply previous choices to the newly loaded model, including finishes, handles, glass types, and options.
- Enhanced user experience by ensuring selections are automatically applied where applicable.
This commit is contained in:
2026-10-19 19:49:44 +02:00
parent 863e6ca920
commit 06617a985a
197 changed files with 4892 additions and 400 deletions
@@ -9,6 +9,7 @@ use App\Models\Cliente;
use App\Models\Preventivo;
use App\Models\PreventivoItem;
use App\Support\ConfigurazioneFormatter;
use App\Support\Configuratore\CalcolatorePrezzo;
use App\Support\PreventivoPdf;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -21,39 +22,57 @@ use Illuminate\Support\Str;
class CarrelloController extends Controller
{
/**
* POST /api/carrello/aggiungi
* Aggiunge un prodotto configurato al carrello (preventivo in stato bozza).
* Voci descrittive del configuratore che non incidono sul prezzo: sono le uniche
* accettate dal payload del client, tutto il resto lo ricostruisce il server.
*/
public function aggiungi(Request $request): JsonResponse
private const VOCI_DESCRITTIVE = ['altezza_maniglia', 'apertura_portoncino', 'tipo_ispezione', 'avvolgibile', 'cassonetto'];
/**
* POST /api/carrello/aggiungi
* Aggiunge un prodotto configurato al carrello (preventivo in stato bozza). Il prezzo è
* ricalcolato dalle scelte con le regole del backoffice: quello del client è ignorato.
*/
public function aggiungi(Request $request, CalcolatorePrezzo $calcolatore): JsonResponse
{
$data = $request->validate([
'token' => ['nullable', 'string', 'max:64'],
'sistema' => ['nullable', 'string', 'max:50'],
'type' => ['nullable', 'string', 'max:100'],
'nome' => ['nullable', 'string', 'max:255'],
'larghezza' => ['nullable', 'integer', 'min:0'],
'altezza' => ['nullable', 'integer', 'min:0'],
'sistema' => ['required', 'string', 'max:50'],
'type' => ['required', 'string', 'max:100'],
'qty' => ['nullable', 'integer', 'min:1', 'max:999'],
'prezzo' => ['required', 'numeric', 'min:0'],
'scelte' => ['required', 'array'],
...CatalogoController::regoleScelte('scelte.'),
'payload' => ['nullable', 'array'],
'img' => ['nullable', 'string'],
]);
$modello = CatalogoController::trovaModello($data['sistema'], $data['type']);
$calcolo = $calcolatore->calcola($modello, $data['scelte']);
$descrittive = collect($data['payload'] ?? [])
->only(self::VOCI_DESCRITTIVE)
->filter(fn ($v) => is_scalar($v) && $v !== '')
->map(fn ($v) => mb_substr((string) $v, 0, 255))
->all();
$preventivo = $this->risolviCarrello($data['token'] ?? null);
$qty = $data['qty'] ?? 1;
$prezzoUnitario = round((float) $data['prezzo'], 2);
$prezzoUnitario = $calcolo['prezzo'];
$configurazione = $calcolo['configurazione'];
$item = new PreventivoItem([
'sistema' => $data['sistema'] ?? null,
'type' => $data['type'] ?? null,
'nome_modello' => $data['nome'] ?? ($data['payload']['nome'] ?? null),
'larghezza' => $data['larghezza'] ?? ($data['payload']['width'] ?? null),
'altezza' => $data['altezza'] ?? ($data['payload']['height'] ?? null),
'sistema' => $modello->sistema->codice,
'type' => $modello->codice,
'nome_modello' => $configurazione['nome'],
'larghezza' => $configurazione['width'],
'altezza' => $configurazione['height'],
'quantita' => $qty,
'prezzo_unitario' => $prezzoUnitario,
'prezzo_totale' => round($prezzoUnitario * $qty, 2),
'payload' => $data['payload'] ?? [],
'payload' => $descrittive + $configurazione + [
'scelte' => $calcolo['scelte'],
'dettaglio_prezzo' => $calcolo['dettaglio'],
],
'immagine_path' => $this->salvaImmagine($data['img'] ?? null),
]);