fix(planif): afficher les congés en attente dans le résumé de Publier
Le résumé de « Publier l'horaire » (pubSummary) était construit UNIQUEMENT à partir des quarts non publiés (unpublished) et ignorait pendingAbs. Un congé mis en attente (ex. Josée-Anne, congé indéterminé) allumait bien le badge « non publié » ET était bien envoyé au Publier (flushPendingAbsences), mais n'apparaissait PAS dans le dialogue de confirmation — on n'y voyait que le changement de quart (Nathan Morrisseau). Le répartiteur ne pouvait donc pas réviser le congé avant de confirmer. pubSummary intègre désormais pendingAbs, groupé par date, avec compteurs absAdded/absRemoved ; l'en-tête affiche « N quart(s) · M congé(s) » et chaque jour liste les congés (event_busy orange = ajout · event_available teal = retrait) à côté des quarts. Vérifié (aperçu, client-only, rien écrit) : congé indéfini Josée-Anne 13-17/07 → résumé « 1 quart(s) · 5 congé(s) », lignes Congé par jour à côté du quart de Nathan Morrisseau. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6761c9e05a
commit
9d568986fc
|
|
@ -1338,12 +1338,13 @@
|
||||||
<q-space /><q-btn flat round dense icon="close" v-close-popup />
|
<q-space /><q-btn flat round dense icon="close" v-close-popup />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section class="q-pt-sm">
|
<q-card-section class="q-pt-sm">
|
||||||
<div class="text-body2 q-mb-sm"><b class="text-positive">{{ pubSummary.added }}</b> ajout(s) · <b class="text-negative">{{ pubSummary.removed }}</b> retrait(s) · <b>{{ notifySms ? pubSummary.added + ' SMS aux techs' : 'sans SMS' }}</b></div>
|
<div class="text-body2 q-mb-sm"><b class="text-positive">{{ pubSummary.added }}</b> quart(s) · <b v-if="pubSummary.absAdded" class="text-orange-8">{{ pubSummary.absAdded }}</b><span v-if="pubSummary.absAdded"> congé(s)</span><span v-if="pubSummary.absRemoved"> · <b class="text-teal-7">{{ pubSummary.absRemoved }}</b> congé(s) retiré(s)</span> · <b>{{ notifySms ? pubSummary.added + ' SMS aux techs' : 'sans SMS' }}</b></div>
|
||||||
<q-list dense bordered style="border-radius:8px;max-height:44vh;overflow:auto">
|
<q-list dense bordered style="border-radius:8px;max-height:44vh;overflow:auto">
|
||||||
<template v-for="d in pubSummary.days" :key="d.date">
|
<template v-for="d in pubSummary.days" :key="d.date">
|
||||||
<q-item-label header class="q-py-xs text-weight-medium">{{ fmtDueLabel(d.date) }}</q-item-label>
|
<q-item-label header class="q-py-xs text-weight-medium">{{ fmtDueLabel(d.date) }}</q-item-label>
|
||||||
<q-item v-for="(a, i) in d.add" :key="'a' + i" dense><q-item-section avatar style="min-width:24px"><q-icon name="add" color="positive" size="16px" /></q-item-section><q-item-section>{{ a.name }}<span class="text-grey-6"> · {{ a.shift }}</span></q-item-section></q-item>
|
<q-item v-for="(a, i) in d.add" :key="'a' + i" dense><q-item-section avatar style="min-width:24px"><q-icon name="add" color="positive" size="16px" /></q-item-section><q-item-section>{{ a.name }}<span class="text-grey-6"> · {{ a.shift }}</span></q-item-section></q-item>
|
||||||
<q-item v-for="(r, i) in d.rem" :key="'r' + i" dense><q-item-section avatar style="min-width:24px"><q-icon name="remove" color="negative" size="16px" /></q-item-section><q-item-section>{{ r.name }}<span class="text-grey-6"> · {{ r.shift }}</span></q-item-section></q-item>
|
<q-item v-for="(r, i) in d.rem" :key="'r' + i" dense><q-item-section avatar style="min-width:24px"><q-icon name="remove" color="negative" size="16px" /></q-item-section><q-item-section>{{ r.name }}<span class="text-grey-6"> · {{ r.shift }}</span></q-item-section></q-item>
|
||||||
|
<q-item v-for="(ab, i) in d.abs" :key="'ab' + i" dense><q-item-section avatar style="min-width:24px"><q-icon :name="ab.op === 'set' ? 'event_busy' : 'event_available'" :color="ab.op === 'set' ? 'orange-8' : 'teal-7'" size="16px" /></q-item-section><q-item-section>{{ ab.name }}<span class="text-grey-6"> · {{ ab.op === 'set' ? (ab.type || 'Congé') : 'congé retiré' }}</span></q-item-section></q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
@ -4003,11 +4004,20 @@ const pubConfirm = ref(false)
|
||||||
const pubSummary = computed(() => {
|
const pubSummary = computed(() => {
|
||||||
const nameOf = id => { const t = (techs.value || []).find(x => x.id === id); return (t && t.name) || id }
|
const nameOf = id => { const t = (techs.value || []).find(x => x.id === id); return (t && t.name) || id }
|
||||||
const byDate = {}
|
const byDate = {}
|
||||||
|
const bucket = date => (byDate[date] = byDate[date] || { date, add: [], rem: [], abs: [] })
|
||||||
for (const a of unpublished.value) {
|
for (const a of unpublished.value) {
|
||||||
const d = (byDate[a.date] = byDate[a.date] || { date: a.date, add: [], rem: [] })
|
bucket(a.date).add.push({ tech: a.tech, date: a.date, shift: a.shift_name || a.shift, name: nameOf(a.tech), status: a.status })
|
||||||
d.add.push({ tech: a.tech, date: a.date, shift: a.shift_name || a.shift, name: nameOf(a.tech), status: a.status })
|
|
||||||
}
|
}
|
||||||
return { added: unpublished.value.length, removed: 0, days: Object.values(byDate).sort((x, y) => String(x.date).localeCompare(String(y.date))) }
|
// CONGÉS / ABSENCES en attente (pendingAbs) : ils comptent dans « non publié » et sont bien envoyés au Publier
|
||||||
|
// (flushPendingAbsences) — donc ils DOIVENT figurer dans le résumé (sinon un congé indéfini reste invisible, ex. Josée-Anne).
|
||||||
|
let absAdded = 0; let absRemoved = 0
|
||||||
|
for (const [k, v] of Object.entries(pendingAbs.value || {})) {
|
||||||
|
const [tid, iso] = k.split('|')
|
||||||
|
const set = v && v.op === 'set'
|
||||||
|
bucket(iso).abs.push({ tech: tid, date: iso, name: nameOf(tid), type: set ? (v.type || 'Congé') : null, op: set ? 'set' : 'remove' })
|
||||||
|
if (set) absAdded++; else absRemoved++
|
||||||
|
}
|
||||||
|
return { added: unpublished.value.length, removed: 0, absAdded, absRemoved, days: Object.values(byDate).sort((x, y) => String(x.date).localeCompare(String(y.date))) }
|
||||||
})
|
})
|
||||||
|
|
||||||
const holSet = computed(() => new Set(holidays.value))
|
const holSet = computed(() => new Set(holidays.value))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user