fix: synchronize intervention status history by including all status events and ensuring the final state matches current intervention status.

This commit is contained in:
kdeterme 2026-08-24 18:46:27 +02:00
parent a21aa59fa9
commit 7d3362d770
3 changed files with 61 additions and 3 deletions

View file

@ -124,6 +124,51 @@ class CalendarEventsTests(TestCase):
self.assertEqual(len(history), 1) self.assertEqual(len(history), 1)
self.assertEqual(history[0]['status_code'], 'to_be_approved') 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): def test_calendar_events_view_mode_members_no_duplicates(self):
# Request calendar events in member view mode # Request calendar events in member view mode
url = reverse('interventions:interventions_events') + '?view_mode=members' url = reverse('interventions:interventions_events') + '?view_mode=members'

View file

@ -485,7 +485,9 @@ def interventions_events(request):
interventions = interventions.prefetch_related( interventions = interventions.prefetch_related(
Prefetch( Prefetch(
'events', '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', to_attr='status_events',
) )
) )
@ -506,12 +508,23 @@ def interventions_events(request):
for evt in status_events: for evt in status_events:
code = evt.to_status or itv.status code = evt.to_status or itv.status
user_name = get_short_name(evt.event_user) if evt.event_user else None 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_history.append({
'status_code': code, 'status_code': code,
'status_label': str(STATUS_CHOICES.get(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, '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: else:
ref_time = itv.begin_time or itv.creation_time or itv.effective_begin ref_time = itv.begin_time or itv.creation_time or itv.effective_begin
status_history.append({ status_history.append({

View file

@ -2255,7 +2255,7 @@ def transfer_intervention(request, intervention_id):
intervention=intervention, intervention=intervention,
event_user=request.user, event_user=request.user,
event_time=event_time, event_time=event_time,
event_type='status', event_type='status_change',
from_status=old_status, from_status=old_status,
to_status=intervention.status, to_status=intervention.status,
) )