fix: eventtype null cant be booked error (#18975)
* fix err msg and add more description * improvements * fix cause * add warn logs for when failing to specific limit checks * typefix * safestringify log * improve error * test fix and log min booking notice * adds out of bounds error code * test fix * fix
This commit is contained in:
@@ -83,6 +83,7 @@
|
||||
"payment_not_created_error": "Payment could not be created",
|
||||
"couldnt_charge_card_error": "Could not charge card for Payment",
|
||||
"no_available_users_found_error": "No available users found. Could you try another time slot?",
|
||||
"booking_time_out_of_bounds_error": "The event type cannot be booked at this time. Could you try another time slot?",
|
||||
"request_body_end_time_internal_error": "Internal Error. Request body does not contain end time",
|
||||
"create_calendar_event_error": "Unable to create Calendar event in Organizer's calendar",
|
||||
"update_calendar_event_error": "Unable to update Calendar event.",
|
||||
|
||||
@@ -772,7 +772,9 @@ describe("handleNewBooking", () => {
|
||||
mockCalendarToHaveNoBusySlots("googlecalendar", {});
|
||||
await createBookingScenario(scenarioData);
|
||||
|
||||
await expect(() => handleNewBooking(req)).rejects.toThrowError("book a meeting in the past");
|
||||
await expect(() => handleNewBooking(req)).rejects.toThrowError(
|
||||
"Attempting to book a meeting in the past."
|
||||
);
|
||||
},
|
||||
timeout
|
||||
);
|
||||
@@ -865,7 +867,7 @@ describe("handleNewBooking", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(() => handleNewBooking(req)).rejects.toThrowError("cannot be booked at this time");
|
||||
expect(() => handleNewBooking(req)).rejects.toThrowError("booking_time_out_of_bounds_error");
|
||||
},
|
||||
timeout
|
||||
);
|
||||
|
||||
+5
-11
@@ -1,6 +1,7 @@
|
||||
import type { Logger } from "tslog";
|
||||
|
||||
import { getUTCOffsetByTimezone } from "@calcom/lib/date-fns";
|
||||
import { ErrorCode } from "@calcom/lib/errorCodes";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import isOutOfBounds, { BookingDateInPastError } from "@calcom/lib/isOutOfBounds";
|
||||
import type { EventType } from "@calcom/prisma/client";
|
||||
@@ -15,6 +16,7 @@ type ValidateBookingTimeEventType = Pick<
|
||||
| "minimumBookingNotice"
|
||||
| "eventName"
|
||||
| "id"
|
||||
| "title"
|
||||
>;
|
||||
|
||||
export const validateBookingTimeIsNotOutOfBounds = async <T extends ValidateBookingTimeEventType>(
|
||||
@@ -41,22 +43,14 @@ export const validateBookingTimeIsNotOutOfBounds = async <T extends ValidateBook
|
||||
);
|
||||
} catch (error) {
|
||||
logger.warn({
|
||||
message: "NewBooking: Unable set timeOutOfBounds. Using false. ",
|
||||
message: "NewBooking: Unable to determine timeOutOfBounds status. Defaulting to false.",
|
||||
});
|
||||
|
||||
if (error instanceof BookingDateInPastError) {
|
||||
logger.info(`Booking eventType ${eventType.id} failed`, JSON.stringify({ error }));
|
||||
throw new HttpError({ statusCode: 400, message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
if (timeOutOfBounds) {
|
||||
const error = {
|
||||
errorCode: "BookingTimeOutOfBounds",
|
||||
message: `EventType '${eventType.eventName}' cannot be booked at this time.`,
|
||||
};
|
||||
logger.warn({
|
||||
message: `NewBooking: EventType '${eventType.eventName}' cannot be booked at this time.`,
|
||||
});
|
||||
throw new HttpError({ statusCode: 400, message: error.message });
|
||||
}
|
||||
if (timeOutOfBounds) throw new Error(ErrorCode.BookingTimeOutOfBounds);
|
||||
};
|
||||
|
||||
@@ -16,4 +16,5 @@ export enum ErrorCode {
|
||||
UnableToSubscribeToThePlatform = "unable_to_subscribe_to_the_platform",
|
||||
UpdatingOauthClientError = "updating_oauth_client_error",
|
||||
CreatingOauthClientError = "creating_oauth_client_error",
|
||||
BookingTimeOutOfBounds = "booking_time_out_of_bounds_error",
|
||||
}
|
||||
|
||||
@@ -250,6 +250,15 @@ export function isTimeViolatingFutureLimit({
|
||||
isAfterRollingEndDay,
|
||||
endOfRollingPeriodEndDayInBookerTz: periodLimits.endOfRollingPeriodEndDayInBookerTz.format(),
|
||||
});
|
||||
if (isAfterRollingEndDay)
|
||||
log.warn(
|
||||
"Booking is out of bounds due to rolling period end day.",
|
||||
safeStringify({
|
||||
formattedDate: dateInSystemTz.format(),
|
||||
isAfterRollingEndDay,
|
||||
endOfRollingPeriodEndDayInBookerTz: periodLimits.endOfRollingPeriodEndDayInBookerTz.format(),
|
||||
})
|
||||
);
|
||||
return isAfterRollingEndDay;
|
||||
}
|
||||
|
||||
@@ -263,6 +272,17 @@ export function isTimeViolatingFutureLimit({
|
||||
startOfRangeStartDayInEventTz: periodLimits.startOfRangeStartDayInEventTz.format(),
|
||||
endOfRangeEndDayInEventTz: periodLimits.endOfRangeEndDayInEventTz.format(),
|
||||
});
|
||||
if (isBeforeRangeStart || isAfterRangeEnd)
|
||||
log.warn(
|
||||
"Booking is out of bounds due to range start and end.",
|
||||
safeStringify({
|
||||
formattedDate: dateInSystemTz.format(),
|
||||
isBeforeRangeStart,
|
||||
isAfterRangeEnd,
|
||||
startOfRangeStartDayInEventTz: periodLimits.startOfRangeStartDayInEventTz.format(),
|
||||
endOfRangeEndDayInEventTz: periodLimits.endOfRangeEndDayInEventTz.format(),
|
||||
})
|
||||
);
|
||||
return isBeforeRangeStart || isAfterRangeEnd;
|
||||
}
|
||||
return false;
|
||||
@@ -287,22 +307,37 @@ export default function isOutOfBounds(
|
||||
},
|
||||
minimumBookingNotice?: number
|
||||
) {
|
||||
return (
|
||||
isTimeOutOfBounds({ time, minimumBookingNotice }) ||
|
||||
isTimeViolatingFutureLimit({
|
||||
time,
|
||||
periodLimits: calculatePeriodLimits({
|
||||
periodType,
|
||||
periodDays,
|
||||
periodCountCalendarDays,
|
||||
periodStartDate,
|
||||
periodEndDate,
|
||||
// Temporary till we find a way to provide allDatesWithBookabilityStatus in handleNewBooking without re-computing availability for the booked timeslot
|
||||
allDatesWithBookabilityStatusInBookerTz: null,
|
||||
_skipRollingWindowCheck: true,
|
||||
eventUtcOffset,
|
||||
bookerUtcOffset,
|
||||
}),
|
||||
})
|
||||
);
|
||||
const log = logger.getSubLogger({ prefix: ["isOutOfBounds"] });
|
||||
const isOutOfBoundsByTime = isTimeOutOfBounds({ time, minimumBookingNotice });
|
||||
const periodLimits = calculatePeriodLimits({
|
||||
periodType,
|
||||
periodDays,
|
||||
periodCountCalendarDays,
|
||||
periodStartDate,
|
||||
periodEndDate,
|
||||
allDatesWithBookabilityStatusInBookerTz: null, // Temporary workaround
|
||||
_skipRollingWindowCheck: true,
|
||||
eventUtcOffset,
|
||||
bookerUtcOffset,
|
||||
});
|
||||
|
||||
const isOutOfBoundsByPeriod = isTimeViolatingFutureLimit({
|
||||
time,
|
||||
periodLimits,
|
||||
});
|
||||
|
||||
if (isOutOfBoundsByTime) {
|
||||
log.warn(
|
||||
"Booking is out of bounds due to minimum booking notice.",
|
||||
safeStringify({ minimumBookingNotice })
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isOutOfBoundsByPeriod) {
|
||||
log.warn("Booking is out of bounds due to period restrictions", safeStringify({ periodLimits }));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user