Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/351 allow booking as of now #355

Merged
merged 3 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions backend/src/appointment/controller/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,10 @@ def available_slots_from_schedule(schedule: models.Schedule) -> list[schemas.Slo
subscriber = schedule.calendar.owner
timezone = zoneinfo.ZoneInfo(subscriber.timezone)

now_tz = datetime.now(tz=timezone)
not_tz_midnight = now_tz.replace(hour=0, minute=0, second=0, microsecond=0)
now_tz_total_seconds = now_tz.timestamp() - not_tz_midnight.timestamp()

# Start and end time in the subscriber's timezone
start_time_local = schedule.start_time_local
end_time_local = schedule.end_time_local
Expand All @@ -450,7 +454,8 @@ def available_slots_from_schedule(schedule: models.Schedule) -> list[schemas.Slo
farthest_booking = now + timedelta(days=1, minutes=schedule.farthest_booking)

schedule_start = max([datetime.combine(schedule.start_date, start_time_local), earliest_booking])
schedule_end = min([datetime.combine(schedule.end_date, end_time_local), farthest_booking]) if schedule.end_date else farthest_booking
schedule_end = min([datetime.combine(schedule.end_date, end_time_local),
farthest_booking]) if schedule.end_date else farthest_booking

start_time = datetime.combine(now.min, start_time_local) - datetime.min
end_time = datetime.combine(now.min, end_time_local) - datetime.min
Expand All @@ -467,23 +472,41 @@ def available_slots_from_schedule(schedule: models.Schedule) -> list[schemas.Slo
# Difference of the start and end time. Since our times are localized we start at 0, and go until we hit the diff.
total_time = int(end_time.total_seconds()) - int(start_time.total_seconds())

slot_duration_seconds = schedule.slot_duration * 60

# Between the available booking time
for ordinal in range(schedule_start.toordinal(), schedule_end.toordinal()):
time_start = 0

# If it's today and now is greater than our normal start time...
if now_tz.toordinal() == ordinal and now_tz_total_seconds > start_time.total_seconds():
# Note: This is in seconds!
# Get the offset from now to 0:00:00, and adjust it so 0 aligns with our start_time.
# (So if the date is today it's 9am, and our start time is also 9am then time_start should be 0)
time_start = int(now_tz_total_seconds - start_time.total_seconds())

# Round up to the nearest slot duration, I'm bad at math...
# Get the remainder of the slow, subtract that from our time_start, then add the slot duration back in.
time_start -= (time_start % slot_duration_seconds)
time_start += slot_duration_seconds

date = datetime.fromordinal(ordinal)
current_datetime = datetime(year=date.year, month=date.month, day=date.day, hour=start_time_local.hour, minute=start_time_local.minute, tzinfo=timezone)
current_datetime = datetime(year=date.year, month=date.month, day=date.day, hour=start_time_local.hour,
minute=start_time_local.minute, tzinfo=timezone)
# Check if this weekday is within our schedule
if current_datetime.isoweekday() in weekdays:
# Generate each timeslot based on the selected duration
# We just loop through the difference of the start and end time and step by slot duration in seconds.
slots += [
schemas.SlotBase(start=current_datetime + timedelta(seconds=time), duration=schedule.slot_duration)
for time in range(0, total_time, schedule.slot_duration * 60)
for time in range(time_start, total_time, slot_duration_seconds)
]

return slots

@staticmethod
def events_roll_up_difference(a_list: list[schemas.SlotBase], b_list: list[schemas.Event]) -> list[schemas.SlotBase]:
def events_roll_up_difference(a_list: list[schemas.SlotBase], b_list: list[schemas.Event]) -> list[
schemas.SlotBase]:
"""This helper rolls up all events from list A, which have a time collision with any event in list B
and returns all remaining elements from A as new list.
"""
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/components/ScheduleCreation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,12 @@ const charCount = computed(() => scheduleInput.value.details.length);

// booking options
const earliestOptions = {};
[0.5, 1, 2, 3, 4, 5].forEach((d) => {
[0, 0.5, 1, 2, 3, 4, 5].forEach((d) => {
// Special case to avoid "in a few seconds"
if (d === 0) {
earliestOptions[0] = t('label.immediately');
return;
}
earliestOptions[d * 60 * 24] = dj.duration(d, 'days').humanize();
});
const farthestOptions = {};
Expand All @@ -471,7 +476,8 @@ const farthestOptions = {};
});

// humanize selected durations
const earliest = computed(() => dj.duration(scheduleInput.value.earliest_booking, 'minutes').humanize());
const earliest = computed(() => (parseInt(scheduleInput.value.earliest_booking, 10) === 0
? t('label.immediately') : dj.duration(scheduleInput.value.earliest_booking, 'minutes').humanize()));
const farthest = computed(() => dj.duration(scheduleInput.value.farthest_booking, 'minutes').humanize());

// show confirmation dialog
Expand Down
1 change: 1 addition & 0 deletions frontend/src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
"goBack": "Zurück",
"google": "Google",
"guest": "{count} Gäste | {count} Gast | {count} Gäste",
"immediately": "Sofort",
"inPerson": "Vor Ort",
"language": "Sprache",
"legal": "Impressum",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
"goBack": "Go Back",
"google": "Google",
"guest": "{count} guests | {count} guest | {count} guests",
"immediately": "Immediately",
"inPerson": "In person",
"language": "Choose language",
"legal": "Legal",
Expand Down