mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
9f0d035a3b
* fix: pass seatUid when rescheduling seated booking from booking limit error Co-Authored-By: [email protected] <[email protected]> * test: add test case for seatUid in booking limit reschedule error for seated events Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
136 lines
3.4 KiB
TypeScript
136 lines
3.4 KiB
TypeScript
import { ErrorCode } from "@calcom/lib/errorCodes";
|
|
import { ErrorWithCode } from "@calcom/lib/errors";
|
|
import logger from "@calcom/lib/logger";
|
|
import prisma from "@calcom/prisma";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
|
|
const log = logger.getSubLogger({ prefix: ["[checkActiveBookingsLimitForBooker]"] });
|
|
|
|
export const checkActiveBookingsLimitForBooker = async ({
|
|
eventTypeId,
|
|
maxActiveBookingsPerBooker,
|
|
bookerEmail,
|
|
offerToRescheduleLastBooking,
|
|
}: {
|
|
eventTypeId: number;
|
|
maxActiveBookingsPerBooker: number | null;
|
|
bookerEmail: string;
|
|
offerToRescheduleLastBooking: boolean;
|
|
}) => {
|
|
if (!maxActiveBookingsPerBooker) {
|
|
return;
|
|
}
|
|
|
|
if (offerToRescheduleLastBooking) {
|
|
await checkActiveBookingsLimitAndOfferReschedule({
|
|
eventTypeId,
|
|
maxActiveBookingsPerBooker,
|
|
bookerEmail,
|
|
});
|
|
} else {
|
|
await checkActiveBookingsLimit({ eventTypeId, maxActiveBookingsPerBooker, bookerEmail });
|
|
}
|
|
};
|
|
|
|
/** If we don't need the last record then we should just use COUNT */
|
|
const checkActiveBookingsLimit = async ({
|
|
eventTypeId,
|
|
maxActiveBookingsPerBooker,
|
|
bookerEmail,
|
|
}: {
|
|
eventTypeId: number;
|
|
maxActiveBookingsPerBooker: number;
|
|
bookerEmail: string;
|
|
}) => {
|
|
const bookingsCount = await prisma.booking.count({
|
|
where: {
|
|
eventTypeId,
|
|
startTime: {
|
|
gte: new Date(),
|
|
},
|
|
status: {
|
|
in: [BookingStatus.ACCEPTED],
|
|
},
|
|
attendees: {
|
|
some: {
|
|
email: bookerEmail,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (bookingsCount >= maxActiveBookingsPerBooker) {
|
|
log.warn(`Maximum booking limit reached for ${bookerEmail} for event type ${eventTypeId}`);
|
|
throw new ErrorWithCode(ErrorCode.BookerLimitExceeded, ErrorCode.BookerLimitExceeded, {
|
|
count: maxActiveBookingsPerBooker,
|
|
});
|
|
}
|
|
};
|
|
|
|
const checkActiveBookingsLimitAndOfferReschedule = async ({
|
|
eventTypeId,
|
|
maxActiveBookingsPerBooker,
|
|
bookerEmail,
|
|
}: {
|
|
eventTypeId: number;
|
|
maxActiveBookingsPerBooker: number;
|
|
bookerEmail: string;
|
|
}) => {
|
|
const bookingsCount = await prisma.booking.findMany({
|
|
where: {
|
|
eventTypeId,
|
|
startTime: {
|
|
gte: new Date(),
|
|
},
|
|
status: {
|
|
in: [BookingStatus.ACCEPTED],
|
|
},
|
|
attendees: {
|
|
some: {
|
|
email: bookerEmail,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
startTime: "desc",
|
|
},
|
|
take: maxActiveBookingsPerBooker,
|
|
select: {
|
|
uid: true,
|
|
startTime: true,
|
|
attendees: {
|
|
select: {
|
|
name: true,
|
|
email: true,
|
|
bookingSeat: {
|
|
select: {
|
|
referenceUid: true,
|
|
},
|
|
},
|
|
},
|
|
where: {
|
|
email: bookerEmail,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const lastBooking = bookingsCount[bookingsCount.length - 1];
|
|
// Get the seatUid for the booker's seat in this booking (if it's a seated event)
|
|
const seatUid = lastBooking?.attendees[0]?.bookingSeat?.referenceUid;
|
|
|
|
if (bookingsCount.length >= maxActiveBookingsPerBooker) {
|
|
log.warn(`Maximum booking limit reached for ${bookerEmail} for event type ${eventTypeId}`);
|
|
throw new ErrorWithCode(
|
|
ErrorCode.BookerLimitExceededReschedule,
|
|
ErrorCode.BookerLimitExceededReschedule,
|
|
{
|
|
rescheduleUid: lastBooking.uid,
|
|
startTime: lastBooking.startTime,
|
|
attendees: lastBooking.attendees,
|
|
seatUid,
|
|
}
|
|
);
|
|
}
|
|
};
|