diff --git a/packages/features/bookings/lib/getBookingFields.ts b/packages/features/bookings/lib/getBookingFields.ts index b1adcb1485..e297c6345e 100644 --- a/packages/features/bookings/lib/getBookingFields.ts +++ b/packages/features/bookings/lib/getBookingFields.ts @@ -218,14 +218,6 @@ export const ensureBookingInputsHaveSystemFields = ({ }, ]; - // Backward Compatibility for SMS Reminder Number - if (smsNumberSources.length) { - systemBeforeFields.push({ - ...getSmsReminderNumberField(), - sources: smsNumberSources, - }); - } - // These fields should be added after other user fields const systemAfterFields: typeof bookingFields = [ { @@ -282,6 +274,18 @@ export const ensureBookingInputsHaveSystemFields = ({ bookingFields = missingSystemBeforeFields.concat(bookingFields); + // Backward Compatibility for SMS Reminder Number + // Note: We still need workflows in `getBookingFields` due to Backward Compatibility. If we do a one time entry for all event-types, we can remove workflows from `getBookingFields` + // Also, note that even if Workflows don't explicity add smsReminderNumber field to bookingFields, it would be added as a side effect of this backward compatibility logic + if (smsNumberSources.length && !bookingFields.find((f) => f.name !== SMS_REMINDER_NUMBER_FIELD)) { + const indexForLocation = bookingFields.findIndex((f) => f.name === "location"); + // Add the SMS Reminder Number field after `location` field always + bookingFields.splice(indexForLocation + 1, 0, { + ...getSmsReminderNumberField(), + sources: smsNumberSources, + }); + } + // Backward Compatibility: If we are migrating from old system, we need to map `customInputs` to `bookingFields` if (handleMigration) { customInputs.forEach((input) => { diff --git a/packages/features/eventtypes/lib/bookingFieldsManager.ts b/packages/features/eventtypes/lib/bookingFieldsManager.ts index 74d4119d74..645b9c6390 100644 --- a/packages/features/eventtypes/lib/bookingFieldsManager.ts +++ b/packages/features/eventtypes/lib/bookingFieldsManager.ts @@ -1,9 +1,9 @@ -import { z } from "zod"; +import type { z } from "zod"; import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields"; import { prisma } from "@calcom/prisma"; -import { EventType } from "@calcom/prisma/client"; -import { eventTypeBookingFields } from "@calcom/prisma/zod-utils"; +import type { EventType } from "@calcom/prisma/client"; +import type { eventTypeBookingFields } from "@calcom/prisma/zod-utils"; type Field = z.infer[number]; @@ -51,6 +51,7 @@ export async function upsertBookingField( ) { const eventType = await getEventType(eventTypeId); let fieldFound = false; + const newFields = eventType.bookingFields.map((f) => { if (f.name === fieldToAdd.name) { fieldFound = true; diff --git a/packages/trpc/server/routers/viewer/workflows.tsx b/packages/trpc/server/routers/viewer/workflows.tsx index 0c47b8a706..46ae210777 100644 --- a/packages/trpc/server/routers/viewer/workflows.tsx +++ b/packages/trpc/server/routers/viewer/workflows.tsx @@ -384,6 +384,9 @@ export const workflowsRouter = router({ where: { id, }, + include: { + activeOn: true, + }, }); const isUserAuthorized = await isAuthorized(workflowToDelete, ctx.prisma, ctx.user.id, true); @@ -413,6 +416,10 @@ export const workflowsRouter = router({ } }); + for (const activeOn of workflowToDelete.activeOn) { + await removeSmsReminderFieldForBooking({ workflowId: id, eventTypeId: activeOn.eventTypeId }); + } + await ctx.prisma.workflow.deleteMany({ where: { id, @@ -467,6 +474,7 @@ export const workflowsRouter = router({ }, }, steps: true, + activeOn: true, }, }); @@ -578,13 +586,6 @@ export const workflowsRouter = router({ remindersToDeletePromise.push(reminderToDelete); }); - for (const removedEventType of removedEventTypes) { - await removeSmsReminderFieldForBooking({ - workflowId: id, - eventTypeId: removedEventType, - }); - } - const remindersToDelete = await Promise.all(remindersToDeletePromise); //cancel workflow reminders for all bookings from event types that got disabled @@ -718,16 +719,6 @@ export const workflowsRouter = router({ }); } - for (const eventTypeId of activeOn) { - await upsertSmsReminderFieldForBooking({ - workflowId: id, - isSmsReminderNumberRequired: input.steps.some( - (s) => s.action === WorkflowActions.SMS_ATTENDEE && s.numberRequired - ), - eventTypeId, - }); - } - userWorkflow.steps.map(async (oldStep) => { const newStep = steps.filter((s) => s.id === oldStep.id)[0]; const remindersFromStep = await ctx.prisma.workflowReminder.findMany({ @@ -738,6 +729,7 @@ export const workflowsRouter = router({ booking: true, }, }); + //step was deleted if (!newStep) { // cancel all workflow reminders from deleted steps @@ -755,6 +747,7 @@ export const workflowsRouter = router({ id: oldStep.id, }, }); + //step was edited } else if (JSON.stringify(oldStep) !== JSON.stringify(newStep)) { if ( @@ -1077,6 +1070,31 @@ export const workflowsRouter = router({ }, }); + // Remove or add booking field for sms reminder number + const smsReminderNumberNeeded = + activeOn.length && steps.some((step) => step.action === WorkflowActions.SMS_ATTENDEE); + + for (const removedEventType of removedEventTypes) { + await removeSmsReminderFieldForBooking({ + workflowId: id, + eventTypeId: removedEventType, + }); + } + + for (const eventTypeId of activeOn) { + if (smsReminderNumberNeeded) { + await upsertSmsReminderFieldForBooking({ + workflowId: id, + isSmsReminderNumberRequired: steps.some( + (s) => s.action === WorkflowActions.SMS_ATTENDEE && s.numberRequired + ), + eventTypeId, + }); + } else { + await removeSmsReminderFieldForBooking({ workflowId: id, eventTypeId }); + } + } + return { workflow, }; @@ -1183,7 +1201,7 @@ evt = { attendees: [{ name: "John Doe", email: "john.doe@example.com", timeZone: "Europe/London" }], organizer: { language: { - locale: ctx.user.locale, +locale: ctx.user.locale, }, name: ctx.user.name || "", email: ctx.user.email, @@ -1319,16 +1337,11 @@ action === WorkflowActions.EMAIL_ADDRESS*/ eventTypeId, }, }); - await removeBookingField( - { - name: "smsReminderNumber", - }, - { - id: "" + workflowId, - type: "workflow", - }, - eventTypeId - ); + + await removeSmsReminderFieldForBooking({ + workflowId, + eventTypeId, + }); } else { await ctx.prisma.workflowsOnEventTypes.create({ data: { @@ -1337,15 +1350,20 @@ action === WorkflowActions.EMAIL_ADDRESS*/ }, }); - const isSmsReminderNumberRequired = eventTypeWorkflow.steps.some((step) => { - return step.action === WorkflowActions.SMS_ATTENDEE && step.numberRequired; - }); - - await upsertSmsReminderFieldForBooking({ - workflowId, - isSmsReminderNumberRequired, - eventTypeId, - }); + if ( + eventTypeWorkflow.steps.some((step) => { + return step.action === WorkflowActions.SMS_ATTENDEE; + }) + ) { + const isSmsReminderNumberRequired = eventTypeWorkflow.steps.some((step) => { + return step.action === WorkflowActions.SMS_ATTENDEE && step.numberRequired; + }); + await upsertSmsReminderFieldForBooking({ + workflowId, + isSmsReminderNumberRequired, + eventTypeId, + }); + } } }), sendVerificationCode: authedProcedure