From dcf10935de5afce1ee5c32cc28996d87811787cf Mon Sep 17 00:00:00 2001 From: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com> Date: Wed, 7 Jan 2026 19:33:01 +0530 Subject: [PATCH] feat: add missing event type fields for advanced settings in api v2 (#25739) * feat: api v2 add missing event type fields for advanced settings Add 9 event type fields to API v2 that were available in tRPC but missing from the platform API: - disableCancelling: disable cancelling for guests/organizer - disableRescheduling: disable rescheduling for guests/organizer - canSendCalVideoTranscriptionEmails: send Cal Video transcription emails - autoTranslateInstantMeetingTitleEnabled: auto-translate instant meeting titles - interfaceLanguage: preferred booking interface language - allowReschedulingPastBookings: allow rescheduling past events - allowReschedulingCancelledBookings: allow booking via reschedule link - customReplyToEmail: custom reply-to email for confirmations - showOptimizedSlots: optimize time slot arrangement Updated output/input schemas, transformation services, and E2E tests. * fix(api-v2): add proper OpenAPI types for nullable event type fields Add explicit type and nullable properties to @ApiPropertyOptional decorators for fields with `boolean | null` or `string | null` types. Without these, Swagger was generating incorrect "type": "object" instead of the correct types. Fixed fields: - disableCancelling: type: Boolean, nullable: true - disableRescheduling: type: Boolean, nullable: true - interfaceLanguage: type: String, nullable: true - allowReschedulingCancelledBookings: type: Boolean, nullable: true - customReplyToEmail: type: String, nullable: true - showOptimizedSlots: type: Boolean, nullable: true * refactor: customReplyToEmail was intentionally excluded from this PR. The web UI restricts this field to only allow the user's own verified emails via a dropdown, but implementing the same validation in the API requires additional business logic. This will be addressed in a separate PR with proper email ownership validation. * feat(api-v2): add validation for interfaceLanguage field Add @IsIn validation to interfaceLanguage field to only accept supported locales. This ensures API v2 matches the web UI behavior where users can only select from a predefined dropdown of supported languages. Changes: - Add SUPPORTED_LOCALES constant to @calcom/platform-constants - Add @IsIn([...SUPPORTED_LOCALES]) validation to create/update DTOs - Add E2E tests for invalid locale rejection (400 error) - Add cross-reference comments in i18n.json and api.ts to keep in sync * docs(api): add default values to event type input field documentation Added default value documentation to @DocsPropertyOptional decorators for the new event type fields in API v2 (2024_06_14): - disableCancelling: false - disableRescheduling: false - canSendCalVideoTranscriptionEmails: true - autoTranslateInstantMeetingTitleEnabled: false - allowReschedulingPastBookings: false - allowReschedulingCancelledBookings: false - showOptimizedSlots: false This improves API documentation by clearly communicating default values to API consumers in the OpenAPI spec. * feat(api-v2): refactor event type settings to object types for future extensibility - Convert disableRescheduling from boolean to object with disabled and minutesBefore properties - Convert disableCancelling from boolean to object with disabled property - Move canSendCalVideoTranscriptionEmails into CalVideoSettings as sendTranscriptionEmails - Remove autoTranslateInstantMeetingTitleEnabled (Enterprise-only feature) - Add DisableRescheduling_2024_06_14 and DisableCancelling_2024_06_14 input/output types - Add transformation methods for new object types in input and output services - Update E2E tests for new API contract BREAKING CHANGE: disableRescheduling and disableCancelling now accept objects instead of booleans * fix(api-v2): prevent clearing calVideoSettings when only sendTranscriptionEmails is provided Only include calVideoSettings in transformed output if it has properties, avoiding unintentional reset of existing settings during updates. --- .../event-types.controller.e2e-spec.ts | 102 ++++ .../services/input-event-types.service.ts | 82 ++++ .../services/output-event-types.service.ts | 71 ++- .../transformed/event-type.tranformed.ts | 19 +- .../event-types/services/output.service.ts | 8 + docs/api-reference/v2/openapi.json | 453 ++++++++++++++++++ i18n.json | 1 + packages/platform/constants/api.ts | 44 ++ .../inputs/create-event-type.input.ts | 72 ++- .../inputs/disable-cancelling.input.ts | 15 + .../inputs/disable-rescheduling.input.ts | 23 + .../event-types_2024_06_14/inputs/index.ts | 2 + .../inputs/update-event-type.input.ts | 63 ++- .../outputs/disable-cancelling.output.ts | 15 + .../outputs/disable-rescheduling.output.ts | 23 + .../outputs/event-type.output.ts | 56 +++ .../event-types_2024_06_14/outputs/index.ts | 2 + 17 files changed, 1046 insertions(+), 5 deletions(-) create mode 100644 packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-cancelling.input.ts create mode 100644 packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-rescheduling.input.ts create mode 100644 packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-cancelling.output.ts create mode 100644 packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-rescheduling.output.ts diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts index a0da2d4bfe..bd3a48bcd3 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts @@ -432,6 +432,29 @@ describe("Event types Endpoints", () => { .expect(400); }); + it("should return an error when creating an event type with invalid interfaceLanguage", async () => { + const body: CreateEventTypeInput_2024_06_14 = { + title: "Coding class invalid locale", + slug: "coding-class-invalid-locale", + description: "Let's learn how to code like a pro.", + lengthInMinutes: 60, + locations: [ + { + type: "integration", + integration: "cal-video", + }, + ], + interfaceLanguage: "invalid-locale-xyz", + }; + + return request(app.getHttpServer()) + .post("/api/v2/event-types") + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .set("Authorization", `Bearer ${apiKeyString}`) + .send(body) + .expect(400); + }); + it("should create an event type", async () => { const nameBookingField: NameDefaultFieldInput_2024_06_14 = { type: "name", @@ -532,6 +555,13 @@ describe("Event types Endpoints", () => { }, customName: `{Event type title} between {Organiser} and {Scheduler}`, bookingRequiresAuthentication: true, + disableCancelling: { disabled: true }, + disableRescheduling: { disabled: true }, + calVideoSettings: { sendTranscriptionEmails: true }, + interfaceLanguage: "en", + allowReschedulingPastBookings: true, + allowReschedulingCancelledBookings: true, + showOptimizedSlots: true, }; return request(app.getHttpServer()) @@ -606,6 +636,15 @@ describe("Event types Endpoints", () => { expect(createdEventType.bookingFields).toEqual(expectedBookingFields); expect(createdEventType.bookingRequiresAuthentication).toEqual(true); + expect(createdEventType.disableCancelling).toEqual({ disabled: true }); + expect(createdEventType.disableRescheduling).toEqual({ disabled: true }); + expect(createdEventType.calVideoSettings?.sendTranscriptionEmails).toEqual(true); + expect(createdEventType.interfaceLanguage).toEqual(body.interfaceLanguage); + expect(createdEventType.allowReschedulingPastBookings).toEqual(body.allowReschedulingPastBookings); + expect(createdEventType.allowReschedulingCancelledBookings).toEqual( + body.allowReschedulingCancelledBookings + ); + expect(createdEventType.showOptimizedSlots).toEqual(body.showOptimizedSlots); eventType = responseBody.data; }); }); @@ -693,6 +732,19 @@ describe("Event types Endpoints", () => { ); expect(fetchedEventType?.color).toEqual(eventType.color); expect(fetchedEventType?.hidden).toEqual(false); + expect(fetchedEventType?.disableCancelling).toEqual(eventType.disableCancelling); + expect(fetchedEventType?.disableRescheduling).toEqual(eventType.disableRescheduling); + expect(fetchedEventType?.calVideoSettings?.sendTranscriptionEmails).toEqual( + eventType.calVideoSettings?.sendTranscriptionEmails + ); + expect(fetchedEventType?.interfaceLanguage).toEqual(eventType.interfaceLanguage); + expect(fetchedEventType?.allowReschedulingPastBookings).toEqual( + eventType.allowReschedulingPastBookings + ); + expect(fetchedEventType?.allowReschedulingCancelledBookings).toEqual( + eventType.allowReschedulingCancelledBookings + ); + expect(fetchedEventType?.showOptimizedSlots).toEqual(eventType.showOptimizedSlots); expect(fetchedHiddenEventType?.id).toEqual(hiddenEventType.id); expect(fetchedHiddenEventType?.hidden).toEqual(true); @@ -822,6 +874,19 @@ describe("Event types Endpoints", () => { ); expect(fetchedEventType?.color).toEqual(eventType.color); expect(fetchedEventType?.hidden).toEqual(false); + expect(fetchedEventType?.disableCancelling).toEqual(eventType.disableCancelling); + expect(fetchedEventType?.disableRescheduling).toEqual(eventType.disableRescheduling); + expect(fetchedEventType?.calVideoSettings?.sendTranscriptionEmails).toEqual( + eventType.calVideoSettings?.sendTranscriptionEmails + ); + expect(fetchedEventType?.interfaceLanguage).toEqual(eventType.interfaceLanguage); + expect(fetchedEventType?.allowReschedulingPastBookings).toEqual( + eventType.allowReschedulingPastBookings + ); + expect(fetchedEventType?.allowReschedulingCancelledBookings).toEqual( + eventType.allowReschedulingCancelledBookings + ); + expect(fetchedEventType?.showOptimizedSlots).toEqual(eventType.showOptimizedSlots); }); it(`/GET/event-types by username and eventSlug should not return hidden event type if auth of non event type owner provided`, async () => { @@ -1209,6 +1274,7 @@ describe("Event types Endpoints", () => { enableAutomaticTranscription: true, disableTranscriptionForGuests: true, disableTranscriptionForOrganizer: true, + sendTranscriptionEmails: false, }, bookingFields: [ nameBookingField, @@ -1268,6 +1334,12 @@ describe("Event types Endpoints", () => { }, customName: `{Event type title} betweennnnnnnnnnn {Organiser} and {Scheduler}`, bookingRequiresAuthentication: false, + disableCancelling: { disabled: false }, + disableRescheduling: { disabled: false, minutesBefore: 60 }, + interfaceLanguage: "es", + allowReschedulingPastBookings: false, + allowReschedulingCancelledBookings: false, + showOptimizedSlots: false, }; return request(app.getHttpServer()) @@ -1374,6 +1446,23 @@ describe("Event types Endpoints", () => { eventType.calVideoSettings = updatedEventType.calVideoSettings; expect(updatedEventType.bookingRequiresAuthentication).toEqual(false); + expect(updatedEventType.disableCancelling).toEqual({ disabled: false }); + expect(updatedEventType.disableRescheduling).toEqual({ disabled: false, minutesBefore: 60 }); + expect(updatedEventType.calVideoSettings?.sendTranscriptionEmails).toEqual(false); + expect(updatedEventType.interfaceLanguage).toEqual(body.interfaceLanguage); + expect(updatedEventType.allowReschedulingPastBookings).toEqual(body.allowReschedulingPastBookings); + expect(updatedEventType.allowReschedulingCancelledBookings).toEqual( + body.allowReschedulingCancelledBookings + ); + expect(updatedEventType.showOptimizedSlots).toEqual(body.showOptimizedSlots); + + eventType.disableCancelling = updatedEventType.disableCancelling; + eventType.disableRescheduling = updatedEventType.disableRescheduling; + eventType.calVideoSettings = updatedEventType.calVideoSettings; + eventType.interfaceLanguage = updatedEventType.interfaceLanguage; + eventType.allowReschedulingPastBookings = updatedEventType.allowReschedulingPastBookings; + eventType.allowReschedulingCancelledBookings = updatedEventType.allowReschedulingCancelledBookings; + eventType.showOptimizedSlots = updatedEventType.showOptimizedSlots; }); }); @@ -1408,6 +1497,19 @@ describe("Event types Endpoints", () => { .expect(400); }); + it("should return an error when updating an event type with invalid interfaceLanguage", async () => { + const body: UpdateEventTypeInput_2024_06_14 = { + interfaceLanguage: "invalid-locale-xyz", + }; + + return request(app.getHttpServer()) + .patch(`/api/v2/event-types/${eventType.id}`) + .set("Authorization", `Bearer ${apiKeyString}`) + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .send(body) + .expect(400); + }); + it(`/GET/:id`, async () => { const response = await request(app.getHttpServer()) .get(`/api/v2/event-types/${eventType.id}`) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts index fe392fef16..2b16fa0d31 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts @@ -131,6 +131,9 @@ export class InputEventTypesService_2024_06_14 { disableGuests, bookerActiveBookingsLimit, slug, + disableRescheduling, + disableCancelling, + calVideoSettings, ...rest } = inputEventType; const confirmationPolicyTransformed = this.transformInputConfirmationPolicy(confirmationPolicy); @@ -155,6 +158,10 @@ export class InputEventTypesService_2024_06_14 { multipleDuration: lengthInMinutesOptions, }; + const disableReschedulingTransformed = this.transformInputDisableRescheduling(disableRescheduling); + const disableCancellingTransformed = this.transformInputDisableCancelling(disableCancelling); + const calVideoSettingsTransformed = this.transformInputCalVideoSettings(calVideoSettings); + const eventType = { ...rest, slug: slugifiedSlug, @@ -176,6 +183,9 @@ export class InputEventTypesService_2024_06_14 { eventName: customName, useEventTypeDestinationCalendarEmail: useDestinationCalendarEmail, ...maxActiveBookingsPerBooker, + ...disableReschedulingTransformed, + ...disableCancellingTransformed, + ...calVideoSettingsTransformed, }; return eventType; @@ -215,6 +225,9 @@ export class InputEventTypesService_2024_06_14 { disableGuests, bookerActiveBookingsLimit, slug, + disableRescheduling, + disableCancelling, + calVideoSettings, ...rest } = inputEventType; const eventTypeDb = await this.eventTypesRepository.getEventTypeWithMetaData(eventTypeId); @@ -247,6 +260,16 @@ export class InputEventTypesService_2024_06_14 { ...(lengthInMinutesOptions !== undefined ? { multipleDuration: lengthInMinutesOptions } : {}), }; + const disableReschedulingTransformed = disableRescheduling + ? this.transformInputDisableRescheduling(disableRescheduling) + : {}; + const disableCancellingTransformed = disableCancelling + ? this.transformInputDisableCancelling(disableCancelling) + : {}; + const calVideoSettingsTransformed = calVideoSettings + ? this.transformInputCalVideoSettings(calVideoSettings) + : {}; + const eventType = { ...rest, ...(slug ? { slug: slugifyLenient(slug) } : {}), @@ -270,6 +293,9 @@ export class InputEventTypesService_2024_06_14 { eventName: customName, useEventTypeDestinationCalendarEmail: useDestinationCalendarEmail, ...maxActiveBookingsPerBooker, + ...disableReschedulingTransformed, + ...disableCancellingTransformed, + ...calVideoSettingsTransformed, }; return eventType; @@ -602,4 +628,60 @@ export class InputEventTypesService_2024_06_14 { } return foundApp.credential; } + + transformInputDisableRescheduling(disableRescheduling: CreateEventTypeInput_2024_06_14["disableRescheduling"]) { + if (!disableRescheduling) { + return {}; + } + + // If disabled is true, rescheduling is always disabled + if (disableRescheduling.disabled === true) { + return { + disableRescheduling: true, + minimumRescheduleNotice: null, + }; + } + + // If minutesBefore is set, use it for conditional disable + if (disableRescheduling.minutesBefore && disableRescheduling.minutesBefore > 0) { + return { + disableRescheduling: false, + minimumRescheduleNotice: disableRescheduling.minutesBefore, + }; + } + + // Otherwise rescheduling is not disabled + return { + disableRescheduling: false, + minimumRescheduleNotice: null, + }; + } + + transformInputDisableCancelling(disableCancelling: CreateEventTypeInput_2024_06_14["disableCancelling"]) { + if (!disableCancelling) { + return {}; + } + + return { + disableCancelling: disableCancelling.disabled === true, + }; + } + + transformInputCalVideoSettings(calVideoSettings: CreateEventTypeInput_2024_06_14["calVideoSettings"]) { + if (!calVideoSettings) { + return {}; + } + + // Extract sendTranscriptionEmails from calVideoSettings and map to canSendCalVideoTranscriptionEmails + const { sendTranscriptionEmails, ...restCalVideoSettings } = calVideoSettings; + + const hasOtherSettings = Object.keys(restCalVideoSettings).length > 0; + + return { + ...(hasOtherSettings ? { calVideoSettings: restCalVideoSettings } : {}), + ...(sendTranscriptionEmails !== undefined + ? { canSendCalVideoTranscriptionEmails: sendTranscriptionEmails } + : {}), + }; + } } diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts index d53d14e4e0..ea7207a8b6 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts @@ -40,7 +40,7 @@ type EventTypeRelations = { destinationCalendar?: DestinationCalendar | null; calVideoSettings?: CalVideoSettings | null; }; -export type DatabaseEventType = Omit & EventTypeRelations; +export type DatabaseEventType = EventType & EventTypeRelations; type Input = Pick< DatabaseEventType, @@ -94,6 +94,14 @@ type Input = Pick< | "bookingRequiresAuthentication" | "maxActiveBookingsPerBooker" | "maxActiveBookingPerBookerOfferReschedule" + | "disableCancelling" + | "disableRescheduling" + | "minimumRescheduleNotice" + | "canSendCalVideoTranscriptionEmails" + | "interfaceLanguage" + | "allowReschedulingPastBookings" + | "allowReschedulingCancelledBookings" + | "showOptimizedSlots" >; @Injectable() @@ -134,6 +142,14 @@ export class OutputEventTypesService_2024_06_14 { calVideoSettings, hidden, bookingRequiresAuthentication, + disableCancelling, + disableRescheduling, + minimumRescheduleNotice, + canSendCalVideoTranscriptionEmails, + interfaceLanguage, + allowReschedulingPastBookings, + allowReschedulingCancelledBookings, + showOptimizedSlots, } = databaseEventType; const locations = this.transformLocations(databaseEventType.locations); @@ -168,6 +184,15 @@ export class OutputEventTypesService_2024_06_14 { } as TransformFutureBookingsLimitSchema_2024_06_14); const destinationCalendar = this.transformDestinationCalendar(databaseEventType.destinationCalendar); const bookerActiveBookingsLimit = this.transformBookerActiveBookingsLimit(databaseEventType); + const disableReschedulingOutput = this.transformDisableRescheduling( + disableRescheduling, + minimumRescheduleNotice + ); + const disableCancellingOutput = this.transformDisableCancelling(disableCancelling); + const calVideoSettingsOutput = this.transformCalVideoSettings( + calVideoSettings, + canSendCalVideoTranscriptionEmails + ); return { id, @@ -210,10 +235,16 @@ export class OutputEventTypesService_2024_06_14 { useDestinationCalendarEmail: useEventTypeDestinationCalendarEmail, hideCalendarEventDetails, hideOrganizerEmail, - calVideoSettings, + calVideoSettings: calVideoSettingsOutput, hidden, bookingRequiresAuthentication, bookerActiveBookingsLimit, + disableCancelling: disableCancellingOutput, + disableRescheduling: disableReschedulingOutput, + interfaceLanguage, + allowReschedulingPastBookings, + allowReschedulingCancelledBookings, + showOptimizedSlots, }; } @@ -395,4 +426,40 @@ export class OutputEventTypesService_2024_06_14 { bookingFields: visibleBookingFields, }; } + + transformDisableRescheduling( + disableRescheduling: boolean | null | undefined, + minimumRescheduleNotice: number | null | undefined + ) { + // If disableRescheduling is true, rescheduling is always disabled + if (disableRescheduling === true) { + return { disabled: true }; + } + + // If minimumRescheduleNotice is set, rescheduling is conditionally disabled + if (minimumRescheduleNotice && minimumRescheduleNotice > 0) { + return { disabled: false, minutesBefore: minimumRescheduleNotice }; + } + + // Otherwise rescheduling is not disabled + return { disabled: false }; + } + + transformDisableCancelling(disableCancelling: boolean | null | undefined) { + return { disabled: disableCancelling === true }; + } + + transformCalVideoSettings( + calVideoSettings: CalVideoSettings | null | undefined, + canSendCalVideoTranscriptionEmails: boolean | null | undefined + ) { + if (!calVideoSettings && canSendCalVideoTranscriptionEmails === undefined) { + return undefined; + } + + return { + ...calVideoSettings, + sendTranscriptionEmails: canSendCalVideoTranscriptionEmails ?? true, + }; + } } diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformed/event-type.tranformed.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformed/event-type.tranformed.ts index c613b6d71c..e884766277 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformed/event-type.tranformed.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformed/event-type.tranformed.ts @@ -29,6 +29,10 @@ export type InputEventTransformed_2024_06_14 = Omit< | "seats" | "customName" | "useDestinationCalendarEmail" + | "disableRescheduling" + | "disableCancelling" + | "calVideoSettings" + | "bookerActiveBookingsLimit" > & { length: number; slug: string; @@ -38,10 +42,23 @@ export type InputEventTransformed_2024_06_14 = Omit< bookingFields?: ReturnType; durationLimits?: ReturnType; recurringEvent?: ReturnType; - maxActiveBookingsPerBooker?: number; + maxActiveBookingsPerBooker?: number | null; maxActiveBookingPerBookerOfferReschedule?: boolean; eventTypeColor?: ReturnType; useEventTypeDestinationCalendarEmail?: boolean; + disableRescheduling?: boolean; + disableCancelling?: boolean; + minimumRescheduleNotice?: number | null; + canSendCalVideoTranscriptionEmails?: boolean; + calVideoSettings?: { + disableRecordingForOrganizer?: boolean; + disableRecordingForGuests?: boolean; + redirectUrlOnExit?: string | null; + enableAutomaticRecordingForOrganizer?: boolean; + enableAutomaticTranscription?: boolean; + disableTranscriptionForGuests?: boolean; + disableTranscriptionForOrganizer?: boolean; + }; } & Partial< Pick > & diff --git a/apps/api/v2/src/modules/organizations/event-types/services/output.service.ts b/apps/api/v2/src/modules/organizations/event-types/services/output.service.ts index ba0cd2dc59..dc48db092a 100644 --- a/apps/api/v2/src/modules/organizations/event-types/services/output.service.ts +++ b/apps/api/v2/src/modules/organizations/event-types/services/output.service.ts @@ -88,6 +88,14 @@ type Input = Pick< | "rescheduleWithSameRoundRobinHost" | "maxActiveBookingPerBookerOfferReschedule" | "maxActiveBookingsPerBooker" + | "disableCancelling" + | "disableRescheduling" + | "minimumRescheduleNotice" + | "canSendCalVideoTranscriptionEmails" + | "interfaceLanguage" + | "allowReschedulingPastBookings" + | "allowReschedulingCancelledBookings" + | "showOptimizedSlots" | "rrHostSubsetEnabled" >; diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 16ba4bf668..e0684a0920 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -19114,6 +19114,31 @@ } } }, + "DisableRescheduling_2024_06_14": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean", + "description": "If true, rescheduling is always disabled for this event type.", + "example": true + }, + "minutesBefore": { + "type": "number", + "description": "Disable rescheduling when less than the specified number of minutes before the meeting. If set, `disabled` should be false or undefined.", + "example": 60 + } + } + }, + "DisableCancelling_2024_06_14": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean", + "description": "If true, cancelling is always disabled for this event type.", + "example": true + } + } + }, "CalVideoSettings": { "type": "object", "properties": { @@ -19144,6 +19169,11 @@ "disableTranscriptionForOrganizer": { "type": "boolean", "description": "If true, the organizer will not be able to receive transcription of the meeting" + }, + "sendTranscriptionEmails": { + "type": "boolean", + "description": "Send emails with the transcription of the Cal Video after the meeting ends.", + "default": true } } }, @@ -19417,6 +19447,88 @@ "default": false, "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "example": { + "disabled": true + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancelling_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "example": { + "disabled": false, + "minutesBefore": 60 + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableRescheduling_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + "enum": [ + "", + "en", + "ar", + "az", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "es", + "es-419", + "eu", + "et", + "fi", + "fr", + "he", + "hu", + "it", + "ja", + "km", + "ko", + "nl", + "no", + "pl", + "pt-BR", + "pt", + "ro", + "ru", + "sk-SK", + "sr", + "sv", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW" + ] + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled.", + "default": false + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + "default": false + }, + "showOptimizedSlots": { + "type": "boolean", + "description": "Arrange time slots to optimize availability.", + "default": false + }, "locations": { "type": "array", "description": "Locations where the event will take place. If not provided, cal video link will be used as the location. Note: Setting a location to a conferencing app does not install the app - the app must already be installed. Via API, only Google Meet (google-meet), Microsoft Teams (office365-video), and Zoom (zoom) can be installed. Cal Video (cal-video) is installed by default. All other conferencing apps must be connected via the Cal.com web app and are not available for Platform plan customers. You can only set an event type location to an app that has already been installed or connected.", @@ -20528,6 +20640,31 @@ } } }, + "DisableCancellingOutput_2024_06_14": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean", + "description": "If true, cancelling is always disabled for this event type.", + "example": true + } + } + }, + "DisableReschedulingOutput_2024_06_14": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean", + "description": "If true, rescheduling is always disabled for this event type.", + "example": true + }, + "minutesBefore": { + "type": "number", + "description": "Rescheduling is disabled when less than the specified number of minutes before the meeting.", + "example": 60 + } + } + }, "EventTypeOutput_2024_06_14": { "type": "object", "properties": { @@ -20796,6 +20933,41 @@ "type": "boolean", "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancellingOutput_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "allOf": [ + { + "$ref": "#/components/schemas/DisableReschedulingOutput_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "nullable": true, + "description": "Set preferred language for the booking interface." + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled." + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "nullable": true, + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking." + }, + "showOptimizedSlots": { + "type": "boolean", + "nullable": true, + "description": "Arrange time slots to optimize availability." + }, "ownerId": { "type": "number", "example": 10 @@ -21162,6 +21334,41 @@ "type": "boolean", "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancellingOutput_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "allOf": [ + { + "$ref": "#/components/schemas/DisableReschedulingOutput_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "nullable": true, + "description": "Set preferred language for the booking interface." + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled." + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "nullable": true, + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking." + }, + "showOptimizedSlots": { + "type": "boolean", + "nullable": true, + "description": "Arrange time slots to optimize availability." + }, "teamId": { "type": "number" }, @@ -21550,6 +21757,88 @@ "default": false, "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "example": { + "disabled": true + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancelling_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "example": { + "disabled": false, + "minutesBefore": 60 + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableRescheduling_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + "enum": [ + "", + "en", + "ar", + "az", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "es", + "es-419", + "eu", + "et", + "fi", + "fr", + "he", + "hu", + "it", + "ja", + "km", + "ko", + "nl", + "no", + "pl", + "pt-BR", + "pt", + "ro", + "ru", + "sk-SK", + "sr", + "sv", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW" + ] + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled.", + "default": false + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + "default": false + }, + "showOptimizedSlots": { + "type": "boolean", + "description": "Arrange time slots to optimize availability.", + "default": false + }, "locations": { "type": "array", "description": "Locations where the event will take place. If not provided, cal video link will be used as the location. Note: Setting a location to a conferencing app does not install the app - the app must already be installed. Via API, only Google Meet (google-meet), Microsoft Teams (office365-video), and Zoom (zoom) can be installed. Cal Video (cal-video) is installed by default. All other conferencing apps must be connected via the Cal.com web app and are not available for Platform plan customers. You can only set an event type location to an app that has already been installed or connected.", @@ -23451,6 +23740,88 @@ "default": false, "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "example": { + "disabled": true + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancelling_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "example": { + "disabled": false, + "minutesBefore": 60 + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableRescheduling_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + "enum": [ + "", + "en", + "ar", + "az", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "es", + "es-419", + "eu", + "et", + "fi", + "fr", + "he", + "hu", + "it", + "ja", + "km", + "ko", + "nl", + "no", + "pl", + "pt-BR", + "pt", + "ro", + "ru", + "sk-SK", + "sr", + "sv", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW" + ] + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled.", + "default": false + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + "default": false + }, + "showOptimizedSlots": { + "type": "boolean", + "description": "Arrange time slots to optimize availability.", + "default": false + }, "schedulingType": { "type": "string", "enum": [ @@ -23962,6 +24333,88 @@ "default": false, "description": "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type." }, + "disableCancelling": { + "description": "Settings for disabling cancelling of this event type.", + "example": { + "disabled": true + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableCancelling_2024_06_14" + } + ] + }, + "disableRescheduling": { + "description": "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + "example": { + "disabled": false, + "minutesBefore": 60 + }, + "allOf": [ + { + "$ref": "#/components/schemas/DisableRescheduling_2024_06_14" + } + ] + }, + "interfaceLanguage": { + "type": "string", + "description": "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + "enum": [ + "", + "en", + "ar", + "az", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "es", + "es-419", + "eu", + "et", + "fi", + "fr", + "he", + "hu", + "it", + "ja", + "km", + "ko", + "nl", + "no", + "pl", + "pt-BR", + "pt", + "ro", + "ru", + "sk-SK", + "sr", + "sv", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW" + ] + }, + "allowReschedulingPastBookings": { + "type": "boolean", + "description": "Enabling this option allows for past events to be rescheduled.", + "default": false + }, + "allowReschedulingCancelledBookings": { + "type": "boolean", + "description": "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + "default": false + }, + "showOptimizedSlots": { + "type": "boolean", + "description": "Arrange time slots to optimize availability.", + "default": false + }, "schedulingType": { "type": "string", "enum": [ diff --git a/i18n.json b/i18n.json index dd6ef9b3b5..987c5f8703 100644 --- a/i18n.json +++ b/i18n.json @@ -1,5 +1,6 @@ { "version": 1.2, + "_comment": "When adding new locales, also update SUPPORTED_LOCALES in packages/platform/constants/api.ts", "locale": { "source": "en", "targets": [ diff --git a/packages/platform/constants/api.ts b/packages/platform/constants/api.ts index 36d98810f6..8709198294 100644 --- a/packages/platform/constants/api.ts +++ b/packages/platform/constants/api.ts @@ -71,3 +71,47 @@ export type API_VERSIONS_ENUM = (typeof API_VERSIONS)[number]; export type API_VERSIONS_TYPE = typeof API_VERSIONS; export const CAL_API_VERSION_HEADER = "cal-api-version"; export const MAX_SEATS_PER_TIME_SLOT = 1000; + +// Keep in sync with i18n.json locale.targets +export const SUPPORTED_LOCALES = [ + "", + "en", + "ar", + "az", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "es", + "es-419", + "eu", + "et", + "fi", + "fr", + "he", + "hu", + "it", + "ja", + "km", + "ko", + "nl", + "no", + "pl", + "pt-BR", + "pt", + "ro", + "ru", + "sk-SK", + "sr", + "sv", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW", +] as const; + +export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts index 14636fdd67..4f55c4ef9c 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts @@ -18,12 +18,16 @@ import { ValidateNested, ArrayNotEmpty, ArrayUnique, + IsIn, } from "class-validator"; +import { SUPPORTED_LOCALES } from "@calcom/platform-constants"; import { SchedulingType } from "@calcom/platform-enums"; import { RequiresAtLeastOnePropertyWhenNotDisabled } from "../../../utils/RequiresOneOfPropertiesWhenNotDisabled"; import { BookerActiveBookingsLimit_2024_06_14 } from "./booker-active-booking-limit.input"; +import { DisableCancelling_2024_06_14 } from "./disable-cancelling.input"; +import { DisableRescheduling_2024_06_14 } from "./disable-rescheduling.input"; import { BookerLayouts_2024_06_14 } from "./booker-layouts.input"; import { AddressFieldInput_2024_06_14, @@ -129,7 +133,9 @@ export const CREATE_EVENT_SLUG_EXAMPLE = "learn-the-secrets-of-masterchief"; GuestsDefaultFieldInput_2024_06_14, RescheduleReasonDefaultFieldInput_2024_06_14, InputOrganizersDefaultApp_2024_06_14, - EmailSettings_2024_06_14 + EmailSettings_2024_06_14, + DisableRescheduling_2024_06_14, + DisableCancelling_2024_06_14 ) export class CalVideoSettings { @IsOptional() @@ -180,6 +186,14 @@ export class CalVideoSettings { description: "If true, the organizer will not be able to receive transcription of the meeting", }) disableTranscriptionForOrganizer?: boolean; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: "Send emails with the transcription of the Cal Video after the meeting ends.", + default: true, + }) + sendTranscriptionEmails?: boolean; } @CantHaveRecurrenceAndBookerActiveBookingsLimit() @@ -513,6 +527,62 @@ export class BaseCreateEventTypeInput { "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.", }) bookingRequiresAuthentication?: boolean; + + @IsOptional() + @ValidateNested() + @Type(() => DisableCancelling_2024_06_14) + @DocsPropertyOptional({ + description: "Settings for disabling cancelling of this event type.", + type: DisableCancelling_2024_06_14, + example: { disabled: true }, + }) + disableCancelling?: DisableCancelling_2024_06_14; + + @IsOptional() + @ValidateNested() + @Type(() => DisableRescheduling_2024_06_14) + @DocsPropertyOptional({ + description: + "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + type: DisableRescheduling_2024_06_14, + example: { disabled: false, minutesBefore: 60 }, + }) + disableRescheduling?: DisableRescheduling_2024_06_14; + + @IsOptional() + @IsString() + @IsIn([...SUPPORTED_LOCALES]) + @DocsPropertyOptional({ + description: + "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + enum: SUPPORTED_LOCALES, + }) + interfaceLanguage?: string; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: "Enabling this option allows for past events to be rescheduled.", + default: false, + }) + allowReschedulingPastBookings?: boolean; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: + "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + default: false, + }) + allowReschedulingCancelledBookings?: boolean; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: "Arrange time slots to optimize availability.", + default: false, + }) + showOptimizedSlots?: boolean; } export class CreateEventTypeInput_2024_06_14 extends BaseCreateEventTypeInput { @IsOptional() diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-cancelling.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-cancelling.input.ts new file mode 100644 index 0000000000..4f3aea4e0b --- /dev/null +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-cancelling.input.ts @@ -0,0 +1,15 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; +import { IsBoolean, IsOptional } from "class-validator"; + +export class DisableCancelling_2024_06_14 { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + description: "If true, cancelling is always disabled for this event type.", + example: true, + }) + disabled?: boolean; + + // Note: minutesBefore can be added later when the feature is implemented for cancelling +} + diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-rescheduling.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-rescheduling.input.ts new file mode 100644 index 0000000000..b3861651af --- /dev/null +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/disable-rescheduling.input.ts @@ -0,0 +1,23 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; +import { IsBoolean, IsInt, IsOptional, Min } from "class-validator"; + +export class DisableRescheduling_2024_06_14 { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + description: "If true, rescheduling is always disabled for this event type.", + example: true, + }) + disabled?: boolean; + + @IsOptional() + @IsInt() + @Min(1) + @ApiPropertyOptional({ + description: + "Disable rescheduling when less than the specified number of minutes before the meeting. If set, `disabled` should be false or undefined.", + example: 60, + }) + minutesBefore?: number; +} + diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/index.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/index.ts index 9f87d63fb7..79a95a1869 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/index.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/index.ts @@ -14,3 +14,5 @@ export * from "./event-type-color.input"; export * from "./seats.input"; export * from "./destination-calendar.input"; export * from "./disabled.input"; +export * from "./disable-rescheduling.input"; +export * from "./disable-cancelling.input"; diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts index 415cf53b6b..bfbe0e4a41 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts @@ -19,6 +19,7 @@ import { IsIn, } from "class-validator"; +import { SUPPORTED_LOCALES } from "@calcom/platform-constants"; import { SchedulingType } from "@calcom/platform-enums"; import { RequiresAtLeastOnePropertyWhenNotDisabled } from "../../../utils/RequiresOneOfPropertiesWhenNotDisabled"; @@ -70,6 +71,8 @@ import { Host, CalVideoSettings, } from "./create-event-type.input"; +import { DisableCancelling_2024_06_14 } from "./disable-cancelling.input"; +import { DisableRescheduling_2024_06_14 } from "./disable-rescheduling.input"; import { DestinationCalendar_2024_06_14 } from "./destination-calendar.input"; import { Disabled_2024_06_14 } from "./disabled.input"; import { EmailSettings_2024_06_14 } from "./email-settings.input"; @@ -127,7 +130,9 @@ import { CantHaveRecurrenceAndBookerActiveBookingsLimit } from "./validators/Can GuestsDefaultFieldInput_2024_06_14, RescheduleReasonDefaultFieldInput_2024_06_14, BookerActiveBookingsLimit_2024_06_14, - EmailSettings_2024_06_14 + EmailSettings_2024_06_14, + DisableRescheduling_2024_06_14, + DisableCancelling_2024_06_14 ) @CantHaveRecurrenceAndBookerActiveBookingsLimit() class BaseUpdateEventTypeInput { @@ -461,6 +466,62 @@ class BaseUpdateEventTypeInput { "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.", }) bookingRequiresAuthentication?: boolean; + + @IsOptional() + @ValidateNested() + @Type(() => DisableCancelling_2024_06_14) + @DocsPropertyOptional({ + description: "Settings for disabling cancelling of this event type.", + type: DisableCancelling_2024_06_14, + example: { disabled: true }, + }) + disableCancelling?: DisableCancelling_2024_06_14; + + @IsOptional() + @ValidateNested() + @Type(() => DisableRescheduling_2024_06_14) + @DocsPropertyOptional({ + description: + "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + type: DisableRescheduling_2024_06_14, + example: { disabled: false, minutesBefore: 60 }, + }) + disableRescheduling?: DisableRescheduling_2024_06_14; + + @IsOptional() + @IsString() + @IsIn([...SUPPORTED_LOCALES]) + @DocsPropertyOptional({ + description: + "Set preferred language for the booking interface. Use empty string for visitor's browser language (default).", + enum: SUPPORTED_LOCALES, + }) + interfaceLanguage?: string; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: "Enabling this option allows for past events to be rescheduled.", + default: false, + }) + allowReschedulingPastBookings?: boolean; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: + "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + default: false, + }) + allowReschedulingCancelledBookings?: boolean; + + @IsOptional() + @IsBoolean() + @DocsPropertyOptional({ + description: "Arrange time slots to optimize availability.", + default: false, + }) + showOptimizedSlots?: boolean; } export class UpdateEventTypeInput_2024_06_14 extends BaseUpdateEventTypeInput { @IsOptional() diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-cancelling.output.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-cancelling.output.ts new file mode 100644 index 0000000000..dfef1a7ef0 --- /dev/null +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-cancelling.output.ts @@ -0,0 +1,15 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; +import { IsBoolean, IsOptional } from "class-validator"; + +export class DisableCancellingOutput_2024_06_14 { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + description: "If true, cancelling is always disabled for this event type.", + example: true, + }) + disabled?: boolean; + + // Note: minutesBefore can be added later when the feature is implemented for cancelling +} + diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-rescheduling.output.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-rescheduling.output.ts new file mode 100644 index 0000000000..15577d541a --- /dev/null +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/disable-rescheduling.output.ts @@ -0,0 +1,23 @@ +import { ApiPropertyOptional } from "@nestjs/swagger"; +import { IsBoolean, IsInt, IsOptional, Min } from "class-validator"; + +export class DisableReschedulingOutput_2024_06_14 { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + description: "If true, rescheduling is always disabled for this event type.", + example: true, + }) + disabled?: boolean; + + @IsOptional() + @IsInt() + @Min(1) + @ApiPropertyOptional({ + description: + "Rescheduling is disabled when less than the specified number of minutes before the meeting.", + example: 60, + }) + minutesBefore?: number; +} + diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts index 175f22402e..04efab7be6 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts @@ -59,6 +59,8 @@ import { UrlFieldOutput_2024_06_14, } from "../outputs/booking-fields.output"; import { BookerActiveBookingsLimitOutput_2024_06_14 } from "./booker-active-bookings-limit.output"; +import { DisableCancellingOutput_2024_06_14 } from "./disable-cancelling.output"; +import { DisableReschedulingOutput_2024_06_14 } from "./disable-rescheduling.output"; import type { OutputBookingField_2024_06_14 } from "./booking-fields.output"; import { ValidateOutputBookingFields_2024_06_14 } from "./booking-fields.output"; import type { OutputLocation_2024_06_14 } from "./locations.output"; @@ -461,6 +463,60 @@ class BaseEventTypeOutput_2024_06_14 { "Boolean to require authentication for booking this event type via api. If true, only authenticated users who are the event-type owner or org/team admin/owner can book this event type.", }) bookingRequiresAuthentication?: boolean; + + @IsOptional() + @ValidateNested() + @Type(() => DisableCancellingOutput_2024_06_14) + @ApiPropertyOptional({ + type: DisableCancellingOutput_2024_06_14, + description: "Settings for disabling cancelling of this event type.", + }) + disableCancelling?: DisableCancellingOutput_2024_06_14; + + @IsOptional() + @ValidateNested() + @Type(() => DisableReschedulingOutput_2024_06_14) + @ApiPropertyOptional({ + type: DisableReschedulingOutput_2024_06_14, + description: + "Settings for disabling rescheduling of this event type. Can be always disabled or disabled when less than X minutes before the meeting.", + }) + disableRescheduling?: DisableReschedulingOutput_2024_06_14; + + @IsOptional() + @IsString() + @ApiPropertyOptional({ + type: String, + nullable: true, + description: "Set preferred language for the booking interface.", + }) + interfaceLanguage?: string | null; + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + description: "Enabling this option allows for past events to be rescheduled.", + }) + allowReschedulingPastBookings?: boolean; + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + type: Boolean, + nullable: true, + description: + "When enabled, users will be able to create a new booking when trying to reschedule a cancelled booking.", + }) + allowReschedulingCancelledBookings?: boolean | null; + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ + type: Boolean, + nullable: true, + description: "Arrange time slots to optimize availability.", + }) + showOptimizedSlots?: boolean | null; } export class TeamEventTypeResponseHost extends TeamEventTypeHostInput { diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/index.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/index.ts index 06fbdb43b0..8a1480b719 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/outputs/index.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/index.ts @@ -1,3 +1,5 @@ export * from "./event-type.output"; export * from "./booking-fields.output"; export * from "./locations.output"; +export * from "./disable-rescheduling.output"; +export * from "./disable-cancelling.output";