Fix for final event calculation when splitting events
This commit is contained in:
parent
8e8806dcba
commit
1ba742d99e
2 changed files with 81 additions and 7 deletions
|
|
@ -276,14 +276,18 @@ class OnCallSchedule(PolymorphicModel):
|
|||
if not events:
|
||||
return []
|
||||
|
||||
# sort schedule events by (type desc, priority desc, start timestamp asc)
|
||||
events.sort(
|
||||
key=lambda e: (
|
||||
-e["calendar_type"] if e["calendar_type"] else 0, # overrides: 1, shifts: 0, gaps: None
|
||||
-e["priority_level"] if e["priority_level"] else 0,
|
||||
e["start"],
|
||||
def apply_sorting(eventlist):
|
||||
"""Sort events keeping the events priority criteria."""
|
||||
eventlist.sort(
|
||||
key=lambda e: (
|
||||
-e["calendar_type"] if e["calendar_type"] else 0, # overrides: 1, shifts: 0, gaps: None
|
||||
-e["priority_level"] if e["priority_level"] else 0,
|
||||
e["start"],
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# sort schedule events by (type desc, priority desc, start timestamp asc)
|
||||
apply_sorting(events)
|
||||
|
||||
def _merge_intervals(evs):
|
||||
"""Keep track of scheduled intervals."""
|
||||
|
|
@ -345,6 +349,9 @@ class OnCallSchedule(PolymorphicModel):
|
|||
# event ends after current interval, update event start timestamp to match the interval end
|
||||
# and process the updated event as any other event
|
||||
ev["start"] = intervals[current_interval_idx][1]
|
||||
# reorder pending events after updating current event start date
|
||||
# (ie. insert the event where it should be to keep the order criteria)
|
||||
apply_sorting(pending)
|
||||
else:
|
||||
# done, go to next event
|
||||
current_event_idx += 1
|
||||
|
|
|
|||
|
|
@ -322,6 +322,73 @@ def test_final_schedule_events(make_organization, make_user_for_organization, ma
|
|||
assert returned_events == expected_events
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_final_schedule_splitting_events(
|
||||
make_organization, make_user_for_organization, make_on_call_shift, make_schedule
|
||||
):
|
||||
organization = make_organization()
|
||||
schedule = make_schedule(
|
||||
organization,
|
||||
schedule_class=OnCallScheduleWeb,
|
||||
name="test_web_schedule",
|
||||
)
|
||||
|
||||
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
start_date = now - timezone.timedelta(days=7)
|
||||
|
||||
user_a, user_b, user_c = (make_user_for_organization(organization, username=i) for i in "ABC")
|
||||
|
||||
shifts = (
|
||||
# user, priority, start time (h), duration (hs)
|
||||
(user_a, 1, 10, 10), # r1-1: 10-20 / A
|
||||
(user_b, 1, 12, 4), # r1-2: 12-16 / B
|
||||
(user_c, 2, 15, 3), # r2-1: 15-18 / C
|
||||
)
|
||||
for user, priority, start_h, duration in shifts:
|
||||
data = {
|
||||
"start": start_date + timezone.timedelta(hours=start_h),
|
||||
"rotation_start": start_date + timezone.timedelta(hours=start_h),
|
||||
"duration": timezone.timedelta(hours=duration),
|
||||
"priority_level": priority,
|
||||
"frequency": CustomOnCallShift.FREQUENCY_DAILY,
|
||||
"schedule": schedule,
|
||||
}
|
||||
on_call_shift = make_on_call_shift(
|
||||
organization=organization, shift_type=CustomOnCallShift.TYPE_ROLLING_USERS_EVENT, **data
|
||||
)
|
||||
on_call_shift.add_rolling_users([[user]])
|
||||
|
||||
returned_events = schedule.final_events("UTC", start_date, days=1)
|
||||
|
||||
expected = (
|
||||
# start (h), duration (H), user, priority
|
||||
(10, 5, "A", 1), # 10-15 A
|
||||
(12, 3, "B", 1), # 12-15 B
|
||||
(15, 3, "C", 2), # 15-18 C
|
||||
(18, 2, "A", 1), # 18-20 A
|
||||
)
|
||||
expected_events = [
|
||||
{
|
||||
"end": start_date + timezone.timedelta(hours=start + duration),
|
||||
"priority_level": priority,
|
||||
"start": start_date + timezone.timedelta(hours=start),
|
||||
"user": user,
|
||||
}
|
||||
for start, duration, user, priority in expected
|
||||
]
|
||||
returned_events = [
|
||||
{
|
||||
"end": e["end"],
|
||||
"priority_level": e["priority_level"],
|
||||
"start": e["start"],
|
||||
"user": e["users"][0]["display_name"] if e["users"] else None,
|
||||
}
|
||||
for e in returned_events
|
||||
if not e["is_gap"]
|
||||
]
|
||||
assert returned_events == expected_events
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_preview_shift(make_organization, make_user_for_organization, make_schedule, make_on_call_shift):
|
||||
organization = make_organization()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue