fix: buffer times in handleNewBooking (#14871)
* get buffer busy time from bookings outside of start and end time * add test for buffers * fix typo --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com>
This commit is contained in:
co-authored by
CarinaWolli
parent
b8890c841c
commit
304ef29618
@@ -8,6 +8,7 @@ import { Controller, useFormContext } from "react-hook-form";
|
||||
import type { SingleValue } from "react-select";
|
||||
|
||||
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
|
||||
import { getDefinedBufferTimes } from "@calcom/features/eventtypes/lib/getDefinedBufferTimes";
|
||||
import type { FormValues } from "@calcom/features/eventtypes/lib/types";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import type { DurationType } from "@calcom/lib/convertToNewDurationType";
|
||||
@@ -172,7 +173,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
|
||||
label: t("event_buffer_default"),
|
||||
value: 0,
|
||||
},
|
||||
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
|
||||
...getDefinedBufferTimes().map((minutes) => ({
|
||||
label: `${minutes} ${t("minutes")}`,
|
||||
value: minutes,
|
||||
})),
|
||||
|
||||
@@ -14,6 +14,8 @@ import { stringToDayjs } from "@calcom/prisma/zod-utils";
|
||||
import type { EventBusyDetails, IntervalLimit } from "@calcom/types/Calendar";
|
||||
import type { CredentialPayload } from "@calcom/types/Credential";
|
||||
|
||||
import { getDefinedBufferTimes } from "../features/eventtypes/lib/getDefinedBufferTimes";
|
||||
|
||||
export async function getBusyTimes(params: {
|
||||
credentials: CredentialPayload[];
|
||||
userId: number;
|
||||
@@ -85,10 +87,16 @@ export async function getBusyTimes(params: {
|
||||
const endTimeDate =
|
||||
rescheduleUid && duration ? dayjs(endTime).add(duration, "minute").toDate() : new Date(endTime);
|
||||
|
||||
// to also get bookings that are outside of start and end time, but the buffer falls within the start and end time
|
||||
const definedBufferTimes = getDefinedBufferTimes();
|
||||
const maxBuffer = definedBufferTimes[definedBufferTimes.length - 1];
|
||||
const startTimeAdjustedWithMaxBuffer = dayjs(startTimeDate).subtract(maxBuffer, "minute").toDate();
|
||||
const endTimeAdjustedWithMaxBuffer = dayjs(endTimeDate).add(maxBuffer, "minute").toDate();
|
||||
|
||||
// startTime is less than endTimeDate and endTime grater than startTimeDate
|
||||
const sharedQuery = {
|
||||
startTime: { lte: endTimeDate },
|
||||
endTime: { gte: startTimeDate },
|
||||
startTime: { lte: endTimeAdjustedWithMaxBuffer },
|
||||
endTime: { gte: startTimeAdjustedWithMaxBuffer },
|
||||
status: {
|
||||
in: [BookingStatus.ACCEPTED],
|
||||
},
|
||||
|
||||
@@ -462,4 +462,141 @@ describe("handleNewBooking", () => {
|
||||
},
|
||||
timeout
|
||||
);
|
||||
|
||||
describe("Buffers", () => {
|
||||
test(`should throw error when booking is within a before event buffer of an existing booking
|
||||
`, async ({}) => {
|
||||
const handleNewBooking = (await import("@calcom/features/bookings/lib/handleNewBooking")).default;
|
||||
|
||||
const booker = getBooker({
|
||||
email: "booker@example.com",
|
||||
name: "Booker",
|
||||
});
|
||||
|
||||
const organizer = getOrganizer({
|
||||
name: "Organizer",
|
||||
email: "organizer@example.com",
|
||||
id: 101,
|
||||
schedules: [TestData.schedules.IstWorkHours],
|
||||
});
|
||||
|
||||
const { dateString: nextDayDateString } = getDate({ dateIncrement: 1 });
|
||||
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
slotInterval: 15,
|
||||
length: 15,
|
||||
beforeEventBuffer: 60,
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bookings: [
|
||||
{
|
||||
eventTypeId: 1,
|
||||
userId: 101,
|
||||
status: BookingStatus.ACCEPTED,
|
||||
startTime: `${nextDayDateString}T05:00:00.000Z`,
|
||||
endTime: `${nextDayDateString}T05:15:00.000Z`,
|
||||
},
|
||||
],
|
||||
organizer,
|
||||
})
|
||||
);
|
||||
|
||||
const mockBookingData = getMockRequestDataForBooking({
|
||||
data: {
|
||||
start: `${nextDayDateString}T04:30:00.000Z`,
|
||||
end: `${nextDayDateString}T04:45:00.000Z`,
|
||||
eventTypeId: 1,
|
||||
responses: {
|
||||
email: booker.email,
|
||||
name: booker.name,
|
||||
location: { optionValue: "", value: "New York" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { req } = createMockNextJsRequest({
|
||||
method: "POST",
|
||||
body: mockBookingData,
|
||||
});
|
||||
await expect(async () => await handleNewBooking(req)).rejects.toThrowError(
|
||||
"no_available_users_found_error"
|
||||
);
|
||||
});
|
||||
});
|
||||
test(`should throw error when booking is within a after event buffer of an existing booking
|
||||
`, async ({}) => {
|
||||
const handleNewBooking = (await import("@calcom/features/bookings/lib/handleNewBooking")).default;
|
||||
|
||||
const booker = getBooker({
|
||||
email: "booker@example.com",
|
||||
name: "Booker",
|
||||
});
|
||||
|
||||
const organizer = getOrganizer({
|
||||
name: "Organizer",
|
||||
email: "organizer@example.com",
|
||||
id: 101,
|
||||
schedules: [TestData.schedules.IstWorkHours],
|
||||
});
|
||||
|
||||
const { dateString: nextDayDateString } = getDate({ dateIncrement: 1 });
|
||||
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
slotInterval: 15,
|
||||
length: 15,
|
||||
afterEventBuffer: 60,
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bookings: [
|
||||
{
|
||||
eventTypeId: 1,
|
||||
userId: 101,
|
||||
status: BookingStatus.ACCEPTED,
|
||||
startTime: `${nextDayDateString}T05:00:00.000Z`,
|
||||
endTime: `${nextDayDateString}T05:15:00.000Z`,
|
||||
},
|
||||
],
|
||||
organizer,
|
||||
})
|
||||
);
|
||||
|
||||
const mockBookingData = getMockRequestDataForBooking({
|
||||
data: {
|
||||
start: `${nextDayDateString}T05:30:00.000Z`,
|
||||
end: `${nextDayDateString}T05:45:00.000Z`,
|
||||
eventTypeId: 1,
|
||||
responses: {
|
||||
email: booker.email,
|
||||
name: booker.name,
|
||||
location: { optionValue: "", value: "New York" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { req } = createMockNextJsRequest({
|
||||
method: "POST",
|
||||
body: mockBookingData,
|
||||
});
|
||||
await expect(async () => await handleNewBooking(req)).rejects.toThrowError(
|
||||
"no_available_users_found_error"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export const getDefinedBufferTimes = () => {
|
||||
return [5, 10, 15, 20, 30, 45, 60, 90, 120];
|
||||
};
|
||||
Reference in New Issue
Block a user