fix: v2 managed event type creation hosts (#22584)

* fix: v2 managed event type creation hosts

* refactor

* fix: test

* remove uncecessary call
This commit is contained in:
Lauris Skraucis
2025-07-17 09:02:12 +00:00
committed by GitHub
parent a498641b61
commit c472bce54f
2 changed files with 103 additions and 16 deletions
@@ -1158,6 +1158,56 @@ describe("Organizations Event Types Endpoints", () => {
});
});
it("should create a managed team event-type without hosts", async () => {
const body: CreateTeamEventTypeInput_2024_06_14 = {
title: "Coding consultation managed without hosts",
slug: "coding-consultation-managed-without-hosts",
description: "Our team will review your codebase.",
lengthInMinutes: 60,
locations: [
{
type: "integration",
integration: "cal-video",
},
],
schedulingType: "MANAGED",
};
return request(app.getHttpServer())
.post(`/v2/organizations/${org.id}/teams/${team.id}/event-types`)
.send(body)
.expect(201)
.then(async (response) => {
const responseBody: ApiSuccessResponse<TeamEventTypeOutput_2024_06_14[]> = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
const data = responseBody.data;
expect(data.length).toEqual(1);
const teammate1EventTypes = await eventTypesRepositoryFixture.getAllUserEventTypes(teammate1.id);
const teammate2EventTypes = await eventTypesRepositoryFixture.getAllUserEventTypes(teammate2.id);
const teamEventTypes = await eventTypesRepositoryFixture.getAllTeamEventTypes(team.id);
const teammate1HasThisEvent = teammate1EventTypes.some((eventType) => eventType.slug === body.slug);
const teammate2HasThisEvent = teammate2EventTypes.some((eventType) => eventType.slug === body.slug);
expect(teammate1HasThisEvent).toBe(false);
expect(teammate2HasThisEvent).toBe(false);
expect(
teamEventTypes.filter(
(eventType) => eventType.schedulingType === "MANAGED" && eventType.slug === body.slug
).length
).toEqual(1);
const responseTeamEvent = responseBody.data.find((event) => event.teamId === team.id);
expect(responseTeamEvent).toBeDefined();
expect(responseTeamEvent?.hosts).toEqual([]);
if (!responseTeamEvent) {
throw new Error("Team event not found");
}
});
});
function evaluateHost(expected: Host, received: Host | undefined) {
expect(expected.userId).toEqual(received?.userId);
expect(expected.mandatory).toEqual(received?.mandatory);
@@ -121,7 +121,7 @@ export class InputOrganizationsEventTypesService {
},
];
const children = await this.getChildEventTypesForManagedEventType(null, inputEventType, teamId);
const children = await this.getChildEventTypesForManagedEventTypeCreate(inputEventType, teamId);
const metadata =
rest.schedulingType === "MANAGED"
@@ -159,7 +159,11 @@ export class InputOrganizationsEventTypesService {
throw new BadRequestException("Event type to update not found");
}
const children = await this.getChildEventTypesForManagedEventType(eventTypeId, inputEventType, teamId);
const children =
dbEventType.schedulingType === "MANAGED"
? await this.getChildEventTypesForManagedEventTypeUpdate(eventTypeId, inputEventType, teamId)
: undefined;
const teamEventType = {
...eventType,
// 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 {
return teamEventType;
}
async getChildEventTypesForManagedEventType(
eventTypeId: number | null,
async getChildEventTypesForManagedEventTypeUpdate(
eventTypeId: number,
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
teamId: number
) {
let eventType = null;
if (eventTypeId) {
eventType = await this.teamsEventTypesRepository.getEventTypeByIdWithChildren(eventTypeId);
if (!eventType || eventType.schedulingType !== "MANAGED") {
return undefined;
}
const eventType = await this.teamsEventTypesRepository.getEventTypeByIdWithChildren(eventTypeId);
if (!eventType || eventType.schedulingType !== "MANAGED") {
return undefined;
}
const ownersIds = await this.getOwnersIdsForManagedEventType(teamId, inputEventType, eventType);
const ownersIds = await this.getOwnersIdsForManagedEventTypeUpdate(teamId, inputEventType, eventType);
const owners = await this.getOwnersForManagedEventType(ownersIds);
return owners.map((owner) => {
@@ -200,22 +201,58 @@ export class InputOrganizationsEventTypesService {
});
}
async getOwnersIdsForManagedEventType(
async getOwnersIdsForManagedEventTypeUpdate(
teamId: number,
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
eventType: { children: { userId: number | null }[] } | null
eventType: { children: { userId: number | null }[] }
) {
if (inputEventType.assignAllTeamMembers) {
return await this.getTeamUsersIds(teamId);
}
// note(Lauris): when API user updates managed event type users
if (inputEventType.hosts) {
return inputEventType.hosts.map((host) => host.userId);
}
// 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
return eventType?.children.map((child) => child.userId).filter((id) => !!id) as number[];
// e.g if managed event type title is changed then all children managed event types should be updated as well.
const childrenOwnersIds: number[] = [];
for (const child of eventType.children) {
if (child.userId) {
childrenOwnersIds.push(child.userId);
}
}
return childrenOwnersIds;
}
async getChildEventTypesForManagedEventTypeCreate(
inputEventType: UpdateTeamEventTypeInput_2024_06_14,
teamId: number
) {
const ownersIds = await this.getOwnersIdsForManagedEventTypeCreate(teamId, inputEventType);
const owners = await this.getOwnersForManagedEventType(ownersIds);
return owners.map((owner) => {
return {
hidden: false,
owner,
};
});
}
async getOwnersIdsForManagedEventTypeCreate(
teamId: number,
inputEventType: UpdateTeamEventTypeInput_2024_06_14
) {
if (inputEventType.assignAllTeamMembers) {
return await this.getTeamUsersIds(teamId);
}
if (inputEventType.hosts) {
return inputEventType.hosts.map((host) => host.userId);
}
return [];
}
async getTeamUsersIds(teamId: number) {
@@ -234,7 +271,7 @@ export class InputOrganizationsEventTypesService {
}
async getOwnersForManagedEventType(userIds: number[]) {
const users = await this.usersRepository.findByIdsWithEventTypes(userIds);
const users = userIds.length ? await this.usersRepository.findByIdsWithEventTypes(userIds) : [];
return users.map((user) => {
const nonManagedEventTypes = user.eventTypes.filter((eventType) => !eventType.parentId);