Planification: drapeau « longue durée » sur absence (maternité/invalidité = à remplacer)
Tech Availability gagne long_term (Check). Case à cocher « Longue durée » dans le dialogue Congés. absencesByTechDay encode « (longue durée) » → applyTemplate force « à remplacer » (pas juste sauter comme des vacances), même si l'absence ne couvre pas toute la semaine. Complète l'intelligence permanent vs vacances (avant: déduit de « absent toute la semaine »). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8d946daf8d
commit
fe60eeb485
|
|
@ -224,6 +224,7 @@
|
|||
<q-input dense outlined type="date" v-model="newLeave.from_date" label="Du" style="width:140px" />
|
||||
<q-input dense outlined type="date" v-model="newLeave.to_date" label="Au" style="width:140px" />
|
||||
<q-input dense outlined v-model="newLeave.reason" label="Motif" style="width:150px" />
|
||||
<q-toggle dense v-model="newLeave.long_term" :true-value="1" :false-value="0" label="Longue durée"><q-tooltip>Maternité, invalidité… → à remplacer (pas juste sauter comme des vacances)</q-tooltip></q-toggle>
|
||||
<q-btn dense unelevated color="primary" icon="add" label="Créer" @click="createLeave" />
|
||||
</div>
|
||||
<div class="text-caption text-grey-7 q-mt-sm">Une demande <b>approuvée</b> rend le tech indisponible pour le solveur sur ces dates.</div>
|
||||
|
|
@ -367,7 +368,7 @@ const showShiftEditor = ref(false); const editTpls = ref([])
|
|||
const showTeamEditor = ref(false); const editTechs = ref([])
|
||||
const notifySms = ref(false)
|
||||
const showLeave = ref(false); const leaveRows = ref([]); const leaveFilter = ref('Demandé')
|
||||
const newLeave = reactive({ technician: '', availability_type: 'Congé', from_date: '', to_date: '', reason: '' })
|
||||
const newLeave = reactive({ technician: '', availability_type: 'Congé', from_date: '', to_date: '', reason: '', long_term: 0 })
|
||||
const newTpl = reactive({ template_name: '', start: '08:00', end: '16:00', color: '#1976d2', on_call: 0 })
|
||||
function numToTime (h) { const hh = Math.floor(h); const mm = Math.round((h - hh) * 60); return String(hh).padStart(2, '0') + ':' + String(mm).padStart(2, '0') }
|
||||
// Slider à 2 poignées pour le nouveau modèle (heures custom) ↔ newTpl.start/end
|
||||
|
|
@ -532,7 +533,7 @@ async function approveLeave (l, reject) { try { await roster.approveAvailability
|
|||
async function createLeave () {
|
||||
if (!newLeave.technician || !newLeave.from_date || !newLeave.to_date) { $q.notify({ type: 'warning', message: 'Technicien + dates requis' }); return }
|
||||
const t = techs.value.find(x => x.id === newLeave.technician)
|
||||
try { await roster.requestAvailability({ technician: newLeave.technician, technician_name: t ? t.name : '', availability_type: newLeave.availability_type, from_date: newLeave.from_date, to_date: newLeave.to_date, reason: newLeave.reason }); $q.notify({ type: 'positive', message: 'Demande créée' }); newLeave.from_date = ''; newLeave.to_date = ''; newLeave.reason = ''; await loadLeave() } catch (e) { err(e) }
|
||||
try { await roster.requestAvailability({ technician: newLeave.technician, technician_name: t ? t.name : '', availability_type: newLeave.availability_type, from_date: newLeave.from_date, to_date: newLeave.to_date, reason: newLeave.reason, long_term: newLeave.long_term }); $q.notify({ type: 'positive', message: 'Demande créée' }); newLeave.from_date = ''; newLeave.to_date = ''; newLeave.reason = ''; newLeave.long_term = 0; await loadLeave() } catch (e) { err(e) }
|
||||
}
|
||||
async function saveEff (t) { const eff = Number(t.efficiency) || 1; try { await roster.setTechEfficiency(t.id, eff); const tt = techs.value.find(x => x.id === t.id); if (tt) tt.efficiency = eff; $q.notify({ type: 'positive', message: t.name + ' : cadence ' + eff }) } catch (e) { err(e) } }
|
||||
function loadedCost (t) { return Math.round(((Number(t.salary) || 0) * (1 + (Number(t.charges) || 0) / 100) + (Number(t.other) || 0)) * 100) / 100 }
|
||||
|
|
@ -680,7 +681,7 @@ function applyTemplate (tm) {
|
|||
const t = techs.value.find(x => x.id === techId); const name = (t ? t.name : techId)
|
||||
const type = absByTechDay.value[techId + '|' + (dayList.value.find(d => isAbsent(techId, d.iso)) || {}).iso] || ''
|
||||
const lbl = name + (type ? ' (' + type + ')' : '')
|
||||
if (skipped[techId] >= countPatternDays(tm, techId)) fullOut.push(lbl); else partial.push(lbl)
|
||||
if (/longue durée/i.test(type) || skipped[techId] >= countPatternDays(tm, techId)) fullOut.push(lbl); else partial.push(lbl)
|
||||
}
|
||||
let msg = 'Modèle « ' + tm.name + ' » appliqué (' + applied + ' assignations)'
|
||||
if (partial.length) msg += ' · absence partielle ignorée : ' + partial.join(', ')
|
||||
|
|
|
|||
|
|
@ -499,9 +499,9 @@ async function absencesByTechDay (start, days) {
|
|||
for (const t of techs) if (t.status === PAUSE_STATUS) for (const d of dates) m[t.id + '|' + d] = 'En pause'
|
||||
const avs = await erp.list('Tech Availability', {
|
||||
filters: [['status', '=', 'Approuvé'], ['from_date', '<=', hi], ['to_date', '>=', lo]],
|
||||
fields: ['technician', 'from_date', 'to_date', 'availability_type'], limit: 1000,
|
||||
fields: ['technician', 'from_date', 'to_date', 'availability_type', 'long_term'], limit: 1000,
|
||||
})
|
||||
for (const a of avs) for (const d of dates) if (d >= a.from_date && d <= a.to_date) m[a.technician + '|' + d] = a.availability_type || 'Absent'
|
||||
for (const a of avs) for (const d of dates) if (d >= a.from_date && d <= a.to_date) m[a.technician + '|' + d] = (a.availability_type || 'Absent') + (a.long_term ? ' (longue durée)' : '')
|
||||
return m
|
||||
}
|
||||
|
||||
|
|
@ -734,6 +734,7 @@ async function handle (req, res, method, path, url) {
|
|||
technician: b.technician, technician_name: b.technician_name || '',
|
||||
availability_type: b.availability_type || 'Congé', status: 'Demandé',
|
||||
from_date: b.from_date, to_date: b.to_date, reason: b.reason || '',
|
||||
long_term: b.long_term ? 1 : 0,
|
||||
})
|
||||
return json(res, r.ok ? 200 : 500, r)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user