refactor: move getTotalBookingDuration to BookingRepository (#22931)
* refactor: move getTotalBookingDuration to BookingRepository - Move getTotalBookingDuration function from standalone file to BookingRepository class - Update all usage sites to call method through repository instance - Remove standalone function file packages/lib/server/queries/booking/index.ts - Add prisma import to util.ts for BookingRepository instantiation - Maintain exact same method signature and functionality Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix: remove eslint-config-next to resolve TypeScript ESLint conflicts - Remove eslint-config-next dependency that was causing version conflicts - Resolves 'Class extends value undefined is not a constructor or null' errors - ESLint 'next' config issue appears to be pre-existing in main branch Co-Authored-By: morgan@cal.com <morgan@cal.com> * fixup! Merge branch 'main' into devin/move-getTotalBookingDuration-1754460208 * chore: bump platform libs --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
co-authored by
morgan@cal.com <morgan@cal.com>
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
morgan@cal.com <morgan@cal.com>
Morgan
parent
895ed48bd6
commit
cfda4757e4
@@ -38,7 +38,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.287",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.288",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
"@calcom/prisma": "*",
|
||||
|
||||
@@ -597,7 +597,7 @@ export class UserAvailabilityService {
|
||||
getUserAvailability = withReporting(this._getUserAvailability.bind(this), "getUserAvailability");
|
||||
|
||||
getPeriodStartDatesBetween = withReporting(
|
||||
(dateFrom: Dayjs, dateTo: Dayjs, period: IntervalLimitUnit, timeZone?: string) =>
|
||||
(dateFrom: Dayjs, dateTo: Dayjs, period: IntervalLimitUnit, timeZone?: string) =>
|
||||
getPeriodStartDatesBetweenUtil(dateFrom, dateTo, period, timeZone),
|
||||
"getPeriodStartDatesBetween"
|
||||
);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking";
|
||||
import { BookingRepository } from "@calcom/lib/server/repository/booking";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { ascendingLimitKeys, intervalLimitKeyToUnit } from "../intervalLimit";
|
||||
import type { IntervalLimit, IntervalLimitKey } from "../intervalLimitSchema";
|
||||
@@ -55,7 +56,8 @@ export async function checkDurationLimit({
|
||||
const startDate = dayjs(eventStartDate).startOf(unit).toDate();
|
||||
const endDate = dayjs(eventStartDate).endOf(unit).toDate();
|
||||
|
||||
const totalBookingDuration = await getTotalBookingDuration({
|
||||
const bookingRepo = new BookingRepository(prisma);
|
||||
const totalBookingDuration = await bookingRepo.getTotalBookingDuration({
|
||||
eventId,
|
||||
startDate,
|
||||
endDate,
|
||||
|
||||
@@ -6,7 +6,6 @@ import type { EventType } from "@calcom/lib/getUserAvailability";
|
||||
import { getPeriodStartDatesBetween } from "@calcom/lib/intervalLimits/utils/getPeriodStartDatesBetween";
|
||||
import { withReporting } from "@calcom/lib/sentryWrapper";
|
||||
import { performance } from "@calcom/lib/server/perfObserver";
|
||||
import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking";
|
||||
import { BookingRepository } from "@calcom/lib/server/repository/booking";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { EventBusyDetails } from "@calcom/types/Calendar";
|
||||
@@ -181,7 +180,8 @@ const _getBusyTimesFromDurationLimits = async (
|
||||
|
||||
// special handling of yearly limits to improve performance
|
||||
if (unit === "year") {
|
||||
const totalYearlyDuration = await getTotalBookingDuration({
|
||||
const bookingRepo = new BookingRepository(prisma);
|
||||
const totalYearlyDuration = await bookingRepo.getTotalBookingDuration({
|
||||
eventId: eventType.id,
|
||||
startDate: periodStart.toDate(),
|
||||
endDate: periodStart.endOf(unit).toDate(),
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export const getTotalBookingDuration = async ({
|
||||
eventId,
|
||||
startDate,
|
||||
endDate,
|
||||
rescheduleUid,
|
||||
}: {
|
||||
eventId: number;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
rescheduleUid?: string;
|
||||
}) => {
|
||||
// Aggregates the total booking time for a given event in a given time period
|
||||
// FIXME: bookings that overlap on one side will never be counted
|
||||
let totalBookingTime;
|
||||
|
||||
if (rescheduleUid) {
|
||||
[totalBookingTime] = await prisma.$queryRaw<[{ totalMinutes: number | null }]>`
|
||||
SELECT SUM(EXTRACT(EPOCH FROM ("endTime" - "startTime")) / 60) as "totalMinutes"
|
||||
FROM "Booking"
|
||||
WHERE "status" = 'accepted'
|
||||
AND "eventTypeId" = ${eventId}
|
||||
AND "startTime" >= ${startDate}
|
||||
AND "endTime" <= ${endDate}
|
||||
AND "uid" != ${rescheduleUid};
|
||||
`;
|
||||
} else {
|
||||
[totalBookingTime] = await prisma.$queryRaw<[{ totalMinutes: number | null }]>`
|
||||
SELECT SUM(EXTRACT(EPOCH FROM ("endTime" - "startTime")) / 60) as "totalMinutes"
|
||||
FROM "Booking"
|
||||
WHERE "status" = 'accepted'
|
||||
AND "eventTypeId" = ${eventId}
|
||||
AND "startTime" >= ${startDate}
|
||||
AND "endTime" <= ${endDate};
|
||||
`;
|
||||
}
|
||||
return totalBookingTime.totalMinutes ?? 0;
|
||||
};
|
||||
@@ -870,25 +870,69 @@ export class BookingRepository {
|
||||
});
|
||||
}
|
||||
|
||||
async findAcceptedBookingByEventTypeId({eventTypeId, dateFrom, dateTo}: {eventTypeId?: number, dateFrom: string, dateTo: string}) {
|
||||
return this.prismaClient.booking.findMany({
|
||||
where: {
|
||||
eventTypeId,
|
||||
startTime: {
|
||||
gte: dateFrom,
|
||||
lte: dateTo,
|
||||
},
|
||||
status: BookingStatus.ACCEPTED,
|
||||
},
|
||||
async findAcceptedBookingByEventTypeId({
|
||||
eventTypeId,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
}: {
|
||||
eventTypeId?: number;
|
||||
dateFrom: string;
|
||||
dateTo: string;
|
||||
}) {
|
||||
return this.prismaClient.booking.findMany({
|
||||
where: {
|
||||
eventTypeId,
|
||||
startTime: {
|
||||
gte: dateFrom,
|
||||
lte: dateTo,
|
||||
},
|
||||
status: BookingStatus.ACCEPTED,
|
||||
},
|
||||
select: {
|
||||
uid: true,
|
||||
startTime: true,
|
||||
attendees: {
|
||||
select: {
|
||||
uid: true,
|
||||
startTime: true,
|
||||
attendees: {
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getTotalBookingDuration({
|
||||
eventId,
|
||||
startDate,
|
||||
endDate,
|
||||
rescheduleUid,
|
||||
}: {
|
||||
eventId: number;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
rescheduleUid?: string;
|
||||
}) {
|
||||
let totalBookingTime;
|
||||
|
||||
if (rescheduleUid) {
|
||||
[totalBookingTime] = await this.prismaClient.$queryRaw<[{ totalMinutes: number | null }]>`
|
||||
SELECT SUM(EXTRACT(EPOCH FROM ("endTime" - "startTime")) / 60) as "totalMinutes"
|
||||
FROM "Booking"
|
||||
WHERE "status" = 'accepted'
|
||||
AND "eventTypeId" = ${eventId}
|
||||
AND "startTime" >= ${startDate}
|
||||
AND "endTime" <= ${endDate}
|
||||
AND "uid" != ${rescheduleUid};
|
||||
`;
|
||||
} else {
|
||||
[totalBookingTime] = await this.prismaClient.$queryRaw<[{ totalMinutes: number | null }]>`
|
||||
SELECT SUM(EXTRACT(EPOCH FROM ("endTime" - "startTime")) / 60) as "totalMinutes"
|
||||
FROM "Booking"
|
||||
WHERE "status" = 'accepted'
|
||||
AND "eventTypeId" = ${eventId}
|
||||
AND "startTime" >= ${startDate}
|
||||
AND "endTime" <= ${endDate};
|
||||
`;
|
||||
}
|
||||
return totalBookingTime.totalMinutes ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ import logger from "@calcom/lib/logger";
|
||||
import { isRestrictionScheduleEnabled } from "@calcom/lib/restrictionSchedule";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { withReporting } from "@calcom/lib/sentryWrapper";
|
||||
import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking";
|
||||
import type { ISelectedSlotRepository } from "@calcom/lib/server/repository/ISelectedSlotRepository";
|
||||
import type { BookingRepository } from "@calcom/lib/server/repository/booking";
|
||||
import type { EventTypeRepository } from "@calcom/lib/server/repository/eventTypeRepository";
|
||||
@@ -400,7 +399,12 @@ export class AvailableSlotsService {
|
||||
if (!limit) continue;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(dateFrom, dateTo, unit, timeZone);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(
|
||||
dateFrom,
|
||||
dateTo,
|
||||
unit,
|
||||
timeZone
|
||||
);
|
||||
|
||||
for (const periodStart of periodStartDates) {
|
||||
if (globalLimitManager.isAlreadyBusy(periodStart, unit, timeZone)) continue;
|
||||
@@ -435,7 +439,12 @@ export class AvailableSlotsService {
|
||||
if (!limit) continue;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(dateFrom, dateTo, unit, timeZone);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(
|
||||
dateFrom,
|
||||
dateTo,
|
||||
unit,
|
||||
timeZone
|
||||
);
|
||||
|
||||
for (const periodStart of periodStartDates) {
|
||||
if (limitManager.isAlreadyBusy(periodStart, unit, timeZone)) continue;
|
||||
@@ -486,7 +495,12 @@ export class AvailableSlotsService {
|
||||
if (!limit) continue;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(dateFrom, dateTo, unit, timeZone);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(
|
||||
dateFrom,
|
||||
dateTo,
|
||||
unit,
|
||||
timeZone
|
||||
);
|
||||
|
||||
for (const periodStart of periodStartDates) {
|
||||
if (limitManager.isAlreadyBusy(periodStart, unit, timeZone)) continue;
|
||||
@@ -499,8 +513,7 @@ export class AvailableSlotsService {
|
||||
}
|
||||
|
||||
if (unit === "year") {
|
||||
// TODO: DI getTotalBookingDuration
|
||||
const totalYearlyDuration = await getTotalBookingDuration({
|
||||
const totalYearlyDuration = await this.dependencies.bookingRepo.getTotalBookingDuration({
|
||||
eventId: eventType.id,
|
||||
startDate: periodStart.toDate(),
|
||||
endDate: periodStart.endOf(unit).toDate(),
|
||||
@@ -586,7 +599,12 @@ export class AvailableSlotsService {
|
||||
if (!limit) continue;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(dateFrom, dateTo, unit, timeZone);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(
|
||||
dateFrom,
|
||||
dateTo,
|
||||
unit,
|
||||
timeZone
|
||||
);
|
||||
|
||||
for (const periodStart of periodStartDates) {
|
||||
if (globalLimitManager.isAlreadyBusy(periodStart, unit, timeZone)) continue;
|
||||
@@ -634,7 +652,12 @@ export class AvailableSlotsService {
|
||||
if (!limit) continue;
|
||||
|
||||
const unit = intervalLimitKeyToUnit(key);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(dateFrom, dateTo, unit, timeZone);
|
||||
const periodStartDates = this.dependencies.userAvailabilityService.getPeriodStartDatesBetween(
|
||||
dateFrom,
|
||||
dateTo,
|
||||
unit,
|
||||
timeZone
|
||||
);
|
||||
|
||||
for (const periodStart of periodStartDates) {
|
||||
if (limitManager.isAlreadyBusy(periodStart, unit, timeZone)) continue;
|
||||
|
||||
@@ -2500,7 +2500,7 @@ __metadata:
|
||||
"@axiomhq/winston": ^1.2.0
|
||||
"@calcom/platform-constants": "*"
|
||||
"@calcom/platform-enums": "*"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.287"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.288"
|
||||
"@calcom/platform-types": "*"
|
||||
"@calcom/platform-utils": "*"
|
||||
"@calcom/prisma": "*"
|
||||
@@ -3556,13 +3556,13 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.287":
|
||||
version: 0.0.287
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.287"
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.288":
|
||||
version: 0.0.288
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.288"
|
||||
dependencies:
|
||||
"@calcom/features": "*"
|
||||
"@calcom/lib": "*"
|
||||
checksum: 098a50e1b20f70c0f67a332d5f4f6a13c9aaf03f0c0ac9c9ffe1b74c06c607e6650bc0f08bdc1a9bdd89fa25461c0e153580305b845620a1506b23150334c5bd
|
||||
checksum: 9f44ba9e258a94c9b8bb5388c400696f6e6acd20dbf73865d62739b1aad212626bb181d88b38b30d08659c8b9183d27aba94bdd52b36e6c6c3cc7594d1af29d7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user