refactor: Consolidate date parameter extraction and booking period check logic (#21142)

Co-authored-by: keith@cal.com <keith@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
This commit is contained in:
devin-ai-integration[bot]
2025-05-06 16:33:22 -07:00
committed by GitHub
co-authored by keith@cal.com <keith@cal.com> Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Omar López
parent 58d5f2a17c
commit cfc9f0bfc3
3 changed files with 87 additions and 56 deletions
@@ -12,6 +12,7 @@ import type { EventBusyDetails } from "@calcom/types/Calendar";
import { descendingLimitKeys, intervalLimitKeyToUnit } from "../intervalLimit";
import type { IntervalLimit } from "../intervalLimitSchema";
import LimitManager from "../limitManager";
import { isBookingWithinPeriod } from "../utils";
import { checkBookingLimit } from "./checkBookingLimits";
export const getBusyTimesFromLimits = async (
@@ -64,6 +65,7 @@ const _getBusyTimesFromLimits = async (
duration,
eventType,
limitManager,
timeZone,
rescheduleUid
);
performance.mark("durationLimitsEnd");
@@ -147,7 +149,7 @@ const _getBusyTimesFromBookingLimits = async (params: {
for (const booking of bookings) {
// consider booking part of period independent of end date
if (!dayjs(booking.start).isBetween(periodStart, periodEnd)) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone || "UTC")) {
continue;
}
totalBookings++;
@@ -174,6 +176,7 @@ const _getBusyTimesFromDurationLimits = async (
duration: number | undefined,
eventType: NonNullable<EventType>,
limitManager: LimitManager,
timeZone: string,
rescheduleUid?: string
) => {
for (const key of descendingLimitKeys) {
@@ -215,7 +218,7 @@ const _getBusyTimesFromDurationLimits = async (
for (const booking of bookings) {
// consider booking part of period independent of end date
if (!dayjs(booking.start).isBetween(periodStart, periodEnd)) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone || "UTC")) {
continue;
}
totalDuration += dayjs(booking.end).diff(dayjs(booking.start), "minute");
+74
View File
@@ -0,0 +1,74 @@
import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import type { EventBusyDetails } from "@calcom/types/Calendar";
import type { IntervalLimitUnit } from "./intervalLimitSchema";
/**
* Extracts date parameters from a booking and period
* @param booking The booking to extract date parameters from
* @param periodStart The start of the period
* @param periodEnd The end of the period
* @param timeZone The timezone to use
* @returns Object containing extracted date parameters
*/
export function extractDateParameters(
booking: EventBusyDetails,
periodStart: Dayjs,
periodEnd: Dayjs,
timeZone: string
) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
return {
bookingStart,
bookingDay,
periodStartDay,
periodEndDay,
};
}
/**
* Checks if a booking is within a given period
* @param booking The booking to check
* @param periodStart The start of the period
* @param periodEnd The end of the period
* @param timeZone The timezone to use
* @returns Boolean indicating if the booking is within the period
*/
export function isBookingWithinPeriod(
booking: EventBusyDetails,
periodStart: Dayjs,
periodEnd: Dayjs,
timeZone: string
) {
const { bookingDay, periodStartDay, periodEndDay } = extractDateParameters(
booking,
periodStart,
periodEnd,
timeZone
);
return !(bookingDay < periodStartDay || bookingDay > periodEndDay);
}
/**
* Gets unit from a busy time's start and end dates
* @param start The start date
* @param end The end date
* @returns The appropriate interval limit unit
*/
export function getUnitFromBusyTime(start: Dayjs, end: Dayjs): IntervalLimitUnit {
if (end.diff(start, "year") >= 1) {
return "year";
} else if (end.diff(start, "month") >= 1) {
return "month";
} else if (end.diff(start, "week") >= 1) {
return "week";
} else {
return "day";
}
}
@@ -30,6 +30,7 @@ import { parseBookingLimit } from "@calcom/lib/intervalLimits/isBookingLimits";
import { parseDurationLimit } from "@calcom/lib/intervalLimits/isDurationLimits";
import LimitManager from "@calcom/lib/intervalLimits/limitManager";
import { checkBookingLimit } from "@calcom/lib/intervalLimits/server/checkBookingLimits";
import { isBookingWithinPeriod, getUnitFromBusyTime } from "@calcom/lib/intervalLimits/utils";
import {
calculatePeriodLimits,
isTimeOutOfBounds,
@@ -898,12 +899,7 @@ const getBusyTimesFromLimitsForUsers = async (
let totalBookings = 0;
for (const booking of busyTimesFromLimitsBookings) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
if (bookingDay < periodStartDay || bookingDay > periodEndDay) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone)) {
continue;
}
@@ -924,18 +920,7 @@ const getBusyTimesFromLimitsForUsers = async (
for (const busyTime of globalLimitManager.getBusyTimes()) {
const start = dayjs(busyTime.start);
const end = dayjs(busyTime.end);
let unit: "year" | "month" | "week" | "day";
if (end.diff(start, "year") >= 1) {
unit = "year";
} else if (end.diff(start, "month") >= 1) {
unit = "month";
} else if (end.diff(start, "week") >= 1) {
unit = "week";
} else {
unit = "day";
}
const unit = getUnitFromBusyTime(start, end);
limitManager.addBusyTime(start, unit, timeZone);
}
@@ -978,12 +963,7 @@ const getBusyTimesFromLimitsForUsers = async (
let totalBookings = 0;
for (const booking of userBookings) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
if (bookingDay < periodStartDay || bookingDay > periodEndDay) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone)) {
continue;
}
@@ -1037,12 +1017,7 @@ const getBusyTimesFromLimitsForUsers = async (
let totalDuration = selectedDuration;
for (const booking of userBookings) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
if (bookingDay < periodStartDay || bookingDay > periodEndDay) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone)) {
continue;
}
@@ -1115,12 +1090,7 @@ const getBusyTimesFromTeamLimitsForUsers = async (
let totalBookings = 0;
for (const booking of busyTimes) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
if (bookingDay < periodStartDay || bookingDay > periodEndDay) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone)) {
continue;
}
@@ -1142,18 +1112,7 @@ const getBusyTimesFromTeamLimitsForUsers = async (
for (const busyTime of globalLimitManager.getBusyTimes()) {
const start = dayjs(busyTime.start);
const end = dayjs(busyTime.end);
let unit: "year" | "month" | "week" | "day";
if (end.diff(start, "year") >= 1) {
unit = "year";
} else if (end.diff(start, "month") >= 1) {
unit = "month";
} else if (end.diff(start, "week") >= 1) {
unit = "week";
} else {
unit = "day";
}
const unit = getUnitFromBusyTime(start, end);
limitManager.addBusyTime(start, unit, timeZone);
}
@@ -1209,12 +1168,7 @@ const getBusyTimesFromTeamLimitsForUsers = async (
let totalBookings = 0;
for (const booking of userBusyTimes) {
const bookingStart = dayjs(booking.start).tz(timeZone);
const bookingDay = bookingStart.format("YYYY-MM-DD");
const periodStartDay = periodStart.format("YYYY-MM-DD");
const periodEndDay = periodEnd.format("YYYY-MM-DD");
if (bookingDay < periodStartDay || bookingDay > periodEndDay) {
if (!isBookingWithinPeriod(booking, periodStart, periodEnd, timeZone)) {
continue;
}