From 7d3362d770e88839bdc2569886db535ab581cb8d Mon Sep 17 00:00:00 2001 From: kdeterme Date: Mon, 24 Aug 2026 18:46:27 +0200 Subject: [PATCH] fix: synchronize intervention status history by including all status events and ensuring the final state matches current intervention status. --- loko/interventions/tests/test_calendar.py | 45 +++++++++++++++++++++++ loko/interventions/views/calendar.py | 17 ++++++++- loko/interventions/views/mobile.py | 2 +- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/loko/interventions/tests/test_calendar.py b/loko/interventions/tests/test_calendar.py index b5df389..bed5cd3 100644 --- a/loko/interventions/tests/test_calendar.py +++ b/loko/interventions/tests/test_calendar.py @@ -124,6 +124,51 @@ class CalendarEventsTests(TestCase): self.assertEqual(len(history), 1) self.assertEqual(history[0]['status_code'], 'to_be_approved') + def test_timeline_events_captures_all_events_and_guarantees_current_status(self): + now = timezone.now() + itv = Intervention.objects.create( + title='Paused Intervention', + status='on_hold', + assigned_member=self.member, + ) + InterventionTimeLine.objects.create( + intervention=itv, + event_type='status_change', + from_status='to_be_processed', + to_status='in_charge', + event_time=now - timedelta(hours=3), + event_user=self.user, + ) + InterventionTimeLine.objects.create( + intervention=itv, + event_type='status_change', + from_status='in_charge', + to_status='in_progress', + event_time=now - timedelta(hours=2), + event_user=self.user, + ) + # Event created with event_type='status' (e.g. from transfer) + InterventionTimeLine.objects.create( + intervention=itv, + event_type='status', + from_status='in_progress', + to_status='on_hold', + event_time=now - timedelta(hours=1), + event_user=self.user, + ) + + url = reverse('interventions:interventions_events') + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + events = response.json() + itv_event = next((e for e in events if e['id'] == itv.id), None) + self.assertIsNotNone(itv_event) + + ext = itv_event.get('extendedProps', {}) + history = ext['status_history'] + self.assertEqual(len(history), 3) + self.assertEqual(history[-1]['status_code'], 'on_hold') + def test_calendar_events_view_mode_members_no_duplicates(self): # Request calendar events in member view mode url = reverse('interventions:interventions_events') + '?view_mode=members' diff --git a/loko/interventions/views/calendar.py b/loko/interventions/views/calendar.py index 6a93442..4f17913 100644 --- a/loko/interventions/views/calendar.py +++ b/loko/interventions/views/calendar.py @@ -485,7 +485,9 @@ def interventions_events(request): interventions = interventions.prefetch_related( Prefetch( 'events', - queryset=InterventionTimeLine.objects.filter(event_type='status_change').select_related('event_user').order_by('event_time'), + queryset=InterventionTimeLine.objects.filter( + Q(event_type__in=['status_change', 'status']) | Q(to_status__isnull=False) + ).select_related('event_user').order_by('event_time'), to_attr='status_events', ) ) @@ -506,12 +508,23 @@ def interventions_events(request): for evt in status_events: code = evt.to_status or itv.status user_name = get_short_name(evt.event_user) if evt.event_user else None + event_iso = evt.event_time.isoformat() if evt.event_time else None + if status_history and status_history[-1]['status_code'] == code and status_history[-1]['event_time'] == event_iso: + continue status_history.append({ 'status_code': code, 'status_label': str(STATUS_CHOICES.get(code, code)), - 'event_time': evt.event_time.isoformat() if evt.event_time else None, + 'event_time': event_iso, 'user_name': user_name, }) + if status_history and status_history[-1]['status_code'] != itv.status: + ref_time = itv.effective_begin or itv.begin_time or itv.creation_time or timezone.now() + status_history.append({ + 'status_code': itv.status, + 'status_label': itv.get_status_display(), + 'event_time': ref_time.isoformat() if ref_time else None, + 'user_name': None, + }) else: ref_time = itv.begin_time or itv.creation_time or itv.effective_begin status_history.append({ diff --git a/loko/interventions/views/mobile.py b/loko/interventions/views/mobile.py index efd5504..4199611 100644 --- a/loko/interventions/views/mobile.py +++ b/loko/interventions/views/mobile.py @@ -2255,7 +2255,7 @@ def transfer_intervention(request, intervention_id): intervention=intervention, event_user=request.user, event_time=event_time, - event_type='status', + event_type='status_change', from_status=old_status, to_status=intervention.status, )