Skip to content

Commit

Permalink
Validate booking slot's weekday in schedule timezone. (Fixes #735) (#744
Browse files Browse the repository at this point in the history
)

* Validate booking slot's weekday in schedule timezone. (Fixes #735)

* Update backend/src/appointment/routes/schedule.py

Co-authored-by: Andreas <[email protected]>

* Add some comments to the test

---------

Co-authored-by: Andreas <[email protected]>
  • Loading branch information
MelissaAutumn and devmount authored Nov 18, 2024
1 parent 996e63d commit 8094904
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 10 deletions.
16 changes: 11 additions & 5 deletions backend/src/appointment/routes/schedule.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import zoneinfo

import sentry_sdk
from fastapi import APIRouter, Depends, BackgroundTasks, Request
import logging
Expand Down Expand Up @@ -48,6 +50,7 @@
limiter = Limiter(key_func=get_remote_address)



def is_this_a_valid_booking_time(schedule: models.Schedule, booking_slot: schemas.SlotBase) -> bool:
"""Checks for timezone correctness, weekday and start/end time validity."""
# For now lets only accept utc bookings as that's what our frontend supplies us.
Expand All @@ -62,7 +65,9 @@ def is_this_a_valid_booking_time(schedule: models.Schedule, booking_slot: schema
return False

# Is the time requested on a day of the week they have disabled?
iso_weekday = int(booking_slot.start.strftime('%u'))
# This should be based on the schedule timezone
start_date_tz = booking_slot.start.astimezone(zoneinfo.ZoneInfo(schedule.timezone))
iso_weekday = int(start_date_tz.strftime('%u'))
if iso_weekday not in schedule.weekdays:
return False

Expand All @@ -73,10 +78,11 @@ def is_this_a_valid_booking_time(schedule: models.Schedule, booking_slot: schema

booking_slot_end = booking_slot.start + timedelta(minutes=schedule.slot_duration)

if (
booking_slot.start < datetime.combine(today, schedule.start_time, tzinfo=timezone.utc)
or booking_slot_end > datetime.combine(today, schedule.end_time, tzinfo=timezone.utc) + timedelta(days=add_day)
):
too_early = booking_slot.start < datetime.combine(today, schedule.start_time, tzinfo=timezone.utc)
too_late = booking_slot_end > (
datetime.combine(today, schedule.end_time, tzinfo=timezone.utc) + timedelta(days=add_day)
)
if too_early or too_late:
return False

return True
Expand Down
41 changes: 36 additions & 5 deletions backend/test/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def test_failure(self):

class TestIsAValidBookingTime:
def test_bug_735(self, make_schedule):
"""A test case to cover unsuccessfully capturing bug 735, which is the seemingly random slot not found issue.
Ref: https://github.com/thunderbird/appointment/issues/735"""
# Request data submitted from bug and anonymized.
request_data = {
's_a': {
Expand All @@ -83,14 +85,43 @@ def test_bug_735(self, make_schedule):
end_time=0, # 5PM PDT
timezone='America/Vancouver',
# This is not accurate, but it was probably saved before Nov 3rd.
time_updated=datetime.datetime(2024, 11, 1, 12, 0,0, tzinfo=datetime.UTC),
time_updated=datetime.datetime(2024, 11, 1, 12, 0, 0, tzinfo=datetime.UTC),
)

# Freeze on the datetime that the error occurred on
with freeze_time('2024-11-04T09:09:29.530Z'):
is_valid = is_this_a_valid_booking_time(
schedule,
s_a.slot
)
is_valid = is_this_a_valid_booking_time(schedule, s_a.slot)

assert is_valid is True

def test_bug_735_case_2(self, make_schedule):
"""A test case to cover successfully capturing bug 735, which is the seemingly random slot not found issue.
Ref: https://github.com/thunderbird/appointment/issues/735"""
# Request data submitted from bug and anonymized.
request_data = {
's_a': {
'slot': {'start': '2024-11-17T22:00:00.000Z', 'duration': 30},
'attendee': {'name': 'melissa', 'email': '[email protected]', 'timezone': 'Australia/Sydney'},
},
'url': 'http://localhost:8080/user/username/example/',
}

s_a = schemas.AvailabilitySlotAttendee(**request_data['s_a'])

schedule = make_schedule(
active=True,
start_date=datetime.date(2024, 11, 7),
end_date=None,
earliest_booking=0,
farthest_booking=10080,
weekdays=[1, 2, 3, 4, 5],
slot_duration=30,
start_time="22:00", # 9AM AEDT
end_time="06:00", # 5PM AEDT
timezone='Australia/Sydney',
time_updated=datetime.datetime(2024, 11, 15, 12, 0, 0, tzinfo=datetime.UTC),
)

is_valid = is_this_a_valid_booking_time(schedule, s_a.slot)

assert is_valid is True

0 comments on commit 8094904

Please sign in to comment.