From fe1e73aff612e6627bd3f5eb033c16896ca16d1d Mon Sep 17 00:00:00 2001 From: Ossama Lafhel Date: Mon, 15 Sep 2025 16:04:47 +0200 Subject: [PATCH] =?UTF-8?q?feat(minimum-cancellation-notice):=20=E2=9C=A8?= =?UTF-8?q?=20add=20minimum=20cancellation/reschedule=20notice=20for=20boo?= =?UTF-8?q?kings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add minimum cancellation notice field to event types - Implement validation for cancellation requests within minimum notice period - Add validation for reschedule requests within minimum notice period - Add comprehensive e2e and unit tests for the feature - Update UI components to support minimum cancellation notice - Add database migration for minimumCancellationNotice field - Add documentation for the new feature --- apps/web/CHANGELOG.md | 21 +- .../dialog/RescheduleDialog.test.tsx | 367 ++++++++ .../components/dialog/RescheduleDialog.tsx | 13 +- apps/web/package.json | 3 +- .../playwright/cancellation-validation.e2e.ts | 235 +++++ .../minimum-cancellation-notice.e2e.ts | 453 ++++++++++ .../reschedule-minimum-notice.e2e.ts | 218 +++++ apps/web/test-results/.last-run.json | 2 +- .../minimum-cancellation-notice.mdx | 156 ++++ .../bookings/lib/getBookingToDelete.ts | 1 + .../bookings/lib/handleCancelBooking.ts | 29 +- .../handleCancelBooking.minimumNotice.test.ts | 820 ++++++++++++++++++ ...iginalRescheduledBookingUtils.edge.test.ts | 543 ++++++++++++ .../originalRescheduledBookingUtils.test.ts | 177 ++++ .../originalRescheduledBookingUtils.ts | 30 +- .../lib/minimumNotice.integration.test.ts | 667 ++++++++++++++ .../tabs/limits/EventLimitsTab.test.tsx | 631 ++++++++++++++ .../components/tabs/limits/EventLimitsTab.tsx | 20 + .../MinimumCancellationNoticeInput.test.tsx | 690 +++++++++++++++ .../limits/MinimumCancellationNoticeInput.tsx | 111 +++ .../lib/types-minimumCancellationNotice.ts | 5 + .../convertToNewDurationType.test.ts | 234 +++++ .../lib/__tests__/findDurationType.test.ts | 251 ++++++ .../minimumCancellationNotice.test.ts | 101 +++ packages/prisma/eventType.integration.test.ts | 579 +++++++++++++ .../migration.sql | 2 + ...inimumCancellationNotice.migration.test.ts | 281 ++++++ ...nimumCancellationNotice.validation.test.ts | 432 +++++++++ packages/prisma/schema.prisma | 2 + .../requestReschedule.handler.test.ts | 802 +++++++++++++++++ .../bookings/requestReschedule.handler.ts | 268 +++--- .../requestReschedule.integration.test.ts | 637 ++++++++++++++ 32 files changed, 8645 insertions(+), 136 deletions(-) create mode 100644 apps/web/components/dialog/RescheduleDialog.test.tsx create mode 100644 apps/web/playwright/cancellation-validation.e2e.ts create mode 100644 apps/web/playwright/minimum-cancellation-notice.e2e.ts create mode 100644 apps/web/playwright/reschedule-minimum-notice.e2e.ts create mode 100644 docs/developing/guides/event-types/minimum-cancellation-notice.mdx create mode 100644 packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.minimumNotice.test.ts create mode 100644 packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.edge.test.ts create mode 100644 packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.test.ts create mode 100644 packages/features/bookings/lib/minimumNotice.integration.test.ts create mode 100644 packages/features/eventtypes/components/tabs/limits/EventLimitsTab.test.tsx create mode 100644 packages/features/eventtypes/components/tabs/limits/MinimumCancellationNoticeInput.test.tsx create mode 100644 packages/features/eventtypes/components/tabs/limits/MinimumCancellationNoticeInput.tsx create mode 100644 packages/features/eventtypes/lib/types-minimumCancellationNotice.ts create mode 100644 packages/lib/__tests__/convertToNewDurationType.test.ts create mode 100644 packages/lib/__tests__/findDurationType.test.ts create mode 100644 packages/lib/event-types/minimumCancellationNotice.test.ts create mode 100644 packages/prisma/eventType.integration.test.ts create mode 100644 packages/prisma/migrations/20250915064816_add_minimum_cancellation_notice/migration.sql create mode 100644 packages/prisma/minimumCancellationNotice.migration.test.ts create mode 100644 packages/prisma/minimumCancellationNotice.validation.test.ts create mode 100644 packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.test.ts create mode 100644 packages/trpc/server/routers/viewer/bookings/requestReschedule.integration.test.ts diff --git a/apps/web/CHANGELOG.md b/apps/web/CHANGELOG.md index e467dc902737b5..5292c6989fd1cd 100644 --- a/apps/web/CHANGELOG.md +++ b/apps/web/CHANGELOG.md @@ -1,5 +1,24 @@ # @calcom/web +## 5.3.0 + +### Minor Changes + +- **New Feature**: Minimum Cancellation/Reschedule Notice + - Added ability to set minimum notice periods for cancellations and reschedules on event types + - Prevents attendees from cancelling or rescheduling bookings too close to the event start time + - Configurable per event type with support for minutes, hours, and days + - Automatic validation and user-friendly error messages + - Database schema updated with `minimumCancellationNotice` field on EventType model + - Full integration with existing booking cancellation and reschedule workflows + +### Patch Changes + +- Enhanced booking cancellation flow with minimum notice validation +- Updated reschedule dialog to handle minimum notice restrictions +- Added MinimumCancellationNoticeInput component for event type configuration +- Improved error messaging for time-restricted cancellations and reschedules + ## 5.2.8 ### Patch Changes @@ -104,4 +123,4 @@ - Updated dependencies - @calcom/embed-snippet@1.0.7 - @calcom/embed-react@1.0.12 - - @calcom/embed-core@1.1.5 + - @calcom/embed-core@1.1.5 \ No newline at end of file diff --git a/apps/web/components/dialog/RescheduleDialog.test.tsx b/apps/web/components/dialog/RescheduleDialog.test.tsx new file mode 100644 index 00000000000000..8bc167315fce7a --- /dev/null +++ b/apps/web/components/dialog/RescheduleDialog.test.tsx @@ -0,0 +1,367 @@ +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { vi, describe, it, expect, beforeEach, afterEach } from "vitest"; +import { RescheduleDialog } from "./RescheduleDialog"; +import { trpc } from "@calcom/trpc/react"; +import { showToast } from "@calcom/ui/components/toast"; + +// Mock the dependencies +vi.mock("@calcom/lib/hooks/useLocale", () => ({ + useLocale: () => ({ + t: (key: string) => key, + }), +})); + +vi.mock("@calcom/trpc/react", () => ({ + trpc: { + useUtils: vi.fn(), + viewer: { + bookings: { + requestReschedule: { + useMutation: vi.fn(), + }, + }, + }, + }, +})); + +vi.mock("@calcom/ui/components/toast", () => ({ + showToast: vi.fn(), +})); + +vi.mock("@calcom/features/components/controlled-dialog", () => ({ + Dialog: ({ children, open, onOpenChange }: any) => { + if (!open) return null; + return ( +
+ {children} + +
+ ); + }, +})); + +vi.mock("@calcom/ui/components/dialog", () => ({ + DialogContent: ({ children }: any) =>
{children}
, + DialogHeader: ({ title }: any) =>

{title}

, + DialogFooter: ({ children }: any) =>
{children}
, +})); + +vi.mock("@calcom/ui/components/button", () => ({ + Button: ({ children, onClick, disabled, ...props }: any) => ( + + ), +})); + +vi.mock("@calcom/ui/components/form", () => ({ + TextArea: ({ value, onChange, ...props }: any) => ( +