diff --git a/loko/interventions/views/calendar.py b/loko/interventions/views/calendar.py index 41a7eed..6292624 100644 --- a/loko/interventions/views/calendar.py +++ b/loko/interventions/views/calendar.py @@ -1506,19 +1506,7 @@ def member_history_ajax(request, member_id): ) company_str = ", ".join(sorted(company_names)) if company_names else '—' - # Filter assignments: - # 1. Directly assigned to this member in InterventionAssignment - assignment_q = Q(member=member) - - # 2. Directly assigned / acted upon by member user on Intervention - if member.user_id: - assignment_q |= ( - Q(intervention__assigned_member=member) | - Q(intervention__realized_events__event_user=member.user) | - Q(intervention__occupations__member=member) - ) - - # 3. Interventions assigned to teams during the periods member was in that team + # 1. Équipes et périodes valides du membre selon CompanyMemberHistory team_periods_q = Q() for h in team_history_qs: if h.team_id and h.join_date: @@ -1527,10 +1515,8 @@ def member_history_ajax(request, member_id): tq &= Q(date__lte=h.leave_date) team_periods_q |= tq - for t in member.teams.all(): - if not team_history_qs.filter(team=t).exists(): - team_periods_q |= Q(team=t) - + # 2. Récupérer les affectations d'interventions liées au membre + assignment_q = Q(member=member) if team_periods_q: assignment_q |= team_periods_q @@ -1538,26 +1524,31 @@ def member_history_ajax(request, member_id): InterventionAssignment.objects .filter(assignment_q) .select_related('intervention', 'team') - .order_by('-date', '-intervention__code', '-intervention__id')[:100] + .order_by('-date', '-intervention__id') ) - interventions_list = [ - { - 'id': a.intervention.id, - 'code': a.intervention.code, - 'title': a.intervention.title, + # 3. Dédoublonnage strict par ID d'intervention + seen_itv_ids = set() + interventions_dict = {} + + for a in assignments_qs: + itv = a.intervention + if not itv or itv.id in seen_itv_ids: + continue + seen_itv_ids.add(itv.id) + interventions_dict[itv.id] = { + 'id': itv.id, + 'code': itv.code, + 'title': itv.title, 'date': a.date.strftime('%d/%m/%Y') if a.date else '', 'raw_date': a.date.isoformat() if a.date else '', - 'team_name': a.team.name if a.team else (a.intervention.assigned_team.name if a.intervention.assigned_team else '—'), - 'status_code': a.intervention.status, - 'status_display': a.intervention.get_status_display(), - 'detail_url': reverse('interventions:intervention_detail', args=[a.intervention.id]), + 'team_name': a.team.name if a.team else (itv.assigned_team.name if itv.assigned_team else '—'), + 'status_code': itv.status, + 'status_display': itv.get_status_display(), + 'detail_url': reverse('interventions:intervention_detail', args=[itv.id]), } - for a in assignments_qs - ] - # Include any extra interventions directly assigned/realized by member without an InterventionAssignment - assigned_itv_ids = set(a.intervention.id for a in assignments_qs) + # 4. Interventions directement assignées ou réalisées personnellement par le membre direct_itvs_q = Q(assigned_member=member) if member.user_id: direct_itvs_q |= Q(realized_events__event_user=member.user) | Q(occupations__member=member) @@ -1565,10 +1556,16 @@ def member_history_ajax(request, member_id): extra_itvs = ( Intervention.objects .filter(direct_itvs_q) - .exclude(id__in=assigned_itv_ids) - .select_related('assigned_team')[:50] + .exclude(id__in=seen_itv_ids) + .select_related('assigned_team') + .distinct()[:50] ) + 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 @@ -1578,7 +1575,7 @@ def member_history_ajax(request, member_id): date_str = '' raw_date_str = '' - interventions_list.append({ + interventions_dict[itv.id] = { 'id': itv.id, 'code': itv.code, 'title': itv.title, @@ -1588,10 +1585,11 @@ def member_history_ajax(request, member_id): 'status_code': itv.status, 'status_display': itv.get_status_display(), 'detail_url': reverse('interventions:intervention_detail', args=[itv.id]), - }) + } + interventions_list = list(interventions_dict.values()) interventions_list.sort(key=lambda x: (x['raw_date'], x['code'] or '', x['id']), reverse=True) - interventions_list = interventions_list[:100] + interventions_list = interventions_list[:50] return JsonResponse({ 'member': {