Files
carmine.savino 06617a985a 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.
2026-10-19 19:49:44 +02:00

140 lines
4.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
namespace App\Models;
use App\Models\Concerns\HaImmaginiCatalogo;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Collection;
/**
* Opzione del configuratore con eventuale supplemento di prezzo. Le righe senza modello
* valgono per tutto il sistema; se un modello ha righe proprie per un gruppo, per quel
* modello sostituiscono l'intero gruppo del sistema.
*/
class Opzione extends Model
{
use HaImmaginiCatalogo;
protected $table = 'opzioni';
/** Valori del gruppo tipo_finitura, derivati dalle finiture scelte (vedi CalcolatorePrezzo). */
public const TIPI_FINITURA = [
'bianco' => 'Bianco (finitura predefinita su interno ed esterno)',
'uniforme' => 'Uniforme (stessa finitura su interno ed esterno)',
'bicolore' => 'Bicolore (finiture diverse)',
];
public const SUPPLEMENTI = [
'percentuale' => 'Percentuale sul prezzo base',
'fisso' => 'Importo fisso (€)',
'metro_lineare' => 'Al metro lineare (€/ml)',
];
protected static array $immagini = ['icona'];
protected $fillable = [
'sistema_id', 'modello_id', 'gruppo', 'valore', 'etichetta', 'icona', 'alternativa',
'supplemento_tipo', 'supplemento', 'ml_per_larghezza', 'ml_per_altezza', 'ml_aggiunta_mm',
'parametri', 'ordine', 'attivo',
];
protected $casts = [
'supplemento' => 'float',
'ml_per_larghezza' => 'float',
'ml_per_altezza' => 'float',
'ml_aggiunta_mm' => 'float',
'parametri' => 'array',
'ordine' => 'integer',
'attivo' => 'boolean',
];
public function sistema(): BelongsTo
{
return $this->belongsTo(Sistema::class);
}
public function modello(): BelongsTo
{
return $this->belongsTo(Modello::class);
}
public function definizione(): BelongsTo
{
return $this->belongsTo(GruppoOpzioni::class, 'gruppo', 'codice');
}
public function scopeDelSistema(Builder $query): Builder
{
return $query->whereNull('modello_id');
}
/**
* Opzioni attive valide per il modello, per gruppo: quelle del modello dove ne ha,
* altrimenti quelle del sistema.
*
* @return Collection<string,Collection<int,Opzione>>
*/
public static function perModello(Modello $modello): Collection
{
$righe = static::query()
->where('sistema_id', $modello->sistema_id)
->where(fn (Builder $q) => $q->whereNull('modello_id')->orWhere('modello_id', $modello->getKey()))
->orderBy('ordine')
->orderBy('id')
->get();
// Basta una riga del modello (anche disattiva) per sostituire il gruppo.
$personalizzati = $righe->whereNotNull('modello_id')->pluck('gruppo')->unique();
return $righe
->filter(fn (Opzione $o) => $o->attivo && ($o->modello_id !== null) === $personalizzati->contains($o->gruppo))
->groupBy('gruppo');
}
public function descriviSupplemento(): string
{
if (! $this->supplemento_tipo || ! $this->supplemento) {
return '—';
}
$valore = number_format($this->supplemento, 2, ',', '.');
return match ($this->supplemento_tipo) {
'percentuale' => "{$valore}%",
'metro_lineare' => "€ {$valore}/ml × ".$this->formulaMetri(),
default => "€ {$valore}",
};
}
/** Metri lineari per un serramento L x H (mm), senza arrotondamenti. */
public function metriLineari(float $larghezza, float $altezza): float
{
return max(0, $larghezza * $this->ml_per_larghezza + $altezza * $this->ml_per_altezza + $this->ml_aggiunta_mm) / 1000;
}
/** Importo del supplemento sul prezzo base, per un serramento L x H (mm). */
public function importo(float $base, float $larghezza, float $altezza): float
{
return match ($this->supplemento_tipo) {
'percentuale' => $base * $this->supplemento / 100,
'metro_lineare' => $this->supplemento * $this->metriLineari($larghezza, $altezza),
'fisso' => $this->supplemento,
default => 0.0,
};
}
/** Es. "(H x 2 + 200 mm)". */
public function formulaMetri(): string
{
$termini = array_filter([
$this->ml_per_larghezza ? 'L'.($this->ml_per_larghezza != 1 ? ' × '.(float) $this->ml_per_larghezza : '') : null,
$this->ml_per_altezza ? 'H'.($this->ml_per_altezza != 1 ? ' × '.(float) $this->ml_per_altezza : '') : null,
$this->ml_aggiunta_mm ? (float) $this->ml_aggiunta_mm.' mm' : null,
]);
return '('.(implode(' + ', $termini) ?: '0').')';
}
}