From a6578fdcd2f69bc009f74d9c5d9488f2e3f550c9 Mon Sep 17 00:00:00 2001 From: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:11:21 +0200 Subject: [PATCH] perf: handleChildrenEventType link old event-type with workflows using create/findMany (#25653) * perf: link old event-type with workflows using create/findMany * test: fix handleChildrenEventTypes test mocks for new workflow linking implementation Update test to match the new implementation that uses findMany + createMany instead of upsert for linking workflows to old event types. - Add mock for workflowsOnEventTypes.findMany to return empty array - Update assertion from upsert to findMany + createMany Co-Authored-By: morgan@cal.com --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../test/lib/handleChildrenEventTypes.test.ts | 30 +++++---- .../lib/handleChildrenEventTypes.ts | 61 +++++++++++++------ 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/apps/web/test/lib/handleChildrenEventTypes.test.ts b/apps/web/test/lib/handleChildrenEventTypes.test.ts index c98b25d053..30be95e0d3 100644 --- a/apps/web/test/lib/handleChildrenEventTypes.test.ts +++ b/apps/web/test/lib/handleChildrenEventTypes.test.ts @@ -553,6 +553,10 @@ describe("handleChildrenEventTypes", () => { updatedAt: new Date(), }); + // Mock workflowsOnEventTypes.findMany to return empty array (no existing workflow links for old event types) + // This is needed because the new implementation uses findMany + createMany instead of upsert + prismaMock.workflowsOnEventTypes.findMany.mockResolvedValue([]); + await updateChildrenEventTypes({ eventTypeId: 1, oldEventType: { children: [{ userId: 4 }], team: { name: "" } }, @@ -627,19 +631,23 @@ describe("handleChildrenEventTypes", () => { }, }, }); - // Verify workflowsOnEventTypes.upsert was called for existing users' workflows - expect(prismaMock.workflowsOnEventTypes.upsert).toHaveBeenCalledWith({ - create: { - eventTypeId: 2, - workflowId: 11, - }, - update: {}, + // Verify workflowsOnEventTypes.findMany was called to check existing relationships + expect(prismaMock.workflowsOnEventTypes.findMany).toHaveBeenCalledWith({ where: { - workflowId_eventTypeId: { - eventTypeId: 2, - workflowId: 11, - }, + workflowId: { in: [11] }, + eventTypeId: { in: [2] }, }, + select: { + workflowId: true, + eventTypeId: true, + }, + }); + + // Verify workflowsOnEventTypes.createMany was called for existing users' workflows + // Since findMany returned empty array, all workflow-eventType pairs should be created + expect(prismaMock.workflowsOnEventTypes.createMany).toHaveBeenCalledWith({ + data: [{ eventTypeId: 2, workflowId: 11 }], + skipDuplicates: false, }); }); }); diff --git a/packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts b/packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts index f360231330..78e02aef50 100644 --- a/packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts +++ b/packages/features/ee/managed-event-types/lib/handleChildrenEventTypes.ts @@ -355,26 +355,49 @@ export default async function handleChildrenEventTypes({ }) ); - if (currentWorkflowIds?.length) { - await prisma.$transaction( - currentWorkflowIds.flatMap((wfId) => { - return oldEventTypes.map((oEvTy) => { - return prisma.workflowsOnEventTypes.upsert({ - create: { - eventTypeId: oEvTy.id, - workflowId: wfId, - }, - update: {}, - where: { - workflowId_eventTypeId: { - eventTypeId: oEvTy.id, - workflowId: wfId, - }, - }, - }); + // Link workflows with old users' event types if new workflows were added + if (currentWorkflowIds?.length && oldEventTypes.length) { + await prisma.$transaction(async (tx) => { + const eventTypeIds = oldEventTypes.map((e) => e.id); + + const allDesiredPairs = currentWorkflowIds.flatMap((wfId: number) => + oldEventTypes.map((oEvTy: { id: number }) => ({ + eventTypeId: oEvTy.id, + workflowId: wfId, + })) + ); + + const existingRelationships = await tx.workflowsOnEventTypes.findMany({ + where: { + workflowId: { in: currentWorkflowIds }, + eventTypeId: { in: eventTypeIds }, + }, + select: { + workflowId: true, + eventTypeId: true, + }, + }); + + const existingSet = new Set( + existingRelationships.map( + (rel: { eventTypeId: number; workflowId: number }) => `${rel.eventTypeId}_${rel.workflowId}` + ) + ); + + const newRelationshipsToCreate = allDesiredPairs.filter( + (pair: { eventTypeId: number; workflowId: number }) => { + const key = `${pair.eventTypeId}_${pair.workflowId}`; + return !existingSet.has(key); + } + ); + + if (newRelationshipsToCreate.length > 0) { + await tx.workflowsOnEventTypes.createMany({ + data: newRelationshipsToCreate, + skipDuplicates: false, }); - }) - ); + } + }); } }