* WIP * add frontend * backend to update weight * UI improvements * WIP weight algorithm * enable weights switch + algorithm improvements * fix weightDescription * clean up code * remove OOOEntryHost from schema.prisma * implement logic (not yet tested) * add tests for weight algorithm * add test with weight adjustment * finish unit tests * fix type error * fix type error * add migration * fix type error * fix event type update handler * fix failing test * UI fixes for saving hosts * make sure weightAdjustment is not lost on host changes * fix weightadjustment for new hosts * add weightAdjustment to availableUsers * fix type errors * fix default value for weight * make weight and weightAdjustment optional * fix type errors from schema changes * type fix * clean up code * improve comments * remove comment * clean up code * add tests & weight adjustment improvments * better variable naming * fixes for weight adjustments * make weightAdjustments proportional to weights * fix previous host weight adjustments * improved tests for weight adjustments * save weight and priority + sort hosts correctly * fix type error * code clean up * remove console.log * use BookingRepository to fetch bookings of users * use BookingRepository to fetch bookings in getLuckyUser * fix type errors * fix weightAdjustment if changed from fixed to rr host * disable weights when 'assign all' is enabled * typo * allow 0 weight * set min (and max) for weight and priority * use useWatch * code clean up * fix type error * only count accepted bookings for RR * fix type error * improve data fetching of bookings * only filter bookings of availableUsers * code clean up form feedback * fix tests * don't count no show bookings * code clean up * choose user with highest weight * use one reduce instead of two * use reduce instead of filter and map * don't show weights toggle when 'assign all' is enabled * design fixes * fix type errors * fix: type check * Update packages/features/eventtypes/components/AddMembersWithSwitch.tsx --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
160 lines
3.6 KiB
TypeScript
160 lines
3.6 KiB
TypeScript
import type { Prisma } from "@prisma/client";
|
|
|
|
import prisma from "@calcom/prisma";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
|
|
import { UserRepository } from "./user";
|
|
|
|
export class BookingRepository {
|
|
static async getBookingAttendees(bookingId: number) {
|
|
return await prisma.attendee.findMany({
|
|
where: {
|
|
bookingId,
|
|
},
|
|
});
|
|
}
|
|
|
|
/** Determines if the user is the organizer, team admin, or org admin that the booking was created under */
|
|
static async doesUserIdHaveAccessToBooking({ userId, bookingId }: { userId: number; bookingId: number }) {
|
|
const booking = await prisma.booking.findFirst({
|
|
where: {
|
|
id: bookingId,
|
|
},
|
|
select: {
|
|
userId: true,
|
|
eventType: {
|
|
select: {
|
|
teamId: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!booking) return false;
|
|
|
|
if (userId === booking.userId) return true;
|
|
|
|
// If the booking doesn't belong to the user and there's no team then return early
|
|
if (!booking.eventType || !booking.eventType.teamId) return false;
|
|
|
|
// TODO add checks for team and org
|
|
const isAdminOrUser = await UserRepository.isAdminOfTeamOrParentOrg({
|
|
userId,
|
|
teamId: booking.eventType.teamId,
|
|
});
|
|
|
|
return isAdminOrUser;
|
|
}
|
|
|
|
static async findFirstBookingByReschedule({ originalBookingUid }: { originalBookingUid: string }) {
|
|
return await prisma.booking.findFirst({
|
|
where: {
|
|
fromReschedule: originalBookingUid,
|
|
},
|
|
select: {
|
|
uid: true,
|
|
},
|
|
});
|
|
}
|
|
|
|
static async getAllBookingsForRoundRobin({
|
|
users,
|
|
eventTypeId,
|
|
}: {
|
|
users: { id: number; email: string }[];
|
|
eventTypeId: number;
|
|
}) {
|
|
const whereClause: Prisma.BookingWhereInput = {
|
|
OR: [
|
|
{
|
|
user: {
|
|
id: {
|
|
in: users.map((user) => user.id),
|
|
},
|
|
},
|
|
OR: [
|
|
{
|
|
noShowHost: false,
|
|
},
|
|
{
|
|
noShowHost: null,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
attendees: {
|
|
some: {
|
|
email: {
|
|
in: users.map((user) => user.email),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
attendees: { some: { noShow: false } },
|
|
status: BookingStatus.ACCEPTED,
|
|
eventTypeId,
|
|
};
|
|
|
|
const allBookings = await prisma.booking.findMany({
|
|
where: whereClause,
|
|
select: {
|
|
id: true,
|
|
attendees: true,
|
|
userId: true,
|
|
createdAt: true,
|
|
status: true,
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
});
|
|
|
|
return allBookings;
|
|
}
|
|
|
|
static async findBookingByUidAndUserId({ bookingUid, userId }: { bookingUid: string; userId: number }) {
|
|
return await prisma.booking.findFirst({
|
|
where: {
|
|
uid: bookingUid,
|
|
OR: [
|
|
{ userId: userId },
|
|
{
|
|
eventType: {
|
|
hosts: {
|
|
some: {
|
|
userId,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
eventType: {
|
|
users: {
|
|
some: {
|
|
id: userId,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
eventType: {
|
|
team: {
|
|
members: {
|
|
some: {
|
|
userId,
|
|
accepted: true,
|
|
role: {
|
|
in: ["ADMIN", "OWNER"],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
}
|
|
}
|