Files
calendar/packages/lib/bookings/getAllUserBookings.ts
T
0eabe7f28b refactor: v2 bookings (#16200)
* chore: version existing bookings as 2024-04-15

* feat: initialize bookings version 2024-08-13

* feat: Create and reschedule booking inputs logic

* feat: create booking

* refactor: create booking response

* feat: reschedule booking

* chore: update language input

* feat: recurring booking

* refactor: add booking status in response

* refactor: recurring bookings

* feat: get booking by uid

* wip: get event types

* feat: fetch by multiple status filters and sort

* feat: fetch by teamId, teamIds, eventTypeId, eventTypeIds

* wip: filter by attendee email

* feat: filter by attendee email

* feat: filter by attendee name

* feat: date range filter

* chore: format get bookings output

* chore: finish main merge

* feat: handle instant bookings

* refactor: separate reschedule endpoint

* feat: cancel endpoint

* feat: mark absent host or attendees

* chore: dont expose metadata for now

* chore: add hostId to response

* fix: metadata

* feat: bill bookings

* feat: cancellationReason

* feat: rescheduling reason

* handle already busy booking error

* test: create new booking

* fix: handleNewRecurringBooking ignoring noEmail

* test: recurring bookings

* test: get individual bookings

* fix: cancel email sent if arePlatformEmailsEnabled=false but platformClientId is undefined

* tests: cancel, reschedule, mark absent

* fix: generateIcsFile null pointer exception

* cancel test

* error msg improve

* tests: team event type creation and teamId, teamIds filters

* test: cancel recurring booking

* refactor: make hosts and attendees an array

* sort by asc start

* simplify

* refactor: absent

* fix: make work with api key

* test

* ts remove any

* feat: BookingUidGuard

* fix: recurring booking no email

* fix: legacy bookings recurring noEmail

* add swagger

* retrigger build

* fix: atom booker work with v2

* docs: exclude old controller from docs

* refactor: make eventTypeIds and teamIds getBookings query params comma separated string

* docs: swagger for get bookings query

* swagger docs

* swagger docs

* docs: document authorization header

* refactor: remove unused attendee variable

* refactor: remove unused check

* refactor: remove unused attendee variable

* refactor: spelling

* use published platform libraries

* fix: ci

* fix: ci

* fix: ci

* fix: ci

* cleanup script platform types

* fix: use libraries from npm

* chore: set test env vapid keys

* fix: event type tests

* fix: remove location from system fields

* fix legacy event types

* Revert "fix legacy event types"

This reverts commit e64b473b73f7ef0fe88942cd87277d29a512b946.

* Revert "fix: remove location from system fields"

This reverts commit bee9a15cb27cd34705f34c427b6b50d51e3b7ee7.

* Revert "fix: event type tests"

This reverts commit fab1cb0f5eeb65e4f542bfbeb83849ceed7ba428.

* update libraries

* fix: increase node space for ci runner

* fix: increase node space for ci runner

* fix: increase node space for ci runner

* readd swagger

* ci

* ci

* refactor: increase idle worker memory jest e2e

* fixup! refactor: increase idle worker memory jest e2e

* fixup! fixup! refactor: increase idle worker memory jest e2e

* refactor: split bookings e2e into smaller e2e files

* fixup! refactor: split bookings e2e into smaller e2e files

* fixup! fixup! refactor: split bookings e2e into smaller e2e files

* fixup! fixup! fixup! refactor: split bookings e2e into smaller e2e files

* fixup! Merge branch 'main' into v2-refactor-bookings

* revert event types service

* fix: remove resetModule, maxWorker 2 jest e2e config

---------

Co-authored-by: Morgan Vernay <morgan@cal.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2024-09-23 16:19:25 +03:00

135 lines
3.7 KiB
TypeScript

import type { PrismaClient } from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
import { BookingStatus } from "@calcom/prisma/enums";
import { getBookings } from "@calcom/trpc/server/routers/viewer/bookings/get.handler";
type InputByStatus = "upcoming" | "recurring" | "past" | "cancelled" | "unconfirmed";
type SortOptions = {
sortStart?: "asc" | "desc";
sortEnd?: "asc" | "desc";
sortCreated?: "asc" | "desc";
};
type GetOptions = {
ctx: {
user: { id: number; email: string };
prisma: PrismaClient;
};
bookingListingByStatus: InputByStatus[];
take: number;
skip: number;
filters: {
status?: InputByStatus;
teamIds?: number[] | undefined;
userIds?: number[] | undefined;
eventTypeIds?: number[] | undefined;
attendeeEmail?: string;
attendeeName?: string;
};
sort?: SortOptions;
};
const getAllUserBookings = async ({ ctx, filters, bookingListingByStatus, take, skip, sort }: GetOptions) => {
const { prisma, user } = ctx;
const bookingListingFilters: Record<InputByStatus, Prisma.BookingWhereInput> = {
upcoming: {
endTime: { gte: new Date() },
// These changes are needed to not show confirmed recurring events,
// as rescheduling or cancel for recurring event bookings should be
// handled separately for each occurrence
OR: [
{
recurringEventId: { not: null },
status: { equals: BookingStatus.ACCEPTED },
},
{
recurringEventId: { equals: null },
status: { notIn: [BookingStatus.CANCELLED, BookingStatus.REJECTED] },
},
],
},
recurring: {
endTime: { gte: new Date() },
AND: [
{ NOT: { recurringEventId: { equals: null } } },
{ status: { notIn: [BookingStatus.CANCELLED, BookingStatus.REJECTED] } },
],
},
past: {
endTime: { lte: new Date() },
AND: [
{ NOT: { status: { equals: BookingStatus.CANCELLED } } },
{ NOT: { status: { equals: BookingStatus.REJECTED } } },
],
},
cancelled: {
OR: [{ status: { equals: BookingStatus.CANCELLED } }, { status: { equals: BookingStatus.REJECTED } }],
},
unconfirmed: {
endTime: { gte: new Date() },
status: { equals: BookingStatus.PENDING },
},
};
const orderBy = getOrderBy(bookingListingByStatus, sort);
const combinedFilters = bookingListingByStatus.map((status) => bookingListingFilters[status]);
const { bookings, recurringInfo } = await getBookings({
user,
prisma,
passedBookingsStatusFilter: {
OR: combinedFilters,
},
filters: filters,
orderBy,
take,
skip,
});
const bookingsFetched = bookings.length;
let nextCursor: typeof skip | null = skip;
if (bookingsFetched > take) {
nextCursor += bookingsFetched;
} else {
nextCursor = null;
}
return {
bookings,
recurringInfo,
nextCursor,
};
};
function getOrderBy(
bookingListingByStatus: InputByStatus[],
sort?: SortOptions
): Prisma.BookingOrderByWithAggregationInput {
const bookingListingOrderby: Record<InputByStatus, Prisma.BookingOrderByWithAggregationInput> = {
upcoming: { startTime: "asc" },
recurring: { startTime: "asc" },
past: { startTime: "desc" },
cancelled: { startTime: "desc" },
unconfirmed: { startTime: "asc" },
};
if (bookingListingByStatus?.length === 1 && !sort) {
return bookingListingOrderby[bookingListingByStatus[0]];
}
if (sort?.sortStart) {
return { startTime: sort.sortStart };
}
if (sort?.sortEnd) {
return { endTime: sort.sortEnd };
}
if (sort?.sortCreated) {
return { createdAt: sort.sortCreated };
}
return { startTime: "asc" };
}
export default getAllUserBookings;