From 9702a19db8b75bedb3e410f5cd7aba431ee6c6ed Mon Sep 17 00:00:00 2001 From: kdeterme Date: Wed, 2 Sep 2026 14:28:12 +0200 Subject: [PATCH] feat: implement member absence tracking and visual styling in calendar interventions --- .../calendar/interventions_calendar.js | 11 +++++++++-- loko/interventions/views/calendar.py | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/loko/interventions/static/interventions/calendar/interventions_calendar.js b/loko/interventions/static/interventions/calendar/interventions_calendar.js index 815b163..b9261ae 100644 --- a/loko/interventions/static/interventions/calendar/interventions_calendar.js +++ b/loko/interventions/static/interventions/calendar/interventions_calendar.js @@ -532,10 +532,17 @@ document.addEventListener('DOMContentLoaded', function () { const formattedMembers = dayData.members.map(m => { const name = typeof m === 'object' && m ? m.name : m; const id = typeof m === 'object' && m ? m.id : null; + const isAbsent = typeof m === 'object' && m ? Boolean(m.is_absent) : false; + const absenceReason = typeof m === 'object' && m ? (m.absence_reason || '') : ''; + + let memberNameHtml = escapeHtml(name); if (isMemberHistoryAllowed && id) { - return `${escapeHtml(name)}`; + memberNameHtml = `${escapeHtml(name)}`; } - return escapeHtml(name); + if (isAbsent) { + return `${memberNameHtml} ${escapeHtml(absenceReason || gettext('Absent'))}`; + } + return memberNameHtml; }).join(', '); membersHTML = `
${formattedMembers} diff --git a/loko/interventions/views/calendar.py b/loko/interventions/views/calendar.py index 76f54fb..9026337 100644 --- a/loko/interventions/views/calendar.py +++ b/loko/interventions/views/calendar.py @@ -1506,6 +1506,11 @@ def member_history_ajax(request, member_id): ) company_str = ", ".join(sorted(company_names)) if company_names else '—' + # 0. Récupérer les dates d'absences du membre + absent_dates = set( + CompanyMemberAbsence.objects.filter(member=member).values_list('date', flat=True) + ) + # 1. Équipes et périodes valides du membre selon CompanyMemberHistory team_periods_q = Q() for h in team_history_qs: @@ -1527,7 +1532,7 @@ def member_history_ajax(request, member_id): .order_by('-date', '-intervention__id') ) - # 3. Dédoublonnage strict par ID d'intervention + # 3. Dédoublonnage strict par ID d'intervention et exclusion des jours d'absence seen_itv_ids = set() interventions_dict = {} @@ -1535,6 +1540,9 @@ def member_history_ajax(request, member_id): itv = a.intervention if not itv or itv.id in seen_itv_ids: continue + # Si le membre était absent ce jour-là et n'était pas nommément assigné + if a.date and a.date in absent_dates and a.member_id != member.id: + continue seen_itv_ids.add(itv.id) interventions_dict[itv.id] = { 'id': itv.id, @@ -1564,17 +1572,20 @@ def member_history_ajax(request, member_id): for itv in extra_itvs: if itv.id in seen_itv_ids: continue - seen_itv_ids.add(itv.id) itv_date = (itv.end_time or itv.begin_time or itv.planned_begin_time or itv.creation_time) if itv_date: itv_date_local = timezone.localtime(itv_date) if timezone.is_aware(itv_date) else itv_date + itv_date_only = itv_date_local.date() + if itv_date_only in absent_dates and itv.assigned_member_id != member.id and not itv.occupations.filter(member=member).exists(): + continue date_str = itv_date_local.strftime('%d/%m/%Y') raw_date_str = itv_date_local.date().isoformat() else: date_str = '' raw_date_str = '' + seen_itv_ids.add(itv.id) interventions_dict[itv.id] = { 'id': itv.id, 'code': itv.code,