feat(dispatch): pre-wired sites — install time ÷4 (Lac des pins/Camping/Domaine Dauphinais)
estimateForJob: an INSTALLATION whose location matches a pre-wired site (Lac des pins, Camping, Domaine Dauphinais) takes ¼ of the normal time (infra already in place). Applied at the estimator source → flows into est_min everywhere (greedy duration, VRP service_min, occupancy, travel). Floored at 15 min; adds a "site pré-câblé ×¼" label. Verified: Lac des pins install 120→30 min; normal install unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2566976191
commit
8b2d7b54e9
|
|
@ -351,10 +351,20 @@ function detectCharacteristics (job, items) {
|
||||||
for (const a of items.filter(i => i.cat === 'addon')) if (hit(a.keywords)) picks.push({ id: a.id, qty: 1 })
|
for (const a of items.filter(i => i.cat === 'addon')) if (hit(a.keywords)) picks.push({ id: a.id, qty: 1 })
|
||||||
return picks
|
return picks
|
||||||
}
|
}
|
||||||
|
// Sites PRÉ-CÂBLÉS : une INSTALLATION y prend ~¼ du temps normal (infra déjà en place → branchement rapide).
|
||||||
|
const FAST_INSTALL_SITES = ['lac des pins', 'camping', 'domaine dauphinais']
|
||||||
function estimateForJob (job, items) {
|
function estimateForJob (job, items) {
|
||||||
items = items || readJobChar().items
|
items = items || readJobChar().items
|
||||||
const picks = detectCharacteristics(job, items); const by = {}; for (const i of items) by[i.id] = i
|
const picks = detectCharacteristics(job, items); const by = {}; for (const i of items) by[i.id] = i
|
||||||
return { minutes: estimateMinutes(picks, items), picks, labels: picks.map(p => (by[p.id] || {}).label).filter(Boolean) }
|
let minutes = estimateMinutes(picks, items)
|
||||||
|
const labels = picks.map(p => (by[p.id] || {}).label).filter(Boolean)
|
||||||
|
// Installation à un site pré-câblé → temps /4 (Lac des pins / Camping / Domaine Dauphinais).
|
||||||
|
const isInstall = picks.some(p => String(p.id).startsWith('install')) || String(job.required_skill || '').toLowerCase().includes('install')
|
||||||
|
if (isInstall && minutes > 0) {
|
||||||
|
const loc = [job.address, job.location_label, job.service_location, job.subject, job.municipalite].join(' ').toLowerCase().normalize('NFD').replace(/\p{Diacritic}/gu, '')
|
||||||
|
if (FAST_INSTALL_SITES.some(s => loc.includes(s))) { minutes = Math.max(15, Math.round(minutes / 4)); labels.push('site pré-câblé ×¼') }
|
||||||
|
}
|
||||||
|
return { minutes, picks, labels }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── #56 Politique de créneaux offerts + holds temporaires ────────────────────
|
// ── #56 Politique de créneaux offerts + holds temporaires ────────────────────
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user