feat: extend api/v2/event-types (#16128)
* feat: extended api/v2/event-types to add more attributes - additional attributes added * bookingLimits * onlyShowFirstAvailableSlot * durationLimits * offsetStart * bookingWindow * add swagger docs * type fix * extend api/v2/teams/[teamId]/event-types * added tests * extend api/v2/orgs/[orgId]/teams/[teamid]/event-types * update: added tests to get and update event-type as well * rename variables - bookingLimits -> bookingLimitsCount - durationLimits -> bookingLimitsDuration * refactor: rename bookingLimits and durationLimits, add descriptions - Renamed `bookingLimits` to `bookingLimitsCount` - Renamed `durationLimits` to `bookingLimitsDuration` - Added descriptions with examples to `bookingLimitsCount` and `bookingLimitsDuration` * feat: add unit tests for transformation logic in api-request and api-response - Added tests for `transformApiEventTypeIntervalLimits` - Added tests for `transformApiEventTypeFutureBookingLimits` * fix: type errors * feat: added custom validators for BookingLimitsCount and BookingLimitsDuration * fix: unit-tests * Update CHANGELOG.md * refactor: update imports to use platform-libraries from @calcom/platform-libraries-1.2.3 * fix: prevent double transformation of bookingWindow and bookingFields - resolving e2e test failures --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.27",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.28",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
+61
-1
@@ -26,6 +26,7 @@ import {
|
||||
EventTypeOutput_2024_06_14,
|
||||
UpdateEventTypeInput_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import { BookingWindowPeriodInputTypeEnum_2024_06_14 } from "@calcom/platform-types/dist/event-types/event-types_2024_06_14/inputs/enums/booking-window.enum";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
describe("Event types Endpoints", () => {
|
||||
@@ -214,6 +215,21 @@ describe("Event types Endpoints", () => {
|
||||
},
|
||||
],
|
||||
scheduleId: firstSchedule.id,
|
||||
bookingLimitsCount: {
|
||||
day: 2,
|
||||
week: 5,
|
||||
},
|
||||
onlyShowFirstAvailableSlot: true,
|
||||
bookingLimitsDuration: {
|
||||
day: 60,
|
||||
week: 100,
|
||||
},
|
||||
offsetStart: 30,
|
||||
bookingWindow: {
|
||||
type: BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays,
|
||||
value: 30,
|
||||
rolling: true,
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
@@ -232,7 +248,11 @@ describe("Event types Endpoints", () => {
|
||||
expect(createdEventType.bookingFields).toEqual(body.bookingFields);
|
||||
expect(createdEventType.ownerId).toEqual(user.id);
|
||||
expect(createdEventType.scheduleId).toEqual(firstSchedule.id);
|
||||
|
||||
expect(createdEventType.bookingLimitsCount).toEqual(body.bookingLimitsCount);
|
||||
expect(createdEventType.onlyShowFirstAvailableSlot).toEqual(body.onlyShowFirstAvailableSlot);
|
||||
expect(createdEventType.bookingLimitsDuration).toEqual(body.bookingLimitsDuration);
|
||||
expect(createdEventType.offsetStart).toEqual(body.offsetStart);
|
||||
expect(createdEventType.bookingWindow).toEqual(body.bookingWindow);
|
||||
eventType = responseBody.data;
|
||||
});
|
||||
});
|
||||
@@ -243,6 +263,21 @@ describe("Event types Endpoints", () => {
|
||||
const body: UpdateEventTypeInput_2024_06_14 = {
|
||||
title: newTitle,
|
||||
scheduleId: secondSchedule.id,
|
||||
bookingLimitsCount: {
|
||||
day: 4,
|
||||
week: 10,
|
||||
},
|
||||
onlyShowFirstAvailableSlot: true,
|
||||
bookingLimitsDuration: {
|
||||
day: 100,
|
||||
week: 200,
|
||||
},
|
||||
offsetStart: 50,
|
||||
bookingWindow: {
|
||||
type: BookingWindowPeriodInputTypeEnum_2024_06_14.businessDays,
|
||||
value: 40,
|
||||
rolling: false,
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
@@ -263,9 +298,19 @@ describe("Event types Endpoints", () => {
|
||||
expect(updatedEventType.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(updatedEventType.ownerId).toEqual(user.id);
|
||||
expect(updatedEventType.scheduleId).toEqual(secondSchedule.id);
|
||||
expect(updatedEventType.bookingLimitsCount).toEqual(body.bookingLimitsCount);
|
||||
expect(updatedEventType.onlyShowFirstAvailableSlot).toEqual(body.onlyShowFirstAvailableSlot);
|
||||
expect(updatedEventType.bookingLimitsDuration).toEqual(body.bookingLimitsDuration);
|
||||
expect(updatedEventType.offsetStart).toEqual(body.offsetStart);
|
||||
expect(updatedEventType.bookingWindow).toEqual(body.bookingWindow);
|
||||
|
||||
eventType.title = newTitle;
|
||||
eventType.scheduleId = secondSchedule.id;
|
||||
eventType.bookingLimitsCount = updatedEventType.bookingLimitsCount;
|
||||
eventType.onlyShowFirstAvailableSlot = updatedEventType.onlyShowFirstAvailableSlot;
|
||||
eventType.bookingLimitsDuration = updatedEventType.bookingLimitsDuration;
|
||||
eventType.offsetStart = updatedEventType.offsetStart;
|
||||
eventType.bookingWindow = updatedEventType.bookingWindow;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -301,6 +346,11 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType.ownerId).toEqual(user.id);
|
||||
expect(fetchedEventType.bookingLimitsCount).toEqual(eventType.bookingLimitsCount);
|
||||
expect(fetchedEventType.onlyShowFirstAvailableSlot).toEqual(eventType.onlyShowFirstAvailableSlot);
|
||||
expect(fetchedEventType.bookingLimitsDuration).toEqual(eventType.bookingLimitsDuration);
|
||||
expect(fetchedEventType.offsetStart).toEqual(eventType.offsetStart);
|
||||
expect(fetchedEventType.bookingWindow).toEqual(eventType.bookingWindow);
|
||||
});
|
||||
|
||||
it(`/GET/even-types by username`, async () => {
|
||||
@@ -326,6 +376,11 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType?.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType?.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType?.ownerId).toEqual(user.id);
|
||||
expect(fetchedEventType.bookingLimitsCount).toEqual(eventType.bookingLimitsCount);
|
||||
expect(fetchedEventType.onlyShowFirstAvailableSlot).toEqual(eventType.onlyShowFirstAvailableSlot);
|
||||
expect(fetchedEventType.bookingLimitsDuration).toEqual(eventType.bookingLimitsDuration);
|
||||
expect(fetchedEventType.offsetStart).toEqual(eventType.offsetStart);
|
||||
expect(fetchedEventType.bookingWindow).toEqual(eventType.bookingWindow);
|
||||
});
|
||||
|
||||
it(`/GET/event-types by username and eventSlug`, async () => {
|
||||
@@ -346,6 +401,11 @@ describe("Event types Endpoints", () => {
|
||||
expect(fetchedEventType?.locations).toEqual(eventType.locations);
|
||||
expect(fetchedEventType?.bookingFields).toEqual(eventType.bookingFields);
|
||||
expect(fetchedEventType?.ownerId).toEqual(user.id);
|
||||
expect(fetchedEventType.bookingLimitsCount).toEqual(eventType.bookingLimitsCount);
|
||||
expect(fetchedEventType.onlyShowFirstAvailableSlot).toEqual(eventType.onlyShowFirstAvailableSlot);
|
||||
expect(fetchedEventType.bookingLimitsDuration).toEqual(eventType.bookingLimitsDuration);
|
||||
expect(fetchedEventType.offsetStart).toEqual(eventType.offsetStart);
|
||||
expect(fetchedEventType.bookingWindow).toEqual(eventType.bookingWindow);
|
||||
});
|
||||
|
||||
it(`/GET/:id not existing`, async () => {
|
||||
|
||||
@@ -13,7 +13,18 @@ import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
type InputEventTransformed = Omit<
|
||||
CreateEventTypeInput_2024_06_14,
|
||||
"lengthInMinutes" | "locations" | "bookingFields"
|
||||
| "lengthInMinutes"
|
||||
| "locations"
|
||||
| "bookingFields"
|
||||
| "bookingLimitsCount"
|
||||
| "onlyShowFirstAvailableSlot"
|
||||
| "bookingLimitsDuration"
|
||||
| "offsetStart"
|
||||
| "periodType"
|
||||
| "periodDays"
|
||||
| "periodCountCalendarDays"
|
||||
| "periodStartDate"
|
||||
| "periodEndDate"
|
||||
> & {
|
||||
length: number;
|
||||
slug: string;
|
||||
|
||||
+33
-1
@@ -38,7 +38,16 @@ export class EventTypesService_2024_06_14 {
|
||||
async createUserEventType(user: UserWithProfile, body: CreateEventTypeInput_2024_06_14) {
|
||||
await this.checkCanCreateEventType(user.id, body);
|
||||
const eventTypeUser = await this.getUserToCreateEvent(user);
|
||||
const bodyTransformed = this.inputEventTypesService.transformInputCreateEventType(body);
|
||||
const {
|
||||
bookingLimits,
|
||||
durationLimits,
|
||||
periodType = undefined,
|
||||
periodDays = undefined,
|
||||
periodCountCalendarDays = undefined,
|
||||
periodStartDate = undefined,
|
||||
periodEndDate = undefined,
|
||||
...bodyTransformed
|
||||
} = this.inputEventTypesService.transformInputCreateEventType(body);
|
||||
const { eventType: eventTypeCreated } = await createEventType({
|
||||
input: bodyTransformed,
|
||||
ctx: {
|
||||
@@ -49,6 +58,26 @@ export class EventTypesService_2024_06_14 {
|
||||
},
|
||||
});
|
||||
|
||||
await updateEventType({
|
||||
input: {
|
||||
id: eventTypeCreated.id,
|
||||
bookingLimits,
|
||||
durationLimits,
|
||||
periodType,
|
||||
periodDays,
|
||||
periodCountCalendarDays,
|
||||
periodStartDate,
|
||||
periodEndDate,
|
||||
...bodyTransformed,
|
||||
},
|
||||
ctx: {
|
||||
user: eventTypeUser,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
prisma: this.dbWrite.prisma,
|
||||
},
|
||||
});
|
||||
|
||||
const eventType = await this.eventTypesRepository.getEventTypeById(eventTypeCreated.id);
|
||||
|
||||
if (!eventType) {
|
||||
@@ -95,13 +124,16 @@ export class EventTypesService_2024_06_14 {
|
||||
? await this.membershipsRepository.isUserOrganizationAdmin(user.id, organizationId)
|
||||
: false;
|
||||
const profileId = user.movedToProfile?.id || null;
|
||||
const selectedCalendars = await this.selectedCalendarsRepository.getUserSelectedCalendars(user.id);
|
||||
return {
|
||||
id: user.id,
|
||||
role: user.role,
|
||||
username: user.username,
|
||||
organizationId: user.organizationId,
|
||||
organization: { isOrgAdmin },
|
||||
profile: { id: profileId },
|
||||
metadata: user.metadata,
|
||||
selectedCalendars,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+40
-2
@@ -3,6 +3,8 @@ import { Injectable } from "@nestjs/common";
|
||||
import {
|
||||
transformApiEventTypeBookingFields,
|
||||
transformApiEventTypeLocations,
|
||||
transformApiEventTypeIntervalLimits,
|
||||
transformApiEventTypeFutureBookingLimits,
|
||||
} from "@calcom/platform-libraries";
|
||||
import { CreateEventTypeInput_2024_06_14, UpdateEventTypeInput_2024_06_14 } from "@calcom/platform-types";
|
||||
|
||||
@@ -16,20 +18,42 @@ export class InputEventTypesService_2024_06_14 {
|
||||
},
|
||||
];
|
||||
|
||||
const { lengthInMinutes, locations, bookingFields, ...rest } = inputEventType;
|
||||
const {
|
||||
lengthInMinutes,
|
||||
locations,
|
||||
bookingFields,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
...rest
|
||||
} = inputEventType;
|
||||
|
||||
const eventType = {
|
||||
...rest,
|
||||
length: lengthInMinutes,
|
||||
locations: this.transformInputLocations(locations || defaultLocations),
|
||||
bookingFields: this.transformInputBookingFields(bookingFields),
|
||||
bookingLimits: bookingLimitsCount ? this.transformInputIntervalLimits(bookingLimitsCount) : undefined,
|
||||
durationLimits: bookingLimitsDuration
|
||||
? this.transformInputIntervalLimits(bookingLimitsDuration)
|
||||
: undefined,
|
||||
...this.transformInputBookingWindow(bookingWindow),
|
||||
};
|
||||
|
||||
return eventType;
|
||||
}
|
||||
|
||||
transformInputUpdateEventType(inputEventType: UpdateEventTypeInput_2024_06_14) {
|
||||
const { lengthInMinutes, locations, bookingFields, scheduleId, ...rest } = inputEventType;
|
||||
const {
|
||||
lengthInMinutes,
|
||||
locations,
|
||||
bookingFields,
|
||||
scheduleId,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
...rest
|
||||
} = inputEventType;
|
||||
|
||||
const eventType = {
|
||||
...rest,
|
||||
@@ -37,6 +61,11 @@ export class InputEventTypesService_2024_06_14 {
|
||||
locations: locations ? this.transformInputLocations(locations) : undefined,
|
||||
bookingFields: bookingFields ? this.transformInputBookingFields(bookingFields) : undefined,
|
||||
schedule: scheduleId,
|
||||
bookingLimits: bookingLimitsCount ? this.transformInputIntervalLimits(bookingLimitsCount) : undefined,
|
||||
durationLimits: bookingLimitsDuration
|
||||
? this.transformInputIntervalLimits(bookingLimitsDuration)
|
||||
: undefined,
|
||||
...this.transformInputBookingWindow(bookingWindow),
|
||||
};
|
||||
|
||||
return eventType;
|
||||
@@ -49,4 +78,13 @@ export class InputEventTypesService_2024_06_14 {
|
||||
transformInputBookingFields(inputBookingFields: CreateEventTypeInput_2024_06_14["bookingFields"]) {
|
||||
return transformApiEventTypeBookingFields(inputBookingFields);
|
||||
}
|
||||
|
||||
transformInputIntervalLimits(inputBookingFields: CreateEventTypeInput_2024_06_14["bookingLimitsCount"]) {
|
||||
return transformApiEventTypeIntervalLimits(inputBookingFields);
|
||||
}
|
||||
|
||||
transformInputBookingWindow(inputBookingWindow: CreateEventTypeInput_2024_06_14["bookingWindow"]) {
|
||||
const res = transformApiEventTypeFutureBookingLimits(inputBookingWindow);
|
||||
return !!res ? res : {};
|
||||
}
|
||||
}
|
||||
|
||||
+38
@@ -11,7 +11,11 @@ import {
|
||||
BookingFieldsSchema,
|
||||
SystemField,
|
||||
UserField,
|
||||
parseBookingLimit,
|
||||
getResponseEventTypeIntervalLimits,
|
||||
getResponseEventTypeFutureBookingLimits,
|
||||
} from "@calcom/platform-libraries";
|
||||
import { TransformFutureBookingsLimitSchema_2024_06_14 } from "@calcom/platform-types";
|
||||
|
||||
type EventTypeRelations = { users: User[]; schedule: Schedule | null };
|
||||
type DatabaseEventType = EventType & EventTypeRelations;
|
||||
@@ -44,6 +48,15 @@ type Input = Pick<
|
||||
| "metadata"
|
||||
| "users"
|
||||
| "scheduleId"
|
||||
| "bookingLimits"
|
||||
| "durationLimits"
|
||||
| "onlyShowFirstAvailableSlot"
|
||||
| "offsetStart"
|
||||
| "periodType"
|
||||
| "periodDays"
|
||||
| "periodCountCalendarDays"
|
||||
| "periodStartDate"
|
||||
| "periodEndDate"
|
||||
>;
|
||||
|
||||
@Injectable()
|
||||
@@ -71,6 +84,8 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
seatsShowAvailabilityCount,
|
||||
isInstantEvent,
|
||||
scheduleId,
|
||||
onlyShowFirstAvailableSlot,
|
||||
offsetStart,
|
||||
} = databaseEventType;
|
||||
|
||||
const locations = this.transformLocations(databaseEventType.locations);
|
||||
@@ -80,6 +95,15 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
const recurringEvent = this.transformRecurringEvent(databaseEventType.recurringEvent);
|
||||
const metadata = this.transformMetadata(databaseEventType.metadata) || {};
|
||||
const users = this.transformUsers(databaseEventType.users);
|
||||
const bookingLimitsCount = this.transformIntervalLimits(databaseEventType.bookingLimits);
|
||||
const bookingLimitsDuration = this.transformIntervalLimits(databaseEventType.durationLimits);
|
||||
const bookingWindow = this.transformBookingWindow({
|
||||
periodType: databaseEventType.periodType,
|
||||
periodDays: databaseEventType.periodDays,
|
||||
periodCountCalendarDays: databaseEventType.periodCountCalendarDays,
|
||||
periodStartDate: databaseEventType.periodStartDate,
|
||||
periodEndDate: databaseEventType.periodEndDate,
|
||||
} as TransformFutureBookingsLimitSchema_2024_06_14);
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -109,6 +133,11 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
isInstantEvent,
|
||||
users,
|
||||
scheduleId,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
onlyShowFirstAvailableSlot,
|
||||
offsetStart,
|
||||
bookingWindow,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,4 +177,13 @@ export class OutputEventTypesService_2024_06_14 {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
transformIntervalLimits(bookingLimits: any) {
|
||||
const bookingLimitsParsed = parseBookingLimit(bookingLimits);
|
||||
return getResponseEventTypeIntervalLimits(bookingLimitsParsed);
|
||||
}
|
||||
|
||||
transformBookingWindow(bookingLimits: TransformFutureBookingsLimitSchema_2024_06_14) {
|
||||
return getResponseEventTypeFutureBookingLimits(bookingLimits);
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -24,6 +24,7 @@ import {
|
||||
TeamEventTypeOutput_2024_06_14,
|
||||
UpdateTeamEventTypeInput_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import { BookingWindowPeriodInputTypeEnum_2024_06_14 } from "@calcom/platform-types/event-types/event-types_2024_06_14/inputs/enums/booking-window.enum";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Organizations Event Types Endpoints", () => {
|
||||
@@ -260,6 +261,21 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
userId: teammate2.id,
|
||||
},
|
||||
],
|
||||
bookingLimitsCount: {
|
||||
day: 2,
|
||||
week: 5,
|
||||
},
|
||||
onlyShowFirstAvailableSlot: true,
|
||||
bookingLimitsDuration: {
|
||||
day: 60,
|
||||
week: 100,
|
||||
},
|
||||
offsetStart: 30,
|
||||
bookingWindow: {
|
||||
type: BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays,
|
||||
value: 30,
|
||||
rolling: true,
|
||||
},
|
||||
};
|
||||
|
||||
return request(app.getHttpServer())
|
||||
@@ -276,6 +292,11 @@ describe("Organizations Event Types Endpoints", () => {
|
||||
expect(data.schedulingType).toEqual("COLLECTIVE");
|
||||
evaluateHost(body.hosts[0], data.hosts[0]);
|
||||
evaluateHost(body.hosts[1], data.hosts[1]);
|
||||
expect(data.bookingLimitsCount).toEqual(body.bookingLimitsCount);
|
||||
expect(data.onlyShowFirstAvailableSlot).toEqual(body.onlyShowFirstAvailableSlot);
|
||||
expect(data.bookingLimitsDuration).toEqual(body.bookingLimitsDuration);
|
||||
expect(data.offsetStart).toEqual(body.offsetStart);
|
||||
expect(data.bookingWindow).toEqual(body.bookingWindow);
|
||||
|
||||
collectiveEventType = responseBody.data;
|
||||
});
|
||||
|
||||
@@ -23,7 +23,15 @@ export class InputOrganizationsEventTypesService {
|
||||
teamId: number,
|
||||
inputEventType: CreateTeamEventTypeInput_2024_06_14
|
||||
) {
|
||||
const { hosts, assignAllTeamMembers, ...rest } = inputEventType;
|
||||
const {
|
||||
hosts,
|
||||
assignAllTeamMembers,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
bookingFields,
|
||||
...rest
|
||||
} = inputEventType;
|
||||
|
||||
const eventType = this.inputEventTypesService.transformInputCreateEventType(rest);
|
||||
|
||||
@@ -35,6 +43,10 @@ export class InputOrganizationsEventTypesService {
|
||||
? await this.getAllTeamMembers(teamId, inputEventType.schedulingType)
|
||||
: this.transformInputHosts(hosts, inputEventType.schedulingType),
|
||||
assignAllTeamMembers,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
bookingFields,
|
||||
metadata,
|
||||
};
|
||||
|
||||
|
||||
+21
-5
@@ -36,11 +36,19 @@ export class OrganizationsEventTypesService {
|
||||
) {
|
||||
await this.validateHosts(teamId, body.hosts);
|
||||
const eventTypeUser = await this.getUserToCreateTeamEvent(user, orgId);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { hosts, assignAllTeamMembers, ...rest } =
|
||||
await this.inputService.transformInputCreateTeamEventType(teamId, body);
|
||||
const {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
hosts,
|
||||
assignAllTeamMembers,
|
||||
locations,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
bookingFields,
|
||||
...rest
|
||||
} = await this.inputService.transformInputCreateTeamEventType(teamId, body);
|
||||
const { eventType: eventTypeCreated } = await createEventType({
|
||||
input: { teamId: teamId, ...rest },
|
||||
input: { teamId: teamId, locations, ...rest },
|
||||
ctx: {
|
||||
user: eventTypeUser,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
@@ -52,7 +60,15 @@ export class OrganizationsEventTypesService {
|
||||
return await this.updateTeamEventType(
|
||||
eventTypeCreated.id,
|
||||
teamId,
|
||||
{ hosts: body.hosts, assignAllTeamMembers },
|
||||
{
|
||||
hosts: body.hosts,
|
||||
assignAllTeamMembers,
|
||||
bookingLimitsCount,
|
||||
bookingLimitsDuration,
|
||||
bookingWindow,
|
||||
bookingFields,
|
||||
...rest,
|
||||
},
|
||||
user
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,15 @@ type Input = Pick<
|
||||
| "userId"
|
||||
| "parentId"
|
||||
| "assignAllTeamMembers"
|
||||
| "bookingLimits"
|
||||
| "durationLimits"
|
||||
| "onlyShowFirstAvailableSlot"
|
||||
| "offsetStart"
|
||||
| "periodType"
|
||||
| "periodDays"
|
||||
| "periodCountCalendarDays"
|
||||
| "periodStartDate"
|
||||
| "periodEndDate"
|
||||
>;
|
||||
|
||||
@Injectable()
|
||||
|
||||
@@ -6631,33 +6631,6 @@
|
||||
"type": "string",
|
||||
"example": "Discover the culinary wonders of the Argentina by making the best flan ever!"
|
||||
},
|
||||
"locations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"bookingFields": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"disableGuests": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"slotInterval": {
|
||||
"type": "number"
|
||||
},
|
||||
"minimumBookingNotice": {
|
||||
"type": "number"
|
||||
},
|
||||
"beforeEventBuffer": {
|
||||
"type": "number"
|
||||
},
|
||||
"afterEventBuffer": {
|
||||
"type": "number"
|
||||
},
|
||||
"schedulingType": {
|
||||
"type": "object"
|
||||
},
|
||||
@@ -6675,13 +6648,6 @@
|
||||
"lengthInMinutes",
|
||||
"title",
|
||||
"description",
|
||||
"locations",
|
||||
"bookingFields",
|
||||
"disableGuests",
|
||||
"slotInterval",
|
||||
"minimumBookingNotice",
|
||||
"beforeEventBuffer",
|
||||
"afterEventBuffer",
|
||||
"schedulingType",
|
||||
"hosts",
|
||||
"assignAllTeamMembers"
|
||||
@@ -6779,6 +6745,64 @@
|
||||
"userId"
|
||||
]
|
||||
},
|
||||
"BookingLimitsCount_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"description": "The number of bookings per day",
|
||||
"example": 1
|
||||
},
|
||||
"week": {
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"description": "The number of bookings per week",
|
||||
"example": 2
|
||||
},
|
||||
"month": {
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"description": "The number of bookings per month",
|
||||
"example": 3
|
||||
},
|
||||
"year": {
|
||||
"type": "number",
|
||||
"minimum": 1,
|
||||
"description": "The number of bookings per year",
|
||||
"example": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"BookingLimitsDuration_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"day": {
|
||||
"type": "number",
|
||||
"minimum": 15,
|
||||
"description": "The duration of bookings per day (must be a multiple of 15)",
|
||||
"example": 60
|
||||
},
|
||||
"week": {
|
||||
"type": "number",
|
||||
"minimum": 15,
|
||||
"description": "The duration of bookings per week (must be a multiple of 15)",
|
||||
"example": 120
|
||||
},
|
||||
"month": {
|
||||
"type": "number",
|
||||
"minimum": 15,
|
||||
"description": "The duration of bookings per month (must be a multiple of 15)",
|
||||
"example": 180
|
||||
},
|
||||
"year": {
|
||||
"type": "number",
|
||||
"minimum": 15,
|
||||
"description": "The duration of bookings per year (must be a multiple of 15)",
|
||||
"example": 240
|
||||
}
|
||||
}
|
||||
},
|
||||
"TeamEventTypeOutput_2024_06_14": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6898,6 +6922,22 @@
|
||||
},
|
||||
"assignAllTeamMembers": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bookingLimitsCount": {
|
||||
"$ref": "#/components/schemas/BookingLimitsCount_2024_06_14"
|
||||
},
|
||||
"onlyShowFirstAvailableSlot": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bookingLimitsDuration": {
|
||||
"$ref": "#/components/schemas/BookingLimitsDuration_2024_06_14"
|
||||
},
|
||||
"bookingWindow": {
|
||||
"type": "object"
|
||||
},
|
||||
"offsetStart": {
|
||||
"type": "number",
|
||||
"minimum": 1
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { BookingField_2024_06_14, Location_2024_06_14 } from "@calcom/platform-types";
|
||||
import type {
|
||||
BookingField_2024_06_14,
|
||||
Location_2024_06_14,
|
||||
BookingLimitsCount_2024_06_14,
|
||||
BookingWindow_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
|
||||
import type { UserField, OptionsField } from "./api-request";
|
||||
import type { UserField } from "./api-request";
|
||||
import {
|
||||
transformApiEventTypeLocations,
|
||||
transformApiEventTypeBookingFields,
|
||||
transformSelectOptions,
|
||||
transformApiEventTypeIntervalLimits,
|
||||
transformApiEventTypeFutureBookingLimits,
|
||||
} from "./api-request";
|
||||
|
||||
describe("transformApiEventTypeLocations", () => {
|
||||
@@ -336,7 +343,7 @@ describe("transformApiEventTypeBookingFields", () => {
|
||||
|
||||
const input: BookingField_2024_06_14[] = [bookingField];
|
||||
|
||||
const expectedOutput: OptionsField[] = [
|
||||
const expectedOutput: UserField[] = [
|
||||
{
|
||||
name: bookingField.slug,
|
||||
type: bookingField.type,
|
||||
@@ -372,7 +379,7 @@ describe("transformApiEventTypeBookingFields", () => {
|
||||
|
||||
const input: BookingField_2024_06_14[] = [bookingField];
|
||||
|
||||
const expectedOutput: OptionsField[] = [
|
||||
const expectedOutput: UserField[] = [
|
||||
{
|
||||
name: bookingField.slug,
|
||||
type: bookingField.type,
|
||||
@@ -443,7 +450,7 @@ describe("transformApiEventTypeBookingFields", () => {
|
||||
|
||||
const input: BookingField_2024_06_14[] = [bookingField];
|
||||
|
||||
const expectedOutput: OptionsField[] = [
|
||||
const expectedOutput: UserField[] = [
|
||||
{
|
||||
name: bookingField.slug,
|
||||
type: bookingField.type,
|
||||
@@ -479,7 +486,7 @@ describe("transformApiEventTypeBookingFields", () => {
|
||||
|
||||
const input: BookingField_2024_06_14[] = [bookingField];
|
||||
|
||||
const expectedOutput: OptionsField[] = [
|
||||
const expectedOutput: UserField[] = [
|
||||
{
|
||||
name: bookingField.slug,
|
||||
type: bookingField.type,
|
||||
@@ -538,3 +545,111 @@ describe("transformApiEventTypeBookingFields", () => {
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("transformApiEventTypeIntervalLimits", () => {
|
||||
it("should transform booking limits count or booking limits duration", () => {
|
||||
const input: BookingLimitsCount_2024_06_14 = {
|
||||
day: 2,
|
||||
week: 11,
|
||||
month: 22,
|
||||
year: 33,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
PER_DAY: 2,
|
||||
PER_WEEK: 11,
|
||||
PER_MONTH: 22,
|
||||
PER_YEAR: 33,
|
||||
};
|
||||
const result = transformApiEventTypeIntervalLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("transformApiEventTypeFutureBookingLimits", () => {
|
||||
it("should transform range type", () => {
|
||||
const input: BookingWindow_2024_06_14 = {
|
||||
type: "range",
|
||||
value: ["2024-08-06", "2024-08-28"],
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
periodType: "RANGE",
|
||||
periodStartDate: new Date("2024-08-06"),
|
||||
periodEndDate: new Date("2024-08-28"),
|
||||
};
|
||||
|
||||
const result = transformApiEventTypeFutureBookingLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should transform calendar days", () => {
|
||||
const input: BookingWindow_2024_06_14 = {
|
||||
type: "calendarDays",
|
||||
value: 30,
|
||||
rolling: false,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
periodType: "ROLLING",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: true,
|
||||
};
|
||||
|
||||
const result = transformApiEventTypeFutureBookingLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should transform calendar days rolling-window", () => {
|
||||
const input: BookingWindow_2024_06_14 = {
|
||||
type: "calendarDays",
|
||||
value: 30,
|
||||
rolling: true,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
periodType: "ROLLING_WINDOW",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: true,
|
||||
};
|
||||
|
||||
const result = transformApiEventTypeFutureBookingLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should transform Business days", () => {
|
||||
const input: BookingWindow_2024_06_14 = {
|
||||
type: "businessDays",
|
||||
value: 30,
|
||||
rolling: false,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
periodType: "ROLLING",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: false,
|
||||
};
|
||||
|
||||
const result = transformApiEventTypeFutureBookingLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should transform Business days rolling-window", () => {
|
||||
const input: BookingWindow_2024_06_14 = {
|
||||
type: "businessDays",
|
||||
value: 30,
|
||||
rolling: true,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
periodType: "ROLLING_WINDOW",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: false,
|
||||
};
|
||||
|
||||
const result = transformApiEventTypeFutureBookingLimits(input);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import type { CreateEventTypeInput_2024_06_14, Integration_2024_06_14 } from "@calcom/platform-types";
|
||||
import type {
|
||||
BookingLimitsKeyOutputType_2024_06_14,
|
||||
TransformBookingLimitsSchema_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import {
|
||||
type CreateEventTypeInput_2024_06_14,
|
||||
type Integration_2024_06_14,
|
||||
type BusinessDaysWindow_2024_06_14,
|
||||
type RangeWindow_2024_06_14,
|
||||
type TransformFutureBookingsLimitSchema_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import {
|
||||
BookingWindowPeriodInputTypeEnum_2024_06_14,
|
||||
BookingWindowPeriodOutputTypeEnum_2024_06_14,
|
||||
} from "@calcom/platform-types/event-types/event-types_2024_06_14/inputs/enums/booking-window.enum";
|
||||
import { BookingLimitsEnum_2024_06_14 } from "@calcom/platform-types/event-types/event-types_2024_06_14/inputs/enums/interval-limits.enum";
|
||||
|
||||
const integrationsMapping: Record<Integration_2024_06_14, string> = {
|
||||
"cal-video": "integrations:daily",
|
||||
@@ -102,6 +117,51 @@ function transformApiEventTypeBookingFields(
|
||||
return customBookingFields;
|
||||
}
|
||||
|
||||
function transformApiEventTypeIntervalLimits(
|
||||
inputBookingLimits: CreateEventTypeInput_2024_06_14["bookingLimitsCount"]
|
||||
) {
|
||||
const res: TransformBookingLimitsSchema_2024_06_14 = {};
|
||||
inputBookingLimits &&
|
||||
Object.entries(inputBookingLimits).map(([key, value]) => {
|
||||
const outputKey: BookingLimitsKeyOutputType_2024_06_14 = BookingLimitsEnum_2024_06_14[
|
||||
key as keyof typeof BookingLimitsEnum_2024_06_14
|
||||
] as BookingLimitsKeyOutputType_2024_06_14;
|
||||
res[outputKey] = value;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
function transformApiEventTypeFutureBookingLimits(
|
||||
inputBookingLimits: CreateEventTypeInput_2024_06_14["bookingWindow"]
|
||||
): TransformFutureBookingsLimitSchema_2024_06_14 | undefined {
|
||||
switch (inputBookingLimits?.type) {
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.businessDays:
|
||||
return {
|
||||
periodDays: (inputBookingLimits as BusinessDaysWindow_2024_06_14).value,
|
||||
periodType: !!(inputBookingLimits as BusinessDaysWindow_2024_06_14).rolling
|
||||
? BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING_WINDOW
|
||||
: BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING,
|
||||
periodCountCalendarDays: false,
|
||||
};
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays:
|
||||
return {
|
||||
periodDays: (inputBookingLimits as BusinessDaysWindow_2024_06_14).value,
|
||||
periodType: !!(inputBookingLimits as BusinessDaysWindow_2024_06_14).rolling
|
||||
? BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING_WINDOW
|
||||
: BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING,
|
||||
periodCountCalendarDays: true,
|
||||
};
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.range:
|
||||
return {
|
||||
periodType: BookingWindowPeriodOutputTypeEnum_2024_06_14.RANGE,
|
||||
periodStartDate: new Date((inputBookingLimits as RangeWindow_2024_06_14).value[0]),
|
||||
periodEndDate: new Date((inputBookingLimits as RangeWindow_2024_06_14).value[1]),
|
||||
};
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function transformSelectOptions(options: string[]) {
|
||||
return options.map((option) => ({
|
||||
label: option,
|
||||
@@ -199,4 +259,9 @@ export type UserField = z.infer<typeof UserFieldsSchema>;
|
||||
|
||||
export const BookingFieldsSchema = z.array(z.union([UserFieldsSchema, SystemFieldsSchema]));
|
||||
|
||||
export { transformApiEventTypeLocations, transformApiEventTypeBookingFields };
|
||||
export {
|
||||
transformApiEventTypeLocations,
|
||||
transformApiEventTypeBookingFields,
|
||||
transformApiEventTypeIntervalLimits,
|
||||
transformApiEventTypeFutureBookingLimits,
|
||||
};
|
||||
|
||||
@@ -5,10 +5,17 @@ import type {
|
||||
LinkLocation_2024_06_14,
|
||||
PhoneLocation_2024_06_14,
|
||||
IntegrationLocation_2024_06_14,
|
||||
TransformBookingLimitsSchema_2024_06_14,
|
||||
TransformFutureBookingsLimitSchema_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
|
||||
import type { UserField, OptionsField } from "./api-request";
|
||||
import { getResponseEventTypeLocations, getResponseEventTypeBookingFields } from "./api-response";
|
||||
import type { UserField } from "./api-request";
|
||||
import {
|
||||
getResponseEventTypeLocations,
|
||||
getResponseEventTypeBookingFields,
|
||||
getResponseEventTypeIntervalLimits,
|
||||
getResponseEventTypeFutureBookingLimits,
|
||||
} from "./api-response";
|
||||
|
||||
describe("getResponseEventTypeLocations", () => {
|
||||
it("should reverse transform address location", () => {
|
||||
@@ -344,7 +351,7 @@ describe("getResponseEventTypeBookingFields", () => {
|
||||
});
|
||||
|
||||
it("should reverse transform select field", () => {
|
||||
const transformedField: OptionsField[] = [
|
||||
const transformedField: UserField[] = [
|
||||
{
|
||||
name: "your-select",
|
||||
type: "select",
|
||||
@@ -384,7 +391,7 @@ describe("getResponseEventTypeBookingFields", () => {
|
||||
});
|
||||
|
||||
it("should reverse transform multiselect field", () => {
|
||||
const transformedField: OptionsField[] = [
|
||||
const transformedField: UserField[] = [
|
||||
{
|
||||
name: "your-multiselect",
|
||||
type: "multiselect",
|
||||
@@ -457,7 +464,7 @@ describe("getResponseEventTypeBookingFields", () => {
|
||||
});
|
||||
|
||||
it("should reverse transform checkbox field", () => {
|
||||
const transformedField: OptionsField[] = [
|
||||
const transformedField: UserField[] = [
|
||||
{
|
||||
name: "your-checkbox",
|
||||
type: "checkbox",
|
||||
@@ -495,7 +502,7 @@ describe("getResponseEventTypeBookingFields", () => {
|
||||
});
|
||||
|
||||
it("should reverse transform radio field", () => {
|
||||
const transformedField: OptionsField[] = [
|
||||
const transformedField: UserField[] = [
|
||||
{
|
||||
name: "your-radio",
|
||||
type: "radio",
|
||||
@@ -566,3 +573,109 @@ describe("getResponseEventTypeBookingFields", () => {
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("transformApiEventTypeIntervalLimits", () => {
|
||||
it("should reverse transform booking limits count or booking limits duration", () => {
|
||||
const transformedField: TransformBookingLimitsSchema_2024_06_14 = {
|
||||
PER_DAY: 2,
|
||||
PER_WEEK: 11,
|
||||
PER_MONTH: 22,
|
||||
PER_YEAR: 33,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
day: 2,
|
||||
week: 11,
|
||||
month: 22,
|
||||
year: 33,
|
||||
};
|
||||
const result = getResponseEventTypeIntervalLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("transformApiEventTypeFutureBookingLimits", () => {
|
||||
it("should reverse transform range type", () => {
|
||||
const transformedField: TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: "RANGE",
|
||||
periodStartDate: new Date("2024-08-06T09:14:30.000Z"),
|
||||
periodEndDate: new Date("2024-08-28T18:30:00.000Z"),
|
||||
};
|
||||
const expectedOutput = {
|
||||
type: "range",
|
||||
value: ["2024-08-06", "2024-08-28"],
|
||||
};
|
||||
|
||||
const result = getResponseEventTypeFutureBookingLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should reverse transform calendar days", () => {
|
||||
const transformedField: TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: "ROLLING",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: true,
|
||||
};
|
||||
const expectedOutput = {
|
||||
type: "calendarDays",
|
||||
value: 30,
|
||||
rolling: false,
|
||||
};
|
||||
|
||||
const result = getResponseEventTypeFutureBookingLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should reverse transform calendar days rolling-window", () => {
|
||||
const transformedField: TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: "ROLLING_WINDOW",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: true,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
type: "calendarDays",
|
||||
value: 30,
|
||||
rolling: true,
|
||||
};
|
||||
|
||||
const result = getResponseEventTypeFutureBookingLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should reverse transform Business days", () => {
|
||||
const transformedField: TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: "ROLLING",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: false,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
type: "businessDays",
|
||||
value: 30,
|
||||
rolling: false,
|
||||
};
|
||||
|
||||
const result = getResponseEventTypeFutureBookingLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
it("should reverse transform Business days rolling-window", () => {
|
||||
const transformedField: TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: "ROLLING_WINDOW",
|
||||
periodDays: 30,
|
||||
periodCountCalendarDays: false,
|
||||
};
|
||||
|
||||
const expectedOutput = {
|
||||
type: "businessDays",
|
||||
value: 30,
|
||||
rolling: true,
|
||||
};
|
||||
|
||||
const result = getResponseEventTypeFutureBookingLimits(transformedField);
|
||||
|
||||
expect(result).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,8 +4,20 @@ import type {
|
||||
LinkLocation_2024_06_14,
|
||||
PhoneLocation_2024_06_14,
|
||||
Integration_2024_06_14,
|
||||
BookingLimitsKeysInputType,
|
||||
TransformBookingLimitsSchema_2024_06_14,
|
||||
TransformFutureBookingsLimitSchema_2024_06_14,
|
||||
BookingWindow_2024_06_14,
|
||||
RangeWindow_2024_06_14,
|
||||
CalendarDaysWindow_2024_06_14,
|
||||
BusinessDaysWindow_2024_06_14,
|
||||
BookingField_2024_06_14,
|
||||
} from "@calcom/platform-types";
|
||||
import {
|
||||
BookingWindowPeriodInputTypeEnum_2024_06_14,
|
||||
BookingWindowPeriodOutputTypeEnum_2024_06_14,
|
||||
} from "@calcom/platform-types/event-types/event-types_2024_06_14/inputs/enums/booking-window.enum";
|
||||
import { BookingLimitsEnum_2024_06_14 } from "@calcom/platform-types/event-types/event-types_2024_06_14/inputs/enums/interval-limits.enum";
|
||||
|
||||
import type { transformApiEventTypeBookingFields, transformApiEventTypeLocations } from "./api-request";
|
||||
|
||||
@@ -189,4 +201,63 @@ function getResponseEventTypeBookingFields(
|
||||
});
|
||||
}
|
||||
|
||||
export { getResponseEventTypeLocations, getResponseEventTypeBookingFields };
|
||||
function getResponseEventTypeIntervalLimits(
|
||||
transformedBookingFields: TransformBookingLimitsSchema_2024_06_14 | null
|
||||
) {
|
||||
if (!transformedBookingFields) {
|
||||
return undefined;
|
||||
}
|
||||
const res: { [K in BookingLimitsKeysInputType]?: number } = {};
|
||||
transformedBookingFields &&
|
||||
Object.entries(transformedBookingFields).map(([key, value]) => {
|
||||
const outputKey: BookingLimitsKeysInputType | undefined = Object.keys(
|
||||
BookingLimitsEnum_2024_06_14
|
||||
).find(
|
||||
(item) => BookingLimitsEnum_2024_06_14[item as keyof typeof BookingLimitsEnum_2024_06_14] === key
|
||||
) as BookingLimitsKeysInputType;
|
||||
|
||||
if (outputKey) {
|
||||
res[outputKey] = value as number;
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
function getResponseEventTypeFutureBookingLimits(
|
||||
transformedFutureBookingsLimitsFields: TransformFutureBookingsLimitSchema_2024_06_14
|
||||
): BookingWindow_2024_06_14 | undefined {
|
||||
switch (transformedFutureBookingsLimitsFields?.periodType) {
|
||||
case BookingWindowPeriodOutputTypeEnum_2024_06_14.RANGE:
|
||||
return {
|
||||
type: BookingWindowPeriodInputTypeEnum_2024_06_14.range,
|
||||
value: [
|
||||
transformedFutureBookingsLimitsFields?.periodStartDate?.toISOString().split("T")[0],
|
||||
transformedFutureBookingsLimitsFields?.periodEndDate?.toISOString().split("T")[0],
|
||||
],
|
||||
} as RangeWindow_2024_06_14;
|
||||
case BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING_WINDOW:
|
||||
return {
|
||||
type: transformedFutureBookingsLimitsFields.periodCountCalendarDays
|
||||
? BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays
|
||||
: BookingWindowPeriodInputTypeEnum_2024_06_14.businessDays,
|
||||
value: transformedFutureBookingsLimitsFields.periodDays,
|
||||
rolling: true,
|
||||
} as CalendarDaysWindow_2024_06_14 | BusinessDaysWindow_2024_06_14;
|
||||
case BookingWindowPeriodOutputTypeEnum_2024_06_14.ROLLING:
|
||||
return {
|
||||
type: transformedFutureBookingsLimitsFields.periodCountCalendarDays
|
||||
? BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays
|
||||
: BookingWindowPeriodInputTypeEnum_2024_06_14.businessDays,
|
||||
value: transformedFutureBookingsLimitsFields.periodDays,
|
||||
rolling: false,
|
||||
} as CalendarDaysWindow_2024_06_14 | BusinessDaysWindow_2024_06_14;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
export {
|
||||
getResponseEventTypeLocations,
|
||||
getResponseEventTypeBookingFields,
|
||||
getResponseEventTypeIntervalLimits,
|
||||
getResponseEventTypeFutureBookingLimits,
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import type { BookerProps } from "@calcom/features/bookings/Booker";
|
||||
import { getFieldIdentifier } from "@calcom/features/form-builder/utils/getFieldIdentifier";
|
||||
import { defaultEvents } from "@calcom/lib/defaultEvents";
|
||||
import type { CommonField, OptionsField, SystemField } from "@calcom/lib/event-types/transformers";
|
||||
import type { UserField, SystemField } from "@calcom/lib/event-types/transformers";
|
||||
import {
|
||||
transformApiEventTypeLocations,
|
||||
transformApiEventTypeBookingFields,
|
||||
@@ -210,7 +210,7 @@ function getLocations(locations: EventTypeOutput_2024_06_14["locations"]) {
|
||||
}
|
||||
|
||||
function getBookingFields(bookingFields: EventTypeOutput_2024_06_14["bookingFields"]) {
|
||||
const transformedBookingFields: (CommonField | SystemField | OptionsField)[] =
|
||||
const transformedBookingFields: (SystemField | UserField)[] =
|
||||
transformApiEventTypeBookingFields(bookingFields);
|
||||
|
||||
// These fields should be added before other user fields
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 0.0.28
|
||||
• Feature: Added support for new event-type limits in the API.
|
||||
• Introduced the transformApiEventTypeFutureBookingLimits translator in packages/lib/event-types/transformers/api-request.ts. This enables the “Limit future bookings” feature in the event-type API.
|
||||
• Introduced the transformApiEventTypeIntervalLimits translator in packages/lib/event-types/transformers/api-request.ts. This allows the “Limit total booking duration” and “Limit booking frequency” features in the event-type API.
|
||||
• Added getResponseEventTypeIntervalLimits translator in packages/lib/event-types/transformers/api-response.ts to return data in a more human-friendly format.
|
||||
• Added getResponseEventTypeFutureBookingLimits translator in packages/lib/event-types/transformers/api-response.ts to improve the clarity and readability of the response data.
|
||||
|
||||
## 0.0.26
|
||||
Update `packages/app-store/office365calendar/lib/CalendarService.ts` "translateEvent" content so that in microsoft outlook calendar event the description
|
||||
has newlines instead of being all in 1 line.
|
||||
@@ -6,7 +13,6 @@ has newlines instead of being all in 1 line.
|
||||
Refactor "packages/lib/event-types/transformers/api-request.ts" getResponseEventTypeBookingFields - make sure that booking fields with options don't have
|
||||
undefines options.
|
||||
|
||||
|
||||
## 0.0.24
|
||||
Refactor "packages/lib/event-types/transformers/api-request.ts" - we access event-type booking fields in database and then distinguish them as either
|
||||
created by the user or system. Then in v2 api "event-types_2024_06_14/services/output-event-types.service.ts" we first parse them and then filter
|
||||
|
||||
@@ -93,13 +93,18 @@ export { EventTypeMetaDataSchema, userMetadata } from "@calcom/prisma/zod-utils"
|
||||
|
||||
export {
|
||||
transformApiEventTypeBookingFields,
|
||||
transformApiEventTypeIntervalLimits,
|
||||
transformApiEventTypeLocations,
|
||||
getResponseEventTypeLocations,
|
||||
getResponseEventTypeBookingFields,
|
||||
TransformedLocationsSchema,
|
||||
BookingFieldsSchema,
|
||||
getResponseEventTypeIntervalLimits,
|
||||
getResponseEventTypeFutureBookingLimits,
|
||||
transformApiEventTypeFutureBookingLimits,
|
||||
} from "@calcom/lib/event-types/transformers";
|
||||
|
||||
export { parseBookingLimit } from "@calcom/lib";
|
||||
export type { SystemField, UserField } from "@calcom/lib/event-types/transformers";
|
||||
|
||||
export { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import type { ValidatorConstraintInterface, ValidationOptions } from "class-validator";
|
||||
import { IsInt, IsOptional, Min, ValidatorConstraint, registerDecorator } from "class-validator";
|
||||
|
||||
export type BookingLimitsKeyOutputType_2024_06_14 = "PER_DAY" | "PER_WEEK" | "PER_MONTH" | "PER_YEAR";
|
||||
export type BookingLimitsKeysInputType = "day" | "week" | "month" | "year";
|
||||
export type TransformBookingLimitsSchema_2024_06_14 = {
|
||||
[K in BookingLimitsKeyOutputType_2024_06_14]?: number;
|
||||
};
|
||||
|
||||
export class BookingLimitsCount_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiProperty({
|
||||
description: "The number of bookings per day",
|
||||
example: 1,
|
||||
})
|
||||
day?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiProperty({
|
||||
description: "The number of bookings per week",
|
||||
example: 2,
|
||||
})
|
||||
week?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiProperty({
|
||||
description: "The number of bookings per month",
|
||||
example: 3,
|
||||
})
|
||||
month?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@ApiProperty({
|
||||
description: "The number of bookings per year",
|
||||
example: 4,
|
||||
})
|
||||
year?: number;
|
||||
}
|
||||
|
||||
// Custom validator to handle the union type
|
||||
@ValidatorConstraint({ name: "BookingLimitsCountValidator", async: false })
|
||||
class BookingLimitsCountValidator implements ValidatorConstraintInterface {
|
||||
private errorDetails: {
|
||||
invalidLimit?: string;
|
||||
comparedLimit?: string;
|
||||
} = {};
|
||||
validate(value: BookingLimitsCount_2024_06_14) {
|
||||
if (!value) return false;
|
||||
|
||||
const { day, week, month, year } = value;
|
||||
|
||||
// Check if 'day' exceeds 'week', 'month', or 'year'
|
||||
if (day && ((week && day > week) || (month && day > month) || (year && day > year))) {
|
||||
this.errorDetails.invalidLimit = "day";
|
||||
this.errorDetails.comparedLimit = week && day > week ? "week" : month && day > month ? "month" : "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if 'week' exceeds 'month' or 'year'
|
||||
if (week && ((month && week > month) || (year && week > year))) {
|
||||
this.errorDetails.invalidLimit = "week";
|
||||
this.errorDetails.comparedLimit = month && week > month ? "month" : "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if 'month' exceeds 'year'
|
||||
if (month && year && month > year) {
|
||||
this.errorDetails.invalidLimit = "month";
|
||||
this.errorDetails.comparedLimit = "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
defaultMessage() {
|
||||
const { invalidLimit, comparedLimit } = this.errorDetails;
|
||||
return `Invalid booking limits: The number of bookings for ${invalidLimit} cannot exceed the number of bookings for ${comparedLimit}.`;
|
||||
}
|
||||
}
|
||||
|
||||
export function ValidateBookingLimistsCount(validationOptions?: ValidationOptions) {
|
||||
return function (object: any, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: "ValidateBookingLimistsCount",
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
options: validationOptions,
|
||||
validator: new BookingLimitsCountValidator(),
|
||||
});
|
||||
};
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import type { ValidatorConstraintInterface, ValidationOptions } from "class-validator";
|
||||
import { IsInt, IsOptional, Min, ValidatorConstraint, registerDecorator } from "class-validator";
|
||||
|
||||
export class BookingLimitsDuration_2024_06_14 {
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(15)
|
||||
@ApiProperty({
|
||||
description: "The duration of bookings per day (must be a multiple of 15)",
|
||||
example: 60,
|
||||
})
|
||||
day?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(15)
|
||||
@ApiProperty({
|
||||
description: "The duration of bookings per week (must be a multiple of 15)",
|
||||
example: 120,
|
||||
})
|
||||
week?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(15)
|
||||
@ApiProperty({
|
||||
description: "The duration of bookings per month (must be a multiple of 15)",
|
||||
example: 180,
|
||||
})
|
||||
month?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(15)
|
||||
@ApiProperty({
|
||||
description: "The duration of bookings per year (must be a multiple of 15)",
|
||||
example: 240,
|
||||
})
|
||||
year?: number;
|
||||
}
|
||||
|
||||
@ValidatorConstraint({ name: "BookingLimitsDurationValidator", async: false })
|
||||
class BookingLimitsDurationValidator implements ValidatorConstraintInterface {
|
||||
private errorDetails: {
|
||||
invalidLimit?: string;
|
||||
comparedLimit?: string;
|
||||
} = {};
|
||||
validate(value: BookingLimitsDuration_2024_06_14) {
|
||||
if (!value) return false;
|
||||
|
||||
const { day, week, month, year } = value;
|
||||
|
||||
// Check if 'day' exceeds 'week', 'month', or 'year'
|
||||
if (day && ((week && day > week) || (month && day > month) || (year && day > year))) {
|
||||
this.errorDetails.invalidLimit = "day";
|
||||
this.errorDetails.comparedLimit = week && day > week ? "week" : month && day > month ? "month" : "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if 'week' exceeds 'month' or 'year'
|
||||
if (week && ((month && week > month) || (year && week > year))) {
|
||||
this.errorDetails.invalidLimit = "week";
|
||||
this.errorDetails.comparedLimit = month && week > month ? "month" : "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if 'month' exceeds 'year'
|
||||
if (month && year && month > year) {
|
||||
this.errorDetails.invalidLimit = "month";
|
||||
this.errorDetails.comparedLimit = "year";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
defaultMessage() {
|
||||
const { invalidLimit, comparedLimit } = this.errorDetails;
|
||||
return `Invalid booking durations: The duration of bookings for ${invalidLimit} cannot exceed the duration of bookings for ${comparedLimit}.`;
|
||||
}
|
||||
}
|
||||
|
||||
export function ValidateBookingLimistsDuration(validationOptions?: ValidationOptions) {
|
||||
return function (object: any, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: "ValidateBookingLimistsDuration",
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
options: validationOptions,
|
||||
validator: new BookingLimitsDurationValidator(),
|
||||
});
|
||||
};
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
import { BadRequestException } from "@nestjs/common";
|
||||
import type { ValidatorConstraintInterface, ValidationOptions } from "class-validator";
|
||||
import {
|
||||
IsEnum,
|
||||
IsNumber,
|
||||
IsArray,
|
||||
ArrayNotEmpty,
|
||||
IsDateString,
|
||||
IsDefined,
|
||||
IsOptional,
|
||||
ValidatorConstraint,
|
||||
registerDecorator,
|
||||
IsBoolean,
|
||||
} from "class-validator";
|
||||
|
||||
import { BookingWindowPeriodInputTypeEnum_2024_06_14 } from "./enums/booking-window.enum";
|
||||
|
||||
export type BookingWindowPeriodInputType_2024_06_14 = "businessDays" | "calendarDays" | "range";
|
||||
export type BookingWindowPeriodOutputType_2024_06_14 = "RANGE" | "ROLLING_WINDOW" | "ROLLING";
|
||||
|
||||
export type TransformFutureBookingsLimitSchema_2024_06_14 = {
|
||||
periodType: BookingWindowPeriodOutputType_2024_06_14;
|
||||
periodDays?: number;
|
||||
periodCountCalendarDays?: boolean;
|
||||
periodStartDate?: Date;
|
||||
periodEndDate?: Date;
|
||||
};
|
||||
|
||||
// Base class for common properties and validation
|
||||
class BookingWindowBase {
|
||||
@IsEnum(BookingWindowPeriodInputTypeEnum_2024_06_14)
|
||||
type!: BookingWindowPeriodInputType_2024_06_14;
|
||||
}
|
||||
|
||||
// Separate classes for different value types
|
||||
export class BusinessDaysWindow_2024_06_14 extends BookingWindowBase {
|
||||
@IsNumber()
|
||||
@IsDefined()
|
||||
value!: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
rolling?: boolean;
|
||||
}
|
||||
|
||||
export class CalendarDaysWindow_2024_06_14 extends BookingWindowBase {
|
||||
@IsNumber()
|
||||
@IsDefined()
|
||||
value!: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
rolling?: boolean;
|
||||
}
|
||||
|
||||
export class RangeWindow_2024_06_14 extends BookingWindowBase {
|
||||
@IsArray()
|
||||
@ArrayNotEmpty()
|
||||
@IsDateString({}, { each: true })
|
||||
@IsDefined()
|
||||
value!: string[];
|
||||
}
|
||||
|
||||
export type BookingWindow_2024_06_14 =
|
||||
| BusinessDaysWindow_2024_06_14
|
||||
| CalendarDaysWindow_2024_06_14
|
||||
| RangeWindow_2024_06_14;
|
||||
|
||||
// Custom validator to handle the union type
|
||||
@ValidatorConstraint({ name: "bookingWindowValidator", async: false })
|
||||
class BookingWindowValidator implements ValidatorConstraintInterface {
|
||||
validate(value: BookingWindow_2024_06_14) {
|
||||
if (!value || !value.type) {
|
||||
throw new BadRequestException(`'BookingWindow' must have a type`);
|
||||
}
|
||||
|
||||
switch (value.type) {
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.businessDays:
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.calendarDays:
|
||||
return (
|
||||
typeof value.value === "number" &&
|
||||
(typeof (value as BusinessDaysWindow_2024_06_14 | CalendarDaysWindow_2024_06_14).rolling ===
|
||||
"undefined" ||
|
||||
typeof (value as BusinessDaysWindow_2024_06_14 | CalendarDaysWindow_2024_06_14).rolling ===
|
||||
"boolean")
|
||||
);
|
||||
case BookingWindowPeriodInputTypeEnum_2024_06_14.range:
|
||||
return (
|
||||
Array.isArray(value.value) &&
|
||||
value.value.every((date: any) => typeof date === "string" && !isNaN(Date.parse(date)))
|
||||
);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
defaultMessage() {
|
||||
return "Invalid bookingWindow structure.";
|
||||
}
|
||||
}
|
||||
|
||||
export function ValidateBookingWindow(validationOptions?: ValidationOptions) {
|
||||
return function (object: any, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: "ValidateBookingWindow",
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
options: validationOptions,
|
||||
validator: new BookingWindowValidator(),
|
||||
});
|
||||
};
|
||||
}
|
||||
+31
-54
@@ -13,6 +13,13 @@ import {
|
||||
|
||||
import type { BookingField_2024_06_14 } from "./booking-fields.input";
|
||||
import { ValidateBookingFields_2024_06_14 } from "./booking-fields.input";
|
||||
import { BookingLimitsCount_2024_06_14, ValidateBookingLimistsCount } from "./booking-limits-count.input";
|
||||
import {
|
||||
BookingLimitsDuration_2024_06_14,
|
||||
ValidateBookingLimistsDuration,
|
||||
} from "./booking-limits-duration.input";
|
||||
import type { BookingWindow_2024_06_14 } from "./booking-window.input";
|
||||
import { ValidateBookingWindow } from "./booking-window.input";
|
||||
import { SchedulingType } from "./enums/scheduling-type";
|
||||
import { ValidateLocations_2024_06_14 } from "./locations.input";
|
||||
import type { Location_2024_06_14 } from "./locations.input";
|
||||
@@ -72,6 +79,29 @@ export class CreateEventTypeInput_2024_06_14 {
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
scheduleId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsCount_2024_06_14)
|
||||
@ValidateBookingLimistsCount()
|
||||
bookingLimitsCount?: BookingLimitsCount_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
onlyShowFirstAvailableSlot?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsDuration_2024_06_14)
|
||||
@ValidateBookingLimistsDuration()
|
||||
bookingLimitsDuration?: BookingLimitsDuration_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateBookingWindow()
|
||||
bookingWindow?: BookingWindow_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
offsetStart?: number;
|
||||
}
|
||||
|
||||
export enum HostPriority {
|
||||
@@ -94,60 +124,7 @@ export class Host {
|
||||
priority?: keyof typeof HostPriority = "medium";
|
||||
}
|
||||
|
||||
export class CreateTeamEventTypeInput_2024_06_14 {
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@DocsProperty({ example: CREATE_EVENT_LENGTH_EXAMPLE })
|
||||
lengthInMinutes!: number;
|
||||
|
||||
@IsString()
|
||||
@DocsProperty({ example: CREATE_EVENT_TITLE_EXAMPLE })
|
||||
title!: string;
|
||||
|
||||
@IsString()
|
||||
slug!: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@DocsProperty({ example: CREATE_EVENT_DESCRIPTION_EXAMPLE })
|
||||
description?: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateLocations_2024_06_14()
|
||||
@DocsProperty()
|
||||
locations?: Location_2024_06_14[];
|
||||
|
||||
@IsOptional()
|
||||
@ValidateBookingFields_2024_06_14()
|
||||
@DocsProperty()
|
||||
bookingFields?: BookingField_2024_06_14[];
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
disableGuests?: boolean;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
slotInterval?: number;
|
||||
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
minimumBookingNotice?: number;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
beforeEventBuffer?: number;
|
||||
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
afterEventBuffer?: number;
|
||||
|
||||
export class CreateTeamEventTypeInput_2024_06_14 extends CreateEventTypeInput_2024_06_14 {
|
||||
@Transform(({ value }) => {
|
||||
if (value === "collective") {
|
||||
return SchedulingType.COLLECTIVE;
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
export enum BookingWindowPeriodInputTypeEnum_2024_06_14 {
|
||||
businessDays = "businessDays",
|
||||
calendarDays = "calendarDays",
|
||||
range = "range",
|
||||
}
|
||||
|
||||
export enum BookingWindowPeriodOutputTypeEnum_2024_06_14 {
|
||||
RANGE = "RANGE",
|
||||
ROLLING_WINDOW = "ROLLING_WINDOW",
|
||||
ROLLING = "ROLLING",
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export enum BookingLimitsEnum_2024_06_14 {
|
||||
day = "PER_DAY",
|
||||
week = "PER_WEEK",
|
||||
month = "PER_MONTH",
|
||||
year = "PER_YEAR",
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
export * from "./create-event-type.input";
|
||||
export * from "./booking-limits-duration.input";
|
||||
export * from "./booking-limits-count.input";
|
||||
export * from "./booking-window.input";
|
||||
export * from "./locations.input";
|
||||
export * from "./booking-fields.input";
|
||||
export * from "./recurring-event.input";
|
||||
|
||||
+52
@@ -4,6 +4,12 @@ import { IsString, IsInt, IsBoolean, IsOptional, Min, ValidateNested, IsArray }
|
||||
|
||||
import type { BookingField_2024_06_14 } from "./booking-fields.input";
|
||||
import { ValidateBookingFields_2024_06_14 } from "./booking-fields.input";
|
||||
import { BookingLimitsCount_2024_06_14, ValidateBookingLimistsCount } from "./booking-limits-count.input";
|
||||
import {
|
||||
BookingLimitsDuration_2024_06_14,
|
||||
ValidateBookingLimistsDuration,
|
||||
} from "./booking-limits-duration.input";
|
||||
import { ValidateBookingWindow, type BookingWindow_2024_06_14 } from "./booking-window.input";
|
||||
import { Host } from "./create-event-type.input";
|
||||
import { ValidateLocations_2024_06_14 } from "./locations.input";
|
||||
import type { Location_2024_06_14 } from "./locations.input";
|
||||
@@ -58,6 +64,29 @@ export class UpdateEventTypeInput_2024_06_14 {
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
scheduleId?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsCount_2024_06_14)
|
||||
@ValidateBookingLimistsCount()
|
||||
bookingLimitsCount?: BookingLimitsCount_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
onlyShowFirstAvailableSlot?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsDuration_2024_06_14)
|
||||
@ValidateBookingLimistsDuration()
|
||||
bookingLimitsDuration?: BookingLimitsDuration_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateBookingWindow()
|
||||
bookingWindow?: BookingWindow_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
offsetStart?: number;
|
||||
}
|
||||
export class UpdateTeamEventTypeInput_2024_06_14 {
|
||||
@IsOptional()
|
||||
@@ -128,4 +157,27 @@ export class UpdateTeamEventTypeInput_2024_06_14 {
|
||||
@IsOptional()
|
||||
@DocsProperty()
|
||||
assignAllTeamMembers?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsCount_2024_06_14)
|
||||
@ValidateBookingLimistsCount()
|
||||
bookingLimitsCount?: BookingLimitsCount_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
onlyShowFirstAvailableSlot?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsDuration_2024_06_14)
|
||||
@ValidateBookingLimistsDuration()
|
||||
bookingLimitsDuration?: BookingLimitsDuration_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateBookingWindow()
|
||||
bookingWindow?: BookingWindow_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
offsetStart?: number;
|
||||
}
|
||||
|
||||
+41
-2
@@ -11,10 +11,11 @@ import {
|
||||
ValidateNested,
|
||||
} from "class-validator";
|
||||
|
||||
import type { Location_2024_06_14, BookingField_2024_06_14 } from "../inputs";
|
||||
import { Host as TeamEventTypeHostInput } from "../inputs";
|
||||
import type { Location_2024_06_14, BookingField_2024_06_14, BookingWindow_2024_06_14 } from "../inputs";
|
||||
import { Host as TeamEventTypeHostInput, BookingLimitsDuration_2024_06_14 } from "../inputs";
|
||||
import { RecurringEvent_2024_06_14 } from "../inputs";
|
||||
import { ValidateBookingFields_2024_06_14 } from "../inputs/booking-fields.input";
|
||||
import type { BookingLimitsCount_2024_06_14 } from "../inputs/booking-limits-count.input";
|
||||
import { ValidateLocations_2024_06_14 } from "../inputs/locations.input";
|
||||
|
||||
enum SchedulingTypeEnum {
|
||||
@@ -137,6 +138,25 @@ export class EventTypeOutput_2024_06_14 {
|
||||
|
||||
@IsInt()
|
||||
scheduleId!: number | null;
|
||||
|
||||
@IsOptional()
|
||||
bookingLimitsCount?: BookingLimitsCount_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
onlyShowFirstAvailableSlot?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsDuration_2024_06_14)
|
||||
bookingLimitsDuration?: BookingLimitsDuration_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
bookingWindow?: BookingWindow_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
offsetStart?: number;
|
||||
}
|
||||
|
||||
export class TeamEventTypeResponseHost extends TeamEventTypeHostInput {
|
||||
@@ -247,4 +267,23 @@ export class TeamEventTypeOutput_2024_06_14 {
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
assignAllTeamMembers?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
bookingLimitsCount?: BookingLimitsCount_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
onlyShowFirstAvailableSlot?: boolean;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => BookingLimitsDuration_2024_06_14)
|
||||
bookingLimitsDuration?: BookingLimitsDuration_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
bookingWindow?: BookingWindow_2024_06_14;
|
||||
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
offsetStart?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user