Google Calendar Integration - consider current oncall shifts for autogeneration of shift swap requests (#4160)

# What this PR does

Fixes issue where you create a Google Calendar OOO that overlaps with an
in-progress oncall shift (currently we only consider future/upcoming
shifts).

Related to https://github.com/grafana/oncall-private/issues/2555

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
This commit is contained in:
Joey Orlando 2024-04-05 09:15:05 -04:00 committed by GitHub
parent 2f33d1ab56
commit 3f24bfce95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 8 deletions

View file

@ -41,16 +41,16 @@ def sync_out_of_office_calendar_events_for_user(google_oauth2_user_pk: int) -> N
)
for schedule in users_schedules:
_, _, upcoming_shifts = schedule.shifts_for_user(
_, current_shifts, upcoming_shifts = schedule.shifts_for_user(
user,
start_time_utc,
datetime_end=end_time_utc,
)
if upcoming_shifts:
if current_shifts or upcoming_shifts:
logger.info(
f"Found {len(upcoming_shifts)} upcoming shift(s) for user {user_id} "
f"during the out of office event {event_id}"
f"Found {len(current_shifts)} current shift(s) and {len(upcoming_shifts)} upcoming shift(s) "
f"for user {user_id} during the out of office event {event_id}"
)
shift_swap_request_exists = ShiftSwapRequest.objects.filter(
@ -78,7 +78,9 @@ def sync_out_of_office_calendar_events_for_user(google_oauth2_user_pk: int) -> N
else:
logger.info(f"Shift swap request already exists for user {user_id} schedule {schedule.pk}")
else:
logger.info(f"No upcoming shifts found for user {user_id} during the out of office event {event_id}")
logger.info(
f"No current or upcoming shifts found for user {user_id} during the out of office event {event_id}"
)
@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True)

View file

@ -56,10 +56,16 @@ def _create_mock_google_calendar_event(start_time: datetime.datetime, end_time:
}
def _get_utc_now():
return datetime.datetime.now(tz=datetime.timezone.utc)
def _adjust_datetime(dt):
return dt.replace(second=0, microsecond=0)
def _create_event_start_and_end_times(start_days_in_future=5, end_time_minutes_past_start=50):
start_time = (
datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(days=start_days_in_future)
).replace(second=0, microsecond=0)
start_time = _adjust_datetime(_get_utc_now() + datetime.timedelta(days=start_days_in_future))
end_time = start_time + datetime.timedelta(minutes=end_time_minutes_past_start)
return start_time, end_time
@ -259,6 +265,29 @@ def test_sync_out_of_office_calendar_events_for_user_no_upcoming_shifts(
assert ShiftSwapRequest.objects.filter(beneficiary=user).count() == 0
@patch("apps.google.client.build")
@pytest.mark.django_db
def test_sync_out_of_office_calendar_events_for_user_considers_current_shifts(
mock_google_api_client_build,
test_setup,
):
in_five_minutes = _adjust_datetime(_get_utc_now() + datetime.timedelta(minutes=5))
in_ten_minutes = in_five_minutes + datetime.timedelta(minutes=5)
mock_google_api_client_build.return_value.events.return_value.list.return_value.execute.return_value = {
"items": [
_create_mock_google_calendar_event(in_five_minutes, in_ten_minutes),
],
}
google_oauth2_user, _ = test_setup([])
user = google_oauth2_user.user
tasks.sync_out_of_office_calendar_events_for_user(google_oauth2_user.pk)
assert ShiftSwapRequest.objects.filter(beneficiary=user).count() == 1
@patch("apps.google.client.build")
@pytest.mark.django_db
def test_sync_out_of_office_calendar_events_for_user_preexisting_shift_swap_request(