Skip to content

Commit c472bce

Browse files
authored
fix: v2 managed event type creation hosts (#22584)
* fix: v2 managed event type creation hosts * refactor * fix: test * remove uncecessary call
1 parent a498641 commit c472bce

File tree

2 files changed

+103
-16
lines changed

2 files changed

+103
-16
lines changed

apps/api/v2/src/modules/organizations/event-types/organizations-event-types.e2e-spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,56 @@ describe("Organizations Event Types Endpoints", () => {
11581158
});
11591159
});
11601160

1161+
it("should create a managed team event-type without hosts", async () => {
1162+
const body: CreateTeamEventTypeInput_2024_06_14 = {
1163+
title: "Coding consultation managed without hosts",
1164+
slug: "coding-consultation-managed-without-hosts",
1165+
description: "Our team will review your codebase.",
1166+
lengthInMinutes: 60,
1167+
locations: [
1168+
{
1169+
type: "integration",
1170+
integration: "cal-video",
1171+
},
1172+
],
1173+
schedulingType: "MANAGED",
1174+
};
1175+
1176+
return request(app.getHttpServer())
1177+
.post(`/v2/organizations/${org.id}/teams/${team.id}/event-types`)
1178+
.send(body)
1179+
.expect(201)
1180+
.then(async (response) => {
1181+
const responseBody: ApiSuccessResponse<TeamEventTypeOutput_2024_06_14[]> = response.body;
1182+
expect(responseBody.status).toEqual(SUCCESS_STATUS);
1183+
1184+
const data = responseBody.data;
1185+
expect(data.length).toEqual(1);
1186+
1187+
const teammate1EventTypes = await eventTypesRepositoryFixture.getAllUserEventTypes(teammate1.id);
1188+
const teammate2EventTypes = await eventTypesRepositoryFixture.getAllUserEventTypes(teammate2.id);
1189+
const teamEventTypes = await eventTypesRepositoryFixture.getAllTeamEventTypes(team.id);
1190+
1191+
const teammate1HasThisEvent = teammate1EventTypes.some((eventType) => eventType.slug === body.slug);
1192+
const teammate2HasThisEvent = teammate2EventTypes.some((eventType) => eventType.slug === body.slug);
1193+
expect(teammate1HasThisEvent).toBe(false);
1194+
expect(teammate2HasThisEvent).toBe(false);
1195+
expect(
1196+
teamEventTypes.filter(
1197+
(eventType) => eventType.schedulingType === "MANAGED" && eventType.slug === body.slug
1198+
).length
1199+
).toEqual(1);
1200+
1201+
const responseTeamEvent = responseBody.data.find((event) => event.teamId === team.id);
1202+
expect(responseTeamEvent).toBeDefined();
1203+
expect(responseTeamEvent?.hosts).toEqual([]);
1204+
1205+
if (!responseTeamEvent) {
1206+
throw new Error("Team event not found");
1207+
}
1208+
});
1209+
});
1210+
11611211
function evaluateHost(expected: Host, received: Host | undefined) {
11621212
expect(expected.userId).toEqual(received?.userId);
11631213
expect(expected.mandatory).toEqual(received?.mandatory);

apps/api/v2/src/modules/organizations/event-types/services/input.service.ts

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export class InputOrganizationsEventTypesService {
121121
},
122122
];
123123

124-
const children = await this.getChildEventTypesForManagedEventType(null, inputEventType, teamId);
124+
const children = await this.getChildEventTypesForManagedEventTypeCreate(inputEventType, teamId);
125125

126126
const metadata =
127127
rest.schedulingType === "MANAGED"
@@ -159,7 +159,11 @@ export class InputOrganizationsEventTypesService {
159159
throw new BadRequestException("Event type to update not found");
160160
}
161161

162-
const children = await this.getChildEventTypesForManagedEventType(eventTypeId, inputEventType, teamId);
162+
const children =
163+
dbEventType.schedulingType === "MANAGED"
164+
? await this.getChildEventTypesForManagedEventTypeUpdate(eventTypeId, inputEventType, teamId)
165+
: undefined;
166+
163167
const teamEventType = {
164168
...eventType,
165169
// note(Lauris): we don't populate hosts for managed event-types because they are handled by the children
@@ -176,20 +180,17 @@ export class InputOrganizationsEventTypesService {
176180
return teamEventType;
177181
}
178182

179-
async getChildEventTypesForManagedEventType(
180-
eventTypeId: number | null,
183+
async getChildEventTypesForManagedEventTypeUpdate(
184+
eventTypeId: number,
181185
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
182186
teamId: number
183187
) {
184-
let eventType = null;
185-
if (eventTypeId) {
186-
eventType = await this.teamsEventTypesRepository.getEventTypeByIdWithChildren(eventTypeId);
187-
if (!eventType || eventType.schedulingType !== "MANAGED") {
188-
return undefined;
189-
}
188+
const eventType = await this.teamsEventTypesRepository.getEventTypeByIdWithChildren(eventTypeId);
189+
if (!eventType || eventType.schedulingType !== "MANAGED") {
190+
return undefined;
190191
}
191192

192-
const ownersIds = await this.getOwnersIdsForManagedEventType(teamId, inputEventType, eventType);
193+
const ownersIds = await this.getOwnersIdsForManagedEventTypeUpdate(teamId, inputEventType, eventType);
193194
const owners = await this.getOwnersForManagedEventType(ownersIds);
194195

195196
return owners.map((owner) => {
@@ -200,22 +201,58 @@ export class InputOrganizationsEventTypesService {
200201
});
201202
}
202203

203-
async getOwnersIdsForManagedEventType(
204+
async getOwnersIdsForManagedEventTypeUpdate(
204205
teamId: number,
205206
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
206-
eventType: { children: { userId: number | null }[] } | null
207+
eventType: { children: { userId: number | null }[] }
207208
) {
208209
if (inputEventType.assignAllTeamMembers) {
209210
return await this.getTeamUsersIds(teamId);
210211
}
211212

212-
// note(Lauris): when API user updates managed event type users
213213
if (inputEventType.hosts) {
214214
return inputEventType.hosts.map((host) => host.userId);
215215
}
216216

217217
// note(Lauris): when API user DOES NOT update managed event type users, but we still need existing managed event type users to know which event-types to update
218-
return eventType?.children.map((child) => child.userId).filter((id) => !!id) as number[];
218+
// e.g if managed event type title is changed then all children managed event types should be updated as well.
219+
const childrenOwnersIds: number[] = [];
220+
for (const child of eventType.children) {
221+
if (child.userId) {
222+
childrenOwnersIds.push(child.userId);
223+
}
224+
}
225+
return childrenOwnersIds;
226+
}
227+
228+
async getChildEventTypesForManagedEventTypeCreate(
229+
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
230+
teamId: number
231+
) {
232+
const ownersIds = await this.getOwnersIdsForManagedEventTypeCreate(teamId, inputEventType);
233+
const owners = await this.getOwnersForManagedEventType(ownersIds);
234+
235+
return owners.map((owner) => {
236+
return {
237+
hidden: false,
238+
owner,
239+
};
240+
});
241+
}
242+
243+
async getOwnersIdsForManagedEventTypeCreate(
244+
teamId: number,
245+
inputEventType: UpdateTeamEventTypeInput_2024_06_14
246+
) {
247+
if (inputEventType.assignAllTeamMembers) {
248+
return await this.getTeamUsersIds(teamId);
249+
}
250+
251+
if (inputEventType.hosts) {
252+
return inputEventType.hosts.map((host) => host.userId);
253+
}
254+
255+
return [];
219256
}
220257

221258
async getTeamUsersIds(teamId: number) {
@@ -234,7 +271,7 @@ export class InputOrganizationsEventTypesService {
234271
}
235272

236273
async getOwnersForManagedEventType(userIds: number[]) {
237-
const users = await this.usersRepository.findByIdsWithEventTypes(userIds);
274+
const users = userIds.length ? await this.usersRepository.findByIdsWithEventTypes(userIds) : [];
238275

239276
return users.map((user) => {
240277
const nonManagedEventTypes = user.eventTypes.filter((eventType) => !eventType.parentId);

0 commit comments

Comments
 (0)