Update daily shifts by day to handle changed week start (#2263)

Related to
https://github.com/grafana/oncall/issues/2118#issuecomment-1592889257
This commit is contained in:
Matias Bordese 2023-06-15 22:01:32 -03:00 committed by GitHub
parent 85beacaeb0
commit 91461991de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 6 deletions

View file

@ -324,12 +324,14 @@ class CustomOnCallShift(models.Model):
break
last_start = start
day = CustomOnCallShift.ICAL_WEEKDAY_MAP[start.weekday()]
if (user_group_id, day, i) in combinations:
all_rotations_checked = True
break
# double-check day is valid (when until is set, we may get unexpected days)
if day in self.by_day:
if (user_group_id, day, i) in combinations:
all_rotations_checked = True
break
starting_dates.append(start)
combinations.append((user_group_id, day, i))
starting_dates.append(start)
combinations.append((user_group_id, day, i))
# get next event date following the original rule
event_ical = self.generate_ical(start, 1, None, 1, time_zone, custom_rrule=day_by_day_rrule)
start = self.get_rotation_date(event_ical, get_next_date=True, interval=1)
@ -386,7 +388,10 @@ class CustomOnCallShift(models.Model):
if self.frequency is not None and self.by_day and start is not None:
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)
# when calculating first start date, make sure to sort days using week_start
sorted_days = [i % 7 for i in range(self.week_start, self.week_start + 7)]
selected_days = [CustomOnCallShift.ICAL_WEEKDAY_REVERSE_MAP[d] for d in self.by_day]
expected_start_day = [d for d in sorted_days if d in selected_days][0]
delta = (expected_start_day - start.weekday()) % 7
start = start + datetime.timedelta(days=delta)

View file

@ -1712,3 +1712,80 @@ def test_until_rrule_must_be_utc(
expected_rrule = f"RRULE:FREQ=WEEKLY;UNTIL={ical_rrule_until}Z;INTERVAL=4;WKST=SU"
assert expected_rrule in ical_data
@pytest.mark.django_db
def test_week_start_changed_daily_shift(
make_organization_and_user,
make_schedule,
make_on_call_shift,
):
organization, user_1 = make_organization_and_user()
schedule = make_schedule(organization, schedule_class=OnCallScheduleWeb, time_zone="Europe/Warsaw")
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
today_weekday = now.weekday()
last_sunday = now - timezone.timedelta(days=7 + (today_weekday + 1) % 7)
last_saturday = last_sunday - timezone.timedelta(days=1)
# set week start to Sunday, so first event should be on last_sunday itself
data = {
"priority_level": 1,
"start": last_saturday,
"rotation_start": last_sunday,
"duration": timezone.timedelta(seconds=3600),
"frequency": CustomOnCallShift.FREQUENCY_DAILY,
"by_day": ["MO", "SU"],
"week_start": 5, # SU
"interval": 1,
"schedule": schedule,
}
on_call_shift = make_on_call_shift(
organization=organization, shift_type=CustomOnCallShift.TYPE_ROLLING_USERS_EVENT, **data
)
rolling_users = [[user_1]]
on_call_shift.add_rolling_users(rolling_users)
ical_data = on_call_shift.convert_to_ical()
expected_start = "DTSTART;VALUE=DATE-TIME:{}T000000Z".format(last_sunday.strftime("%Y%m%d"))
assert expected_start in ical_data
@pytest.mark.django_db
def test_week_start_changed_daily_shift_until(
make_organization_and_user,
make_schedule,
make_on_call_shift,
):
organization, user_1 = make_organization_and_user()
schedule = make_schedule(organization, schedule_class=OnCallScheduleWeb, time_zone="Europe/Warsaw")
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
today_weekday = now.weekday()
last_sunday = now - timezone.timedelta(days=7 + (today_weekday + 1) % 7)
last_saturday = last_sunday - timezone.timedelta(days=1)
thursday = last_sunday + timezone.timedelta(days=4)
data = {
"priority_level": 1,
"start": last_saturday,
"rotation_start": last_sunday,
"duration": timezone.timedelta(seconds=3600),
"frequency": CustomOnCallShift.FREQUENCY_DAILY,
"by_day": ["MO", "SU"],
"week_start": 5, # SU
"interval": 1,
"until": thursday,
"schedule": schedule,
}
on_call_shift = make_on_call_shift(
organization=organization, shift_type=CustomOnCallShift.TYPE_ROLLING_USERS_EVENT, **data
)
rolling_users = [[user_1]]
on_call_shift.add_rolling_users(rolling_users)
ical_data = on_call_shift.convert_to_ical()
# setting UNTIL to Thursday was generating extra events for current week Wednesday and Thursday
unexpected_by_days = ("BYDAY=WE", "BYDAY=TH")
for unexpected in unexpected_by_days:
assert unexpected not in ical_data