first commit
This commit is contained in:
89
calcom/packages/lib/server/checkBookingLimits.ts
Normal file
89
calcom/packages/lib/server/checkBookingLimits.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { BookingStatus } from "@calcom/prisma/enums";
|
||||
import type { IntervalLimit } from "@calcom/types/Calendar";
|
||||
|
||||
import { getErrorFromUnknown } from "../errors";
|
||||
import { HttpError } from "../http-error";
|
||||
import { ascendingLimitKeys, intervalLimitKeyToUnit } from "../intervalLimit";
|
||||
import { parseBookingLimit } from "../isBookingLimits";
|
||||
|
||||
export async function checkBookingLimits(
|
||||
bookingLimits: IntervalLimit,
|
||||
eventStartDate: Date,
|
||||
eventId: number,
|
||||
rescheduleUid?: string | undefined,
|
||||
timeZone?: string | null
|
||||
) {
|
||||
const parsedBookingLimits = parseBookingLimit(bookingLimits);
|
||||
if (!parsedBookingLimits) return false;
|
||||
|
||||
// not iterating entries to preserve types
|
||||
const limitCalculations = ascendingLimitKeys.map((key) =>
|
||||
checkBookingLimit({
|
||||
key,
|
||||
limitingNumber: parsedBookingLimits[key],
|
||||
eventStartDate,
|
||||
eventId,
|
||||
timeZone,
|
||||
rescheduleUid,
|
||||
})
|
||||
);
|
||||
|
||||
try {
|
||||
return !!(await Promise.all(limitCalculations));
|
||||
} catch (error) {
|
||||
throw new HttpError({ message: getErrorFromUnknown(error).message, statusCode: 401 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function checkBookingLimit({
|
||||
eventStartDate,
|
||||
eventId,
|
||||
key,
|
||||
limitingNumber,
|
||||
rescheduleUid,
|
||||
timeZone,
|
||||
}: {
|
||||
eventStartDate: Date;
|
||||
eventId: number;
|
||||
key: keyof IntervalLimit;
|
||||
limitingNumber: number | undefined;
|
||||
rescheduleUid?: string | undefined;
|
||||
timeZone?: string | null;
|
||||
}) {
|
||||
{
|
||||
const eventDateInOrganizerTz = timeZone ? dayjs(eventStartDate).tz(timeZone) : dayjs(eventStartDate);
|
||||
|
||||
if (!limitingNumber) return;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
|
||||
const startDate = dayjs(eventDateInOrganizerTz).startOf(unit).toDate();
|
||||
const endDate = dayjs(eventDateInOrganizerTz).endOf(unit).toDate();
|
||||
|
||||
const bookingsInPeriod = await prisma.booking.count({
|
||||
where: {
|
||||
status: BookingStatus.ACCEPTED,
|
||||
eventTypeId: eventId,
|
||||
// FIXME: bookings that overlap on one side will never be counted
|
||||
startTime: {
|
||||
gte: startDate,
|
||||
},
|
||||
endTime: {
|
||||
lte: endDate,
|
||||
},
|
||||
uid: {
|
||||
not: rescheduleUid,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (bookingsInPeriod < limitingNumber) return;
|
||||
|
||||
throw new HttpError({
|
||||
message: `booking_limit_reached`,
|
||||
statusCode: 403,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user