2022-10-12 05:29:04 +00:00
|
|
|
import dayjs from "@calcom/dayjs";
|
|
|
|
import prisma from "@calcom/prisma";
|
2023-08-09 22:51:38 +00:00
|
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
2023-03-10 20:00:19 +00:00
|
|
|
import type { IntervalLimit } from "@calcom/types/Calendar";
|
2022-10-12 05:29:04 +00:00
|
|
|
|
2023-08-09 22:51:38 +00:00
|
|
|
import { getErrorFromUnknown } from "../errors";
|
2022-10-12 05:29:04 +00:00
|
|
|
import { HttpError } from "../http-error";
|
2023-08-09 22:51:38 +00:00
|
|
|
import { ascendingLimitKeys, intervalLimitKeyToUnit } from "../intervalLimit";
|
2022-10-12 05:29:04 +00:00
|
|
|
import { parseBookingLimit } from "../isBookingLimits";
|
|
|
|
|
|
|
|
export async function checkBookingLimits(
|
2023-06-06 11:59:57 +00:00
|
|
|
bookingLimits: IntervalLimit,
|
2022-10-12 05:29:04 +00:00
|
|
|
eventStartDate: Date,
|
2023-08-09 22:51:38 +00:00
|
|
|
eventId: number
|
2022-10-12 05:29:04 +00:00
|
|
|
) {
|
|
|
|
const parsedBookingLimits = parseBookingLimit(bookingLimits);
|
2023-08-09 22:51:38 +00:00
|
|
|
if (!parsedBookingLimits) return false;
|
|
|
|
|
|
|
|
// not iterating entries to preserve types
|
|
|
|
const limitCalculations = ascendingLimitKeys.map((key) =>
|
|
|
|
checkBookingLimit({ key, limitingNumber: parsedBookingLimits[key], eventStartDate, eventId })
|
|
|
|
);
|
|
|
|
|
|
|
|
try {
|
|
|
|
return !!(await Promise.all(limitCalculations));
|
|
|
|
} catch (error) {
|
|
|
|
throw new HttpError({ message: getErrorFromUnknown(error).message, statusCode: 401 });
|
2022-10-12 05:29:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-10 20:00:19 +00:00
|
|
|
export async function checkBookingLimit({
|
2022-10-12 05:29:04 +00:00
|
|
|
eventStartDate,
|
|
|
|
eventId,
|
|
|
|
key,
|
|
|
|
limitingNumber,
|
|
|
|
}: {
|
|
|
|
eventStartDate: Date;
|
|
|
|
eventId: number;
|
2023-08-09 22:51:38 +00:00
|
|
|
key: keyof IntervalLimit;
|
|
|
|
limitingNumber: number | undefined;
|
2022-10-12 05:29:04 +00:00
|
|
|
}) {
|
|
|
|
{
|
2023-08-09 22:51:38 +00:00
|
|
|
if (!limitingNumber) return;
|
|
|
|
|
|
|
|
const unit = intervalLimitKeyToUnit(key);
|
2022-10-12 05:29:04 +00:00
|
|
|
|
2023-08-09 22:51:38 +00:00
|
|
|
const startDate = dayjs(eventStartDate).startOf(unit).toDate();
|
|
|
|
const endDate = dayjs(eventStartDate).endOf(unit).toDate();
|
2022-10-12 05:29:04 +00:00
|
|
|
|
|
|
|
const bookingsInPeriod = await prisma.booking.count({
|
|
|
|
where: {
|
2023-08-09 22:51:38 +00:00
|
|
|
status: BookingStatus.ACCEPTED,
|
|
|
|
eventTypeId: eventId,
|
|
|
|
// FIXME: bookings that overlap on one side will never be counted
|
|
|
|
startTime: {
|
|
|
|
gte: startDate,
|
|
|
|
},
|
|
|
|
endTime: {
|
|
|
|
lte: endDate,
|
2022-10-12 05:29:04 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2023-08-09 22:51:38 +00:00
|
|
|
if (bookingsInPeriod < limitingNumber) return;
|
|
|
|
|
|
|
|
throw new HttpError({
|
|
|
|
message: `booking_limit_reached`,
|
|
|
|
statusCode: 403,
|
|
|
|
});
|
2022-10-12 05:29:04 +00:00
|
|
|
}
|
|
|
|
}
|