68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
|
import { User } from "@prisma/client";
|
||
|
|
||
|
import prisma from "@calcom/prisma";
|
||
|
|
||
|
async function leastRecentlyBookedUser<T extends Pick<User, "id">>({
|
||
|
availableUsers,
|
||
|
eventTypeId,
|
||
|
}: {
|
||
|
availableUsers: T[];
|
||
|
eventTypeId: number;
|
||
|
}) {
|
||
|
const usersWithLastCreated = await prisma?.user.findMany({
|
||
|
where: {
|
||
|
id: {
|
||
|
in: availableUsers.map((user) => user.id),
|
||
|
},
|
||
|
},
|
||
|
select: {
|
||
|
id: true,
|
||
|
bookings: {
|
||
|
select: {
|
||
|
createdAt: true,
|
||
|
},
|
||
|
where: {
|
||
|
eventTypeId,
|
||
|
},
|
||
|
orderBy: {
|
||
|
createdAt: "desc",
|
||
|
},
|
||
|
take: 1,
|
||
|
},
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (!usersWithLastCreated) {
|
||
|
throw new Error("Unable to find users by availableUser ids."); // should never happen.
|
||
|
}
|
||
|
|
||
|
const userIdAndAtCreatedPair = usersWithLastCreated.reduce(
|
||
|
(keyValuePair: { [key: number]: Date }, user) => {
|
||
|
keyValuePair[user.id] = user.bookings[0]?.createdAt;
|
||
|
return keyValuePair;
|
||
|
},
|
||
|
{}
|
||
|
);
|
||
|
|
||
|
const leastRecentlyBookedUser = availableUsers.sort((a, b) => {
|
||
|
return userIdAndAtCreatedPair[a.id] > userIdAndAtCreatedPair[b.id] ? 1 : -1;
|
||
|
})[0];
|
||
|
|
||
|
return leastRecentlyBookedUser;
|
||
|
}
|
||
|
|
||
|
// TODO: Configure distributionAlgorithm from the event type configuration
|
||
|
// TODO: Add 'MAXIMIZE_FAIRNESS' algorithm.
|
||
|
export async function getLuckyUser<T extends Pick<User, "id">>(
|
||
|
distributionAlgorithm: "MAXIMIZE_AVAILABILITY" = "MAXIMIZE_AVAILABILITY",
|
||
|
{ availableUsers, eventTypeId }: { availableUsers: T[]; eventTypeId: number }
|
||
|
) {
|
||
|
if (availableUsers.length === 1) {
|
||
|
return availableUsers[0];
|
||
|
}
|
||
|
switch (distributionAlgorithm) {
|
||
|
case "MAXIMIZE_AVAILABILITY":
|
||
|
return leastRecentlyBookedUser<T>({ availableUsers, eventTypeId });
|
||
|
}
|
||
|
}
|