From 4aca5705498d706fc403786a2eca8378d8ca11a3 Mon Sep 17 00:00:00 2001 From: Matias Bordese Date: Mon, 7 Nov 2022 17:38:10 -0300 Subject: [PATCH] Ensure start date matches by_day selection --- .../schedules/models/custom_on_call_shift.py | 9 ++++ .../tests/test_custom_on_call_shift.py | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/engine/apps/schedules/models/custom_on_call_shift.py b/engine/apps/schedules/models/custom_on_call_shift.py index c285dba9..96cc2db2 100644 --- a/engine/apps/schedules/models/custom_on_call_shift.py +++ b/engine/apps/schedules/models/custom_on_call_shift.py @@ -121,6 +121,7 @@ class CustomOnCallShift(models.Model): SATURDAY: "SA", SUNDAY: "SU", } + ICAL_WEEKDAY_REVERSE_MAP = {v: k for k, v in ICAL_WEEKDAY_MAP.items()} WEB_WEEKDAY_MAP = { "MO": "Monday", @@ -365,6 +366,14 @@ class CustomOnCallShift(models.Model): else: start = self.get_rotation_date(event_ical) + # Make sure we respect the selected days if any when defining start date + if self.frequency is not None and self.by_day: + start_day = CustomOnCallShift.ICAL_WEEKDAY_MAP[start.weekday()] + if start_day not in self.by_day: + expected_start_day = min(CustomOnCallShift.ICAL_WEEKDAY_REVERSE_MAP[d] for d in self.by_day) + delta = (expected_start_day - start.weekday()) % 7 + start = start + timezone.timedelta(days=delta) + if self.frequency == CustomOnCallShift.FREQUENCY_DAILY and self.by_day: result = self._daily_by_day_to_ical(time_zone, start, users_queue) all_rotation_checked = True diff --git a/engine/apps/schedules/tests/test_custom_on_call_shift.py b/engine/apps/schedules/tests/test_custom_on_call_shift.py index 8a746169..3da17a66 100644 --- a/engine/apps/schedules/tests/test_custom_on_call_shift.py +++ b/engine/apps/schedules/tests/test_custom_on_call_shift.py @@ -386,6 +386,55 @@ def test_rolling_users_event_daily_by_day( assert len(users_on_call) == 0 +@pytest.mark.django_db +def test_rolling_users_event_daily_by_day_off_start(make_organization_and_user, make_on_call_shift, make_schedule): + organization, user_1 = make_organization_and_user() + + schedule = make_schedule(organization, schedule_class=OnCallScheduleWeb) + now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) + current_week_monday = now - timezone.timedelta(days=now.weekday()) + + # WE, FR + weekdays = [2, 4] + by_day = [CustomOnCallShift.ICAL_WEEKDAY_MAP[day] for day in weekdays] + data = { + "priority_level": 1, + "start": current_week_monday, + "rotation_start": current_week_monday, + "duration": timezone.timedelta(seconds=10800), + "frequency": CustomOnCallShift.FREQUENCY_DAILY, + "interval": 1, + "by_day": by_day, + "schedule": schedule, + } + rolling_users = [[user_1]] + on_call_shift = make_on_call_shift( + organization=organization, shift_type=CustomOnCallShift.TYPE_ROLLING_USERS_EVENT, **data + ) + on_call_shift.add_rolling_users(rolling_users) + + date = current_week_monday + timezone.timedelta(minutes=5) + + user_1_on_call_dates = [date + timezone.timedelta(days=2), date + timezone.timedelta(days=4)] + nobody_on_call_dates = [ + date, # MO + date + timezone.timedelta(days=1), # TU + date + timezone.timedelta(days=3), # TH + date + timezone.timedelta(days=5), # SA + date + timezone.timedelta(days=6), # SU + date + timezone.timedelta(days=7), # MO + ] + + for dt in user_1_on_call_dates: + users_on_call = list_users_to_notify_from_ical(schedule, dt) + assert len(users_on_call) == 1 + assert user_1 in users_on_call + + for dt in nobody_on_call_dates: + users_on_call = list_users_to_notify_from_ical(schedule, dt) + assert len(users_on_call) == 0 + + @pytest.mark.django_db def test_rolling_users_event_with_interval_daily_by_day( make_organization_and_user, make_user_for_organization, make_on_call_shift, make_schedule