// prix.ts — fourchettes de prix d'une option selon le mode de pose, prix d'un // preset, preset le plus proche d'un montant. Origine // calculs/src/scripts/autonomie/prix.js + matchPresetNiveaux de simulation.js. // Les prix sont des DONNÉES des options (publiées par calculs) ; ce module ne // porte aucun montant. Le formatage (« 1 200 € HT ») reste côté site. /** Fourchette d'une option × quantité : colonnes prix_mat_* (auto-pose) ou prix_pro_* (faire poser). */ export function prixOption(opt, qty, pose) { const q = qty || opt.quantite_default || 1; let min; let max; if (pose === 'auto') { min = opt.prix_mat_min; max = opt.prix_mat_max; } else { min = opt.prix_pro_min != null ? opt.prix_pro_min : opt.prix_mat_min; max = opt.prix_pro_max != null ? opt.prix_pro_max : opt.prix_mat_max; } if (min == null && max == null) return { min: null, max: null, autoOnly: false }; return { min: min != null ? min * q : null, max: max != null ? max * q : null, autoOnly: pose === 'pro' && opt.prix_pro_min == null && opt.prix_pro_max == null, }; } /** Prix total d'un preset (somme de ses options × quantités) pour un mode de pose. */ export function prixPreset(preset, presetOptions, optionsById, pose) { let min = 0; let max = 0; for (const po of presetOptions) { if (po.preset_id !== preset.Id) continue; const opt = optionsById[po.option_id]; if (!opt) continue; const p = prixOption(opt, po.quantite || 1, pose); if (p.min == null) continue; min += p.min; max += p.max != null ? p.max : p.min; } return { min, max }; } /** Niveau de preset (light/standard/complet) dont le prix médian est le plus proche du montant cible, pour un axe (code BDD). */ export function presetLePlusProche(cible, axe_bdd, presets, presetOptions, optionsById, pose) { let best = null; let bestDist = Infinity; for (const preset of presets.filter((p) => p.axe === axe_bdd && p.actif !== false)) { const prix = prixPreset(preset, presetOptions, optionsById, pose); const mid = (prix.min + prix.max) / 2; const dist = Math.abs(mid - cible); if (dist < bestDist) { bestDist = dist; best = preset; } } return best ? best.niveau : 'standard'; }