planif Suggérer : UNE seule méthode (VRP) + retrait des réglages de coûts
Retire le sélecteur de stratégies (5 modes) et les champs Coûts (Spécialité/Heures sup/km-h/Calcul s) mal compris. Méthode unique = solveur VRP, forcée. Description claire des critères pris en compte. (Backend : brancher l'efficacité par skill + réserve-experts dans le solveur = étape suivante.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
61a2f1000f
commit
88a5e84f90
|
|
@ -1065,24 +1065,15 @@
|
||||||
<q-card-section class="col scroll q-pa-sm" style="overflow:auto">
|
<q-card-section class="col scroll q-pa-sm" style="overflow:auto">
|
||||||
<!-- Étape 1 — disponibilité des techniciens + création de quarts 8–16 -->
|
<!-- Étape 1 — disponibilité des techniciens + création de quarts 8–16 -->
|
||||||
<template v-if="suggestDlg.mode === 'config'">
|
<template v-if="suggestDlg.mode === 'config'">
|
||||||
<div class="row items-center q-mb-sm" style="gap:6px;flex-wrap:wrap">
|
<div class="row items-start q-mb-sm text-caption text-grey-7" style="gap:6px;background:#fffbeb;border:1px solid #fde68a;border-radius:8px;padding:7px 10px">
|
||||||
<span class="text-caption text-grey-7 q-mr-xs">Stratégie :</span>
|
<q-icon name="auto_awesome" color="amber-8" size="17px" />
|
||||||
<q-btn-toggle v-model="suggestDlg.strategy" dense no-caps unelevated toggle-color="primary" color="grey-3" text-color="grey-8" :options="[{ label: '⚡ Optimiser', value: 'optimize' }, { label: 'Intelligent', value: 'smart' }, { label: 'Meilleurs d\'abord', value: 'best' }, { label: 'Équilibré', value: 'balance' }, { label: 'Juste ce qu\'il faut', value: 'enough' }]" />
|
<span>Répartition automatique — compétences · <b>efficacité par compétence</b> · distance (routes réelles) · fenêtres AM/PM · priorités. Les cas simples vont d'abord aux techs les <b>moins polyvalents</b> (réserve les experts). Tu revois et ajustes avant d'appliquer.</span>
|
||||||
<span class="text-caption text-grey-6">{{ ({ optimize: 'solveur VRP (OR-Tools) : routes réelles minimisées + compétences + temps sur place — regroupe les secteurs, spécialistes d\'abord', smart: 'proximité + compétence + charge', best: 'concentre le travail sur les meilleurs (cascade)', balance: 'répartit également entre tous (round-robin)', enough: 'qualifié mais le moins sur-qualifié → réserve les experts (distance + temps pris en compte)' })[suggestDlg.strategy] }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Simulation « ré-optimiser l'existant » : inclut AUSSI les jobs déjà assignés de la fenêtre (le solveur les replace) → comparer/améliorer une tournée déjà dispatchée, avec les nouveaux jobs. Rien n'est écrit avant « Appliquer ». -->
|
<!-- Simulation « ré-optimiser l'existant » : inclut AUSSI les jobs déjà assignés de la fenêtre (le solveur les replace) → comparer/améliorer une tournée déjà dispatchée, avec les nouveaux jobs. Rien n'est écrit avant « Appliquer ». -->
|
||||||
<div class="row items-center q-mb-sm" style="gap:6px">
|
<div class="row items-center q-mb-sm" style="gap:6px">
|
||||||
<q-toggle v-model="suggestDlg.includeAssigned" dense size="sm" color="deep-purple" label="Ré-optimiser aussi les jobs déjà assignés (simulation)" />
|
<q-toggle v-model="suggestDlg.includeAssigned" dense size="sm" color="deep-purple" label="Ré-optimiser aussi les jobs déjà assignés (simulation)" />
|
||||||
<q-icon name="info" size="15px" color="grey-5"><q-tooltip class="bg-grey-9" style="font-size:11px">Inclut les {{ assignedNamesForWindow().length }} job(s) déjà assigné(s) du/des jour(s) → le solveur repropose une répartition de TOUT (existant + nouveaux). Force le solveur VRP. Aperçu seulement — « Appliquer » réassigne.</q-tooltip></q-icon>
|
<q-icon name="info" size="15px" color="grey-5"><q-tooltip class="bg-grey-9" style="font-size:11px">Inclut les {{ assignedNamesForWindow().length }} job(s) déjà assigné(s) du/des jour(s) → le solveur repropose une répartition de TOUT (existant + nouveaux). Force le solveur VRP. Aperçu seulement — « Appliquer » réassigne.</q-tooltip></q-icon>
|
||||||
</div>
|
</div>
|
||||||
<!-- Réglages optimiseur : UN COÛT par critère (pas de slider) — persistés localement -->
|
|
||||||
<div v-if="suggestDlg.strategy === 'optimize'" class="row items-center q-gutter-sm q-mb-sm" style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:6px 10px;flex-wrap:wrap">
|
|
||||||
<span class="text-caption text-grey-7">Coûts :</span>
|
|
||||||
<q-input v-model.number="solverOpts.rankWeight" type="number" dense outlined style="width:98px" label="Spécialité" :min="0" :max="50"><q-tooltip>Coût par cran d'ordre de compétence — 0 = distance seule ; élevé = garde les spécialistes sur leur métier</q-tooltip></q-input>
|
|
||||||
<q-input v-model.number="solverOpts.overtimeCoef" type="number" dense outlined style="width:104px" label="Heures sup" :min="0" :max="200"><q-tooltip>Coût par minute au-delà de 100 % du quart — élevé = étale davantage avant de dépasser (plafond 120 %)</q-tooltip></q-input>
|
|
||||||
<q-input v-model.number="solverOpts.speedKmh" type="number" dense outlined style="width:86px" label="km/h" :min="20" :max="90"><q-tooltip>Vitesse de repli (nœuds sans coordonnées)</q-tooltip></q-input>
|
|
||||||
<q-input v-model.number="solverOpts.maxSeconds" type="number" dense outlined style="width:92px" label="Calcul s" :min="2" :max="30"><q-tooltip>Budget de calcul par jour</q-tooltip></q-input>
|
|
||||||
</div>
|
|
||||||
<!-- FENÊTRE de répartition = les CHIPS de date cochés dans le pool (ou la sélection lasso). Sinon → un jour choisi ici. -->
|
<!-- FENÊTRE de répartition = les CHIPS de date cochés dans le pool (ou la sélection lasso). Sinon → un jour choisi ici. -->
|
||||||
<div class="row items-center q-mb-sm" style="gap:6px;color:#475569;background:#eef2ff;border-radius:6px;padding:5px 8px">
|
<div class="row items-center q-mb-sm" style="gap:6px;color:#475569;background:#eef2ff;border-radius:6px;padding:5px 8px">
|
||||||
<q-icon name="event" size="16px" color="primary" /><span class="text-caption text-weight-medium">Répartir :</span>
|
<q-icon name="event" size="16px" color="primary" /><span class="text-caption text-weight-medium">Répartir :</span>
|
||||||
|
|
@ -4818,6 +4809,7 @@ function techQuality (t) {
|
||||||
const suggestTechsRanked = computed(() => [...(visibleTechs.value || [])].sort((a, b) => techQuality(a) - techQuality(b)))
|
const suggestTechsRanked = computed(() => [...(visibleTechs.value || [])].sort((a, b) => techQuality(a) - techQuality(b)))
|
||||||
async function runSuggestion () {
|
async function runSuggestion () {
|
||||||
if (!suggestSelCount.value) { $q.notify({ type: 'warning', message: 'Choisis au moins un technicien disponible.', timeout: 2500 }); return }
|
if (!suggestSelCount.value) { $q.notify({ type: 'warning', message: 'Choisis au moins un technicien disponible.', timeout: 2500 }); return }
|
||||||
|
suggestDlg.strategy = 'optimize' // UNE seule méthode : solveur VRP (routes réelles + compétences + efficacité + AM/PM + priorités)
|
||||||
showAllMoveTechs.value = false // picker « déplacer vers » : repart filtré aux techs sélectionnés+compétents
|
showAllMoveTechs.value = false // picker « déplacer vers » : repart filtré aux techs sélectionnés+compétents
|
||||||
// « Ré-optimiser l'existant » : le solveur récupère les données des jobs assignés par leur nom (l'heuristique locale
|
// « Ré-optimiser l'existant » : le solveur récupère les données des jobs assignés par leur nom (l'heuristique locale
|
||||||
// n'a que le pool en mémoire) → on force le solveur VRP.
|
// n'a que le pool en mémoire) → on force le solveur VRP.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user