-
Notifications
You must be signed in to change notification settings - Fork 3
Date override fixes #1
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
base: main
Are you sure you want to change the base?
Changes from all commits
754e63e
ae94d69
de351dd
dbf4bfa
79dc235
40ae4e5
3140203
d5d798b
b634898
017ed53
ee38fd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -208,11 +208,22 @@ const getSlots = ({ | |
| }); | ||
|
|
||
| if (!!activeOverrides.length) { | ||
| const overrides = activeOverrides.flatMap((override) => ({ | ||
| userIds: override.userId ? [override.userId] : [], | ||
| startTime: override.start.getUTCHours() * 60 + override.start.getUTCMinutes(), | ||
| endTime: override.end.getUTCHours() * 60 + override.end.getUTCMinutes(), | ||
| })); | ||
| const overrides = activeOverrides.flatMap((override) => { | ||
| const organizerUtcOffset = dayjs(override.start.toString()).tz(override.timeZone).utcOffset(); | ||
| const inviteeUtcOffset = dayjs(override.start.toString()).tz(timeZone).utcOffset(); | ||
| const offset = inviteeUtcOffset - organizerUtcOffset; | ||
|
|
||
| return { | ||
| userIds: override.userId ? [override.userId] : [], | ||
| startTime: | ||
| dayjs(override.start).utc().add(offset, "minute").hour() * 60 + | ||
| dayjs(override.start).utc().add(offset, "minute").minute(), | ||
| endTime: | ||
| dayjs(override.end).utc().add(offset, "minute").hour() * 60 + | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 AI 代码审查发现问题 📋 问题概述
📍 问题详情🔴 问题 1 | 严重程度:
|
||
| dayjs(override.end).utc().add(offset, "minute").minute(), | ||
| }; | ||
| }); | ||
|
|
||
| // unset all working hours that relate to this user availability override | ||
| overrides.forEach((override) => { | ||
| let i = -1; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import type prisma from "@calcom/prisma"; | |
| import { availabilityUserSelect } from "@calcom/prisma"; | ||
| import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; | ||
| import type { EventBusyDate } from "@calcom/types/Calendar"; | ||
| import type { WorkingHours } from "@calcom/types/schedule"; | ||
|
|
||
| import { TRPCError } from "@trpc/server"; | ||
|
|
||
|
|
@@ -75,12 +76,21 @@ const checkIfIsAvailable = ({ | |
| time, | ||
| busy, | ||
| eventLength, | ||
| dateOverrides = [], | ||
| workingHours = [], | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 AI 代码审查发现问题 📋 问题概述
📍 问题详情🟡 问题 1 | 严重程度:
|
||
| currentSeats, | ||
| organizerTimeZone, | ||
| }: { | ||
| time: Dayjs; | ||
| busy: EventBusyDate[]; | ||
| eventLength: number; | ||
| dateOverrides?: { | ||
| start: Date; | ||
| end: Date; | ||
| }[]; | ||
| workingHours?: WorkingHours[]; | ||
| currentSeats?: CurrentSeats; | ||
| organizerTimeZone?: string; | ||
| }): boolean => { | ||
| if (currentSeats?.some((booking) => booking.startTime.toISOString() === time.toISOString())) { | ||
| return true; | ||
|
|
@@ -89,6 +99,57 @@ const checkIfIsAvailable = ({ | |
| const slotEndTime = time.add(eventLength, "minutes").utc(); | ||
| const slotStartTime = time.utc(); | ||
|
|
||
| //check if date override for slot exists | ||
| let dateOverrideExist = false; | ||
|
|
||
| if ( | ||
| dateOverrides.find((date) => { | ||
| const utcOffset = organizerTimeZone ? dayjs.tz(date.start, organizerTimeZone).utcOffset() * -1 : 0; | ||
|
|
||
| if ( | ||
| dayjs(date.start).add(utcOffset, "minutes").format("YYYY MM DD") === | ||
| slotStartTime.format("YYYY MM DD") | ||
| ) { | ||
| dateOverrideExist = true; | ||
| if (dayjs(date.start).add(utcOffset, "minutes") === dayjs(date.end).add(utcOffset, "minutes")) { | ||
| return true; | ||
| } | ||
| if ( | ||
| slotEndTime.isBefore(dayjs(date.start).add(utcOffset, "minutes")) || | ||
| slotEndTime.isSame(dayjs(date.start).add(utcOffset, "minutes")) | ||
| ) { | ||
| return true; | ||
| } | ||
| if (slotStartTime.isAfter(dayjs(date.end).add(utcOffset, "minutes"))) { | ||
| return true; | ||
| } | ||
| } | ||
| }) | ||
| ) { | ||
| // slot is not within the date override | ||
| return false; | ||
| } | ||
|
|
||
| if (dateOverrideExist) { | ||
| return true; | ||
| } | ||
|
|
||
| //if no date override for slot exists check if it is within normal work hours | ||
| if ( | ||
| workingHours.find((workingHour) => { | ||
| if (workingHour.days.includes(slotStartTime.day())) { | ||
| const start = slotStartTime.hour() * 60 + slotStartTime.minute(); | ||
| const end = slotStartTime.hour() * 60 + slotStartTime.minute(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 AI 代码审查发现问题 📋 问题概述
📍 问题详情🟡 问题 1 | 严重程度:
|
||
| if (start < workingHour.startTime || end > workingHour.endTime) { | ||
| return true; | ||
| } | ||
| } | ||
| }) | ||
| ) { | ||
| // slot is outside of working hours | ||
| return false; | ||
| } | ||
|
|
||
| return busy.every((busyTime) => { | ||
| const startTime = dayjs.utc(busyTime.start).utc(); | ||
| const endTime = dayjs.utc(busyTime.end); | ||
|
|
@@ -115,7 +176,6 @@ const checkIfIsAvailable = ({ | |
| else if (startTime.isBetween(time, slotEndTime)) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| }); | ||
| }; | ||
|
|
@@ -348,7 +408,11 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
| ); | ||
| // flattens availability of multiple users | ||
| const dateOverrides = userAvailability.flatMap((availability) => | ||
| availability.dateOverrides.map((override) => ({ userId: availability.user.id, ...override })) | ||
| availability.dateOverrides.map((override) => ({ | ||
| userId: availability.user.id, | ||
| timeZone: availability.timeZone, | ||
| ...override, | ||
| })) | ||
| ); | ||
| const workingHours = getAggregateWorkingHours(userAvailability, eventType.schedulingType); | ||
| const availabilityCheckProps = { | ||
|
|
@@ -372,6 +436,9 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
|
|
||
| const timeSlots: ReturnType<typeof getTimeSlots> = []; | ||
|
|
||
| const organizerTimeZone = | ||
| eventType.timeZone || eventType?.schedule?.timeZone || userAvailability?.[0]?.timeZone; | ||
|
|
||
| for ( | ||
| let currentCheckedTime = startTime; | ||
| currentCheckedTime.isBefore(endTime); | ||
|
|
@@ -386,8 +453,7 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
| dateOverrides, | ||
| minimumBookingNotice: eventType.minimumBookingNotice, | ||
| frequency: eventType.slotInterval || input.duration || eventType.length, | ||
| organizerTimeZone: | ||
| eventType.timeZone || eventType?.schedule?.timeZone || userAvailability?.[0]?.timeZone, | ||
| organizerTimeZone, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 AI 代码审查发现问题 📋 问题概述
📍 问题详情🔴 问题 1 | 严重程度:
|
||
| }) | ||
| ); | ||
| } | ||
|
|
@@ -423,13 +489,15 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
| time: slot.time, | ||
| ...schedule, | ||
| ...availabilityCheckProps, | ||
| organizerTimeZone: schedule.timeZone, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 AI 代码审查发现问题 📋 问题概述
📍 问题详情🟡 问题 1 | 严重程度:
|
||
| }); | ||
| const endCheckForAvailability = performance.now(); | ||
| checkForAvailabilityCount++; | ||
| checkForAvailabilityTime += endCheckForAvailability - startCheckForAvailability; | ||
| return isAvailable; | ||
| }); | ||
| }); | ||
|
|
||
| // what else are you going to call it? | ||
| const looseHostAvailability = userAvailability.filter(({ user: { isFixed } }) => !isFixed); | ||
| if (looseHostAvailability.length > 0) { | ||
|
|
@@ -446,6 +514,7 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
| time: slot.time, | ||
| ...userSchedule, | ||
| ...availabilityCheckProps, | ||
| organizerTimeZone: userSchedule.timeZone, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 AI 代码审查发现问题 📋 问题概述
📍 问题详情🟡 问题 1 | 严重程度:
|
||
| }); | ||
| }); | ||
| return slot; | ||
|
|
@@ -507,17 +576,19 @@ export async function getSchedule(input: z.infer<typeof getScheduleSchema>, ctx: | |
| return false; | ||
| } | ||
|
|
||
| const userSchedule = userAvailability.find(({ user: { id: userId } }) => userId === slotUserId); | ||
|
|
||
| return checkIfIsAvailable({ | ||
| time: slot.time, | ||
| busy, | ||
| ...availabilityCheckProps, | ||
| organizerTimeZone: userSchedule?.timeZone, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 AI 代码审查发现问题 📋 问题概述
📍 问题详情🟡 问题 1 | 严重程度:
|
||
| }); | ||
| }); | ||
| return slot; | ||
| }) | ||
| .filter((slot) => !!slot.userIds?.length); | ||
| } | ||
|
|
||
| availableTimeSlots = availableTimeSlots.filter((slot) => isTimeWithinBounds(slot.time)); | ||
|
|
||
| const computedAvailableSlots = availableTimeSlots.reduce( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 AI 代码审查发现问题
📋 问题概述
📍 问题详情
🟡 问题 1 | 严重程度:
MEDIUM| 行号:788💬 详细说明:
📝 问题代码:
💡 修复建议:
✅ 修复示例:
🔗 参考链接
无