fix(ops): Suggérer never sweeps overdue jobs unless opted in

Le correctif précédent ne couvrait que l'entrée Tournées. Les jobs en
retard (scheduled_date < fenêtre) ou sans date étaient encore balayés sur
le jour choisi via d'autres chemins (bouton SUGGÉRER hors Tournées,
solveur  Optimiser). Corrigé À LA SOURCE + au placement :

- suggestJobs() (source unique — utilisée aussi par le solveur qui reçoit
  job_names) : exclut désormais les jobs hors fenêtre (retard/sans date/
  autre jour) SAUF si l'utilisateur coche «  en retard » / « Sans date »
  ou fait une sélection lasso. Sélectionner un seul jour ne dispatche donc
  QUE les jobs dus ce jour-là.
- buildSuggestion() : la branche fourre-tout `else cand = win` ne place
  plus les retards/sans-date automatiquement — même garde (lasso ou chips
  explicites) en défense.

Vérifié live (Tournées, 06/07) : plan de 25 jobs, tous sur « 07-06 »
(aucune date antérieure), 0 nouvelle erreur.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
louispaulb 2026-07-05 00:16:19 -04:00
parent 8b3c97de9d
commit bae7303d66

View File

@ -4342,7 +4342,14 @@ function buildSuggestion () {
if (j._reDate && winSet.has(j._reDate)) cand = [j._reDate] // date re-choisie (dans la fenêtre) if (j._reDate && winSet.has(j._reDate)) cand = [j._reDate] // date re-choisie (dans la fenêtre)
else if (sched && winSet.has(sched)) cand = [sched] // daté DANS la fenêtre ce jour else if (sched && winSet.has(sched)) cand = [sched] // daté DANS la fenêtre ce jour
else if (sched && sched > winMax) continue // daté APRÈS la fenêtre PAS dispatché maintenant (on ne planifie pas loin) else if (sched && sched > winMax) continue // daté APRÈS la fenêtre PAS dispatché maintenant (on ne planifie pas loin)
else cand = win // en retard / sans date / avant la fenêtre placé dans la fenêtre else {
// En retard (date < fenêtre) ou sans date : NE PLUS balayer automatiquement sur le(s) jour(s) choisi(s).
// Seulement si EXPLICITEMENT demandé : sélection lasso, ou chip « en retard » / « Sans date » coché.
// sélectionner un seul jour ne dispatche QUE les jobs dus ce jour-là (retour terrain : les retards ne doivent pas s'inviter).
const wantBacklog = useSel || (assignDateFilter.value || []).includes('__overdue__') || (assignDateFilter.value || []).includes('Sans date')
if (!wantBacklog) continue
cand = win
}
if (!cand.length) continue if (!cand.length) continue
let best = null let best = null
for (const t of techs) { for (const t of techs) {
@ -4463,8 +4470,14 @@ const suggestJobs = () => {
let jobs = (assignJobsFiltered.value || []).filter(j => j.status !== 'On Hold') // pool tel qu'affiché (type + date) let jobs = (assignJobsFiltered.value || []).filter(j => j.status !== 'On Hold') // pool tel qu'affiché (type + date)
// Par DÉFAUT (aucun chip de date coché) : ne répartir QUE les jobs DATÉS sur le(s) jour(s) de la fenêtre jamais les // Par DÉFAUT (aucun chip de date coché) : ne répartir QUE les jobs DATÉS sur le(s) jour(s) de la fenêtre jamais les
// jobs en retard/sans date/d'autres jours (souvent faits mais pas encore fermés) qui pollueraient la simulation. // jobs en retard/sans date/d'autres jours (souvent faits mais pas encore fermés) qui pollueraient la simulation.
// (Pour dispatcher les retards, cocher explicitement le chip « en retard ».) // (Pour dispatcher les retards, cocher explicitement le chip « en retard » ou « Sans date ».)
if (!assignDateFilter.value.length) { const win = new Set(suggestWindow.value); jobs = jobs.filter(j => win.has(j.scheduled_date)) } // Filtre appliqué à la SOURCE (couvre aussi le solveur Optimiser qui prend suggestJobs()) : seuls les jobs
// datés DANS la fenêtre passent, SAUF si l'utilisateur demande explicitement les retards/sans-date.
const wantBacklog = (assignDateFilter.value || []).includes('__overdue__') || (assignDateFilter.value || []).includes('Sans date')
if (!wantBacklog) {
const win = new Set(suggestWindow.value)
jobs = jobs.filter(j => j.scheduled_date && j.scheduled_date !== 'Sans date' && win.has(j.scheduled_date))
}
return jobs return jobs
} }
const suggestJobCount = computed(() => suggestJobs().length) const suggestJobCount = computed(() => suggestJobs().length)