Files
calendar/packages/lib/server/checkBookingLimits.ts
T
5293db29d9 Feat Booking Limits (#4759)
* Add db relevant stuff

* Basic UI there still buggy

* This UI is hard - some progress

* Fix awful state mangament

* Fix re-ordering

* Working UI logic!

* Partical working minMax function

* Fix min max

* bookingLImits api + tests

* Moved checkBookingLimits to backend only code

* Fix httperror import

* Return busy times

* Remove avaliablity calc

* Working for everything but year

* Remove redundant + fix async forloop

* Add compatible type

* Future proof with evenTypeId filter

* Fix commonjson

* Sorting + validation + tests + passing

* Add empty test

* Move validation check  to backend

* Add bookinglimits in trpc

* Add test for undefined

* Apply suggestions from code review

Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>

* Update apps/web/components/v2/eventtype/EventLimitsTab.tsx

Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>

* Rename value for eligiability

* Rename keyof type

* status code

* Fix toggle not toggling off

* Update apps/web/pages/v2/event-types/[type]/index.tsx

Co-authored-by: Omar López <zomars@me.com>

* Update apps/web/pages/v2/event-types/[type]/index.tsx

Co-authored-by: Omar López <zomars@me.com>

* Change back to undefined as it is working for sean. See if it fails on testapp

* Fixing test builder

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
Co-authored-by: Leo Giovanetti <hello@leog.me>
2022-10-12 05:29:04 +00:00

95 lines
2.5 KiB
TypeScript

import dayjs from "@calcom/dayjs";
import prisma from "@calcom/prisma";
import { BookingLimit } from "@calcom/types/Calendar";
import { HttpError } from "../http-error";
import { parseBookingLimit } from "../isBookingLimits";
export async function checkBookingLimits(
bookingLimits: any,
eventStartDate: Date,
eventId: number,
returnBusyTimes?: boolean
) {
const parsedBookingLimits = parseBookingLimit(bookingLimits);
if (parsedBookingLimits) {
const limitCalculations = Object.entries(parsedBookingLimits).map(
async ([key, limitingNumber]) =>
await checkLimit({ key, limitingNumber, eventStartDate, eventId, returnBusyTimes })
);
await Promise.all(limitCalculations)
.then((res) => {
if (returnBusyTimes) {
return res;
}
})
.catch((error) => {
throw new HttpError({ message: error.message, statusCode: 401 });
});
return true;
}
return false;
}
export async function checkLimit({
eventStartDate,
eventId,
key,
limitingNumber,
returnBusyTimes = false,
}: {
eventStartDate: Date;
eventId: number;
key: string;
limitingNumber: number;
returnBusyTimes?: boolean;
}) {
{
const limitKey = key as keyof BookingLimit;
// Take PER_DAY and turn it into day and PER_WEEK into week etc.
const filter = limitKey.split("_")[1].toLocaleLowerCase() as "day" | "week" | "month" | "year"; // Have to cast here
const startDate = dayjs(eventStartDate).startOf(filter).toDate();
// this is parsed above with parseBookingLimit so we know it's safe.
const endDate = dayjs(startDate).endOf(filter).toDate();
// This allows us to easily add it within dayjs
const bookingsInPeriod = await prisma.booking.count({
where: {
status: "ACCEPTED",
eventType: {
AND: [
{
id: eventId,
bookings: {
some: {
startTime: {
gte: startDate,
},
endTime: {
lte: endDate,
},
},
},
},
],
},
},
});
if (bookingsInPeriod >= limitingNumber) {
// This is used when getting availbility
if (returnBusyTimes) {
return {
start: startDate,
end: endDate,
};
}
throw new HttpError({
message: `Booking limit of ${limitingNumber}/${filter} reached for this eventType`,
statusCode: 403,
});
}
}
}