fix: make cancellation reason mandatory when cancelledBy param is set to host email (#23764)
* fix: make cancelllation Reason mandatory when cancelledBy set as the host * update * tweak * show error message
This commit is contained in:
1 parent
1a8b5d145f
commit
a62c74f79e
3 files changed
+87
-7
No files matched your search
@@ -157,8 +157,11 @@ export default function CancelBooking(props: Props) {
|
||||
|
||||
const cancellationNoShowFeeWarning = autoChargeNoShowFee();
|
||||
|
||||
const isCancellationUserHost =
|
||||
props.isHost || bookingCancelledEventProps.organizer.email === currentUserEmail;
|
||||
|
||||
const hostMissingCancellationReason =
|
||||
props.isHost &&
|
||||
isCancellationUserHost &&
|
||||
(!cancellationReason?.trim() || (props.internalNotePresets.length > 0 && !internalNote?.id));
|
||||
const cancellationNoShowFeeNotAcknowledged =
|
||||
!props.isHost && cancellationNoShowFeeWarning && !acknowledgeCancellationNoShowFee;
|
||||
@@ -211,7 +214,7 @@ export default function CancelBooking(props: Props) {
|
||||
</>
|
||||
)}
|
||||
|
||||
<Label>{props.isHost ? t("cancellation_reason_host") : t("cancellation_reason")}</Label>
|
||||
<Label>{isCancellationUserHost ? t("cancellation_reason_host") : t("cancellation_reason")}</Label>
|
||||
|
||||
<TextArea
|
||||
data-testid="cancel_reason"
|
||||
@@ -222,7 +225,7 @@ export default function CancelBooking(props: Props) {
|
||||
className="mb-4 mt-2 w-full "
|
||||
rows={3}
|
||||
/>
|
||||
{props.isHost ? (
|
||||
{isCancellationUserHost ? (
|
||||
<div className="-mt-2 mb-4 flex items-center gap-2">
|
||||
<Icon name="info" className="text-subtle h-4 w-4" />
|
||||
<p className="text-default text-subtle text-sm leading-none">
|
||||
@@ -296,11 +299,13 @@ export default function CancelBooking(props: Props) {
|
||||
});
|
||||
refreshData();
|
||||
} else {
|
||||
const data = await res.json();
|
||||
setLoading(false);
|
||||
setError(
|
||||
`${t("error_with_status_code_occured", { status: res.status })} ${t(
|
||||
"please_try_again"
|
||||
)}`
|
||||
data.message ||
|
||||
`${t("error_with_status_code_occured", { status: res.status })} ${t(
|
||||
"please_try_again"
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -114,7 +114,10 @@ async function handler(input: CancelBookingInput) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!platformClientId && !cancellationReason?.trim() && bookingToDelete.userId == userId) {
|
||||
const isCancellationUserHost =
|
||||
bookingToDelete.userId == userId || bookingToDelete.user.email === cancelledBy;
|
||||
|
||||
if (!platformClientId && !cancellationReason?.trim() && isCancellationUserHost) {
|
||||
throw new HttpError({
|
||||
statusCode: 400,
|
||||
message: "Cancellation reason is required when you are the host",
|
||||
|
||||
@@ -132,6 +132,7 @@ describe("Cancel Booking", () => {
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
cancelledBy: organizer.email,
|
||||
cancellationReason: "No reason",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -261,6 +262,7 @@ describe("Cancel Booking", () => {
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
cancelledBy: organizer.email,
|
||||
cancellationReason: "No reason",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -510,6 +512,74 @@ describe("Cancel Booking", () => {
|
||||
).rejects.toThrow("Cannot cancel a booking that has already ended");
|
||||
});
|
||||
|
||||
test("Should block canceling bookings without a cancellation reason when cancelledBy is set to the host", async () => {
|
||||
const handleCancelBooking = (await import("@calcom/features/bookings/lib/handleCancelBooking")).default;
|
||||
|
||||
const booker = getBooker({
|
||||
email: "booker@example.com",
|
||||
name: "Booker",
|
||||
});
|
||||
|
||||
const organizer = getOrganizer({
|
||||
name: "Organizer",
|
||||
email: "organizer@example.com",
|
||||
id: 101,
|
||||
schedules: [TestData.schedules.IstWorkHours],
|
||||
credentials: [getGoogleCalendarCredential()],
|
||||
selectedCalendars: [TestData.selectedCalendars.google],
|
||||
});
|
||||
|
||||
const uidOfBookingToBeCancelled = "cancelled-booking";
|
||||
const idOfBookingToBeCancelled = 3040;
|
||||
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
|
||||
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
slotInterval: 30,
|
||||
length: 30,
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bookings: [
|
||||
{
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
eventTypeId: 1,
|
||||
userId: 101,
|
||||
responses: {
|
||||
email: booker.email,
|
||||
name: booker.name,
|
||||
location: { optionValue: "", value: BookingLocations.CalVideo },
|
||||
},
|
||||
status: BookingStatus.ACCEPTED,
|
||||
startTime: `${plus1DateString}T05:00:00.000Z`,
|
||||
endTime: `${plus1DateString}T05:30:00.000Z`,
|
||||
},
|
||||
],
|
||||
organizer,
|
||||
apps: [TestData.apps["daily-video"]],
|
||||
})
|
||||
);
|
||||
|
||||
// This should throw an error with current implementation
|
||||
await expect(
|
||||
handleCancelBooking({
|
||||
bookingData: {
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
cancelledBy: organizer.email,
|
||||
},
|
||||
})
|
||||
).rejects.toThrow("Cancellation reason is required when you are the host");
|
||||
});
|
||||
|
||||
test("Should not charge cancellation fee when organizer cancels booking", async () => {
|
||||
const handleCancelBooking = (await import("@calcom/features/bookings/lib/handleCancelBooking")).default;
|
||||
|
||||
@@ -615,6 +685,7 @@ describe("Cancel Booking", () => {
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
cancelledBy: organizer.email,
|
||||
cancellationReason: "No reason",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -747,6 +818,7 @@ describe("Cancel Booking", () => {
|
||||
id: idOfBookingToBeCancelled,
|
||||
uid: uidOfBookingToBeCancelled,
|
||||
cancelledBy: organizer.email,
|
||||
cancellationReason: "No reason",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user