Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/features/bookings/di/RegularBookingService.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { moduleLoader as luckyUserServiceModuleLoader } from "@calcom/features/d
import { moduleLoader as prismaModuleLoader } from "@calcom/features/di/modules/Prisma";
import { moduleLoader as userRepositoryModuleLoader } from "@calcom/features/di/modules/User";
import { DI_TOKENS } from "@calcom/features/di/tokens";
import { moduleLoader as workflowTaskerModuleLoader } from "@calcom/features/ee/workflows/di/tasker/WorkflowTasker.module";
import { moduleLoader as hashedLinkServiceModuleLoader } from "@calcom/features/hashedLink/di/HashedLinkService.module";

import { moduleLoader as bookingEmailAndSmsTaskerModuleLoader } from "./tasker/BookingEmailAndSmsTasker.module";
Expand All @@ -28,10 +29,11 @@ const loadModule = bindModuleToClassOnToken({
luckyUserService: luckyUserServiceModuleLoader,
userRepository: userRepositoryModuleLoader,
hashedLinkService: hashedLinkServiceModuleLoader,
bookingEmailAndSmsTasker: bookingEmailAndSmsTaskerModuleLoader,
featuresRepository: featuresRepositoryModuleLoader,
bookingEventHandler: bookingEventHandlerModuleLoader,
},
bookingEmailAndSmsTasker: bookingEmailAndSmsTaskerModuleLoader,
featuresRepository: featuresRepositoryModuleLoader,
bookingEventHandler: bookingEventHandlerModuleLoader,
workflowTasker: workflowTaskerModuleLoader,
},
});

export const moduleLoader = {
Expand Down
75 changes: 49 additions & 26 deletions packages/features/bookings/lib/service/RegularBookingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import AssignmentReasonRecorder from "@calcom/features/ee/round-robin/assignment
import { BookingLocationService } from "@calcom/features/ee/round-robin/lib/bookingLocationService";
import { getAllWorkflowsFromEventType } from "@calcom/features/ee/workflows/lib/getAllWorkflowsFromEventType";
import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService";
import type { WorkflowTasker } from "@calcom/features/ee/workflows/lib/tasker/WorkflowTasker";
import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository";
import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents";
import { getEventName, updateHostInEventName } from "@calcom/features/eventtypes/lib/eventNaming";
Expand Down Expand Up @@ -480,6 +481,7 @@ export interface IBookingServiceDependencies {
bookingEmailAndSmsTasker: BookingEmailAndSmsTasker;
featuresRepository: FeaturesRepository;
bookingEventHandler: BookingEventHandlerService;
workflowTasker: WorkflowTasker;
}

async function validateRescheduleRestrictions({
Expand Down Expand Up @@ -2831,37 +2833,58 @@ async function handler(
isTeamEventType,
});

// Unused until we deploy to trigger.dev production
// for now we only enable for cal.com org and we keep our current email system
// cal.com org members will see emails in double while we test
if (ENABLE_ASYNC_TASKER && !noEmail) {
try {
if (orgId) {
const hasTeamFeature = await deps.featuresRepository.checkIfTeamHasFeature(
orgId,
"booking-email-sms-tasker"
);
if (hasTeamFeature) {
await deps.bookingEmailAndSmsTasker.send({
action: bookingEmailsAndSmsTaskerAction,
schedulingType: evtWithMetadata.eventType.schedulingType,
payload: {
// Unused until we deploy to trigger.dev production
// for now we only enable for cal.com org and we keep our current email system
// cal.com org members will see emails in double while we test
if (ENABLE_ASYNC_TASKER && !noEmail) {
try {
if (orgId) {
const hasTeamFeature = await deps.featuresRepository.checkIfTeamHasFeature(
orgId,
"booking-email-sms-tasker"
);
if (hasTeamFeature) {
await deps.bookingEmailAndSmsTasker.send({
action: bookingEmailsAndSmsTaskerAction,
schedulingType: evtWithMetadata.eventType.schedulingType,
payload: {
bookingId: booking.id,
conferenceCredentialId,
platformClientId,
platformRescheduleUrl,
platformCancelUrl,
platformBookingUrl,
isRescheduledByBooker: reqBody.rescheduledBy === bookerEmail,
},
});
}
}
} catch (err) {
tracingLogger.error("bookingEmailAndSmsTasker error:", err);
}
}

if (ENABLE_ASYNC_TASKER && rescheduleUid) {
try {
if (orgId) {
const hasWorkflowTaskerFeature = await deps.featuresRepository.checkIfTeamHasFeature(
orgId,
"workflow-tasker"
);
if (hasWorkflowTaskerFeature) {
await deps.workflowTasker.scheduleRescheduleWorkflows({
bookingId: booking.id,
conferenceCredentialId,
platformClientId,
platformRescheduleUrl,
platformCancelUrl,
platformBookingUrl,
isRescheduledByBooker: reqBody.rescheduledBy === bookerEmail,
},
});
smsReminderNumber: smsReminderNumber || null,
hideBranding: !!eventType.owner?.hideBranding,
seatReferenceUid: evt.attendeeSeatId,
});
}
}
} catch (err) {
tracingLogger.error("workflowTasker error:", err);
}
} catch (err) {
tracingLogger.error("bookingEmailAndSmsTasker error:", err);
}
}
}

// TODO: Refactor better so this booking object is not passed
// all around and instead the individual fields are sent as args.
Expand Down
54 changes: 47 additions & 7 deletions packages/features/bookings/repositories/BookingRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1581,14 +1581,54 @@ async updateMany({ where, data }: { where: BookingWhereInput; data: BookingUpdat
});
}

async getBookingForCalEventBuilderFromUid(bookingUid: string) {
return this.prismaClient.booking.findUnique({
where: { uid: bookingUid },
select: selectStatementToGetBookingForCalEventBuilder,
});
}
async getBookingForCalEventBuilderFromUid(bookingUid: string) {
return this.prismaClient.booking.findUnique({
where: { uid: bookingUid },
select: selectStatementToGetBookingForCalEventBuilder,
});
}

async getBookingForWorkflowTasker(bookingId: number) {
return await this.prismaClient.booking.findUnique({
where: { id: bookingId },
select: {
...selectStatementToGetBookingForCalEventBuilder,
id: true,
eventType: {
select: {
...selectStatementToGetBookingForCalEventBuilder.eventType.select,
teamId: true,
userId: true,
parentId: true,
hosts: {
select: {
userId: true,
isFixed: true,
user: {
select: {
id: true,
name: true,
email: true,
username: true,
timeZone: true,
locale: true,
timeFormat: true,
destinationCalendar: {
select: {
primaryEmail: true,
},
},
},
},
},
},
},
},
},
});
}

async findByIdIncludeDestinationCalendar(bookingId: number) {
async findByIdIncludeDestinationCalendar(bookingId: number) {
return await this.prismaClient.booking.findUnique({
where: {
id: bookingId,
Expand Down
2 changes: 2 additions & 0 deletions packages/features/di/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BOOKING_DI_TOKENS } from "@calcom/features/bookings/di/tokens";
import { BOOKING_AUDIT_DI_TOKENS } from "@calcom/features/booking-audit/di/tokens";
import { WORKFLOW_DI_TOKENS } from "@calcom/features/ee/workflows/di/tokens";
import { FEATURE_OPT_IN_DI_TOKENS } from "@calcom/features/feature-opt-in/di/tokens";
import { FLAGS_DI_TOKENS } from "@calcom/features/flags/di/tokens";
import { HASHED_LINK_DI_TOKENS } from "@calcom/features/hashedLink/di/tokens";
Expand Down Expand Up @@ -85,4 +86,5 @@ export const DI_TOKENS = {
...WATCHLIST_DI_TOKENS,
...ORGANIZATION_DI_TOKENS,
...WEBHOOK_TOKENS,
...WORKFLOW_DI_TOKENS,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "@calcom/features/di/di";
import { moduleLoader as loggerServiceModule } from "@calcom/features/di/shared/services/logger.service";
import { WorkflowSyncTasker } from "@calcom/features/ee/workflows/lib/tasker/WorkflowSyncTasker";

import { moduleLoader as WorkflowTaskServiceModuleLoader } from "./WorkflowTaskService.module";
import { WORKFLOW_TASKER_DI_TOKENS } from "./tokens";

const thisModule = createModule();
const token = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_SYNC_TASKER;
const moduleToken = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_SYNC_TASKER_MODULE;
const loadModule = bindModuleToClassOnToken({
module: thisModule,
moduleToken,
token,
classs: WorkflowSyncTasker,
depsMap: {
logger: loggerServiceModule,
workflowTaskService: WorkflowTaskServiceModuleLoader,
},
});

export const moduleLoader = {
token,
loadModule,
} satisfies ModuleLoader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "@calcom/features/di/di";
import { moduleLoader as bookingRepositoryModuleLoader } from "@calcom/features/di/modules/Booking";
import { moduleLoader as loggerServiceModule } from "@calcom/features/di/shared/services/logger.service";
import { WorkflowTaskService } from "@calcom/features/ee/workflows/lib/tasker/WorkflowTaskService";

import { WORKFLOW_TASKER_DI_TOKENS } from "./tokens";

const thisModule = createModule();
const token = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TASK_SERVICE;
const moduleToken = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TASK_SERVICE_MODULE;
const loadModule = bindModuleToClassOnToken({
module: thisModule,
moduleToken,
token,
classs: WorkflowTaskService,
depsMap: {
logger: loggerServiceModule,
bookingRepository: bookingRepositoryModuleLoader,
},
});

export const moduleLoader = {
token,
loadModule,
} satisfies ModuleLoader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createContainer } from "@calcom/features/di/di";

import { type WorkflowTasker, moduleLoader as workflowTaskerModuleLoader } from "./WorkflowTasker.module";

const workflowTaskerContainer = createContainer();

export function getWorkflowTasker(): WorkflowTasker {
workflowTaskerModuleLoader.loadModule(workflowTaskerContainer);
return workflowTaskerContainer.get<WorkflowTasker>(workflowTaskerModuleLoader.token);
}
27 changes: 27 additions & 0 deletions packages/features/ee/workflows/di/tasker/WorkflowTasker.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "@calcom/features/di/di";
import { moduleLoader as loggerServiceModule } from "@calcom/features/di/shared/services/logger.service";
import { WorkflowTasker } from "@calcom/features/ee/workflows/lib/tasker/WorkflowTasker";

import { moduleLoader as WorkflowSyncTasker } from "./WorkflowSyncTasker.module";
import { moduleLoader as WorkflowTriggerTasker } from "./WorkflowTriggerDevTasker.module";
import { WORKFLOW_TASKER_DI_TOKENS } from "./tokens";

const thisModule = createModule();
const token = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TASKER;
const moduleToken = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TASKER_MODULE;
const loadModule = bindModuleToClassOnToken({
module: thisModule,
moduleToken,
token,
classs: WorkflowTasker,
depsMap: {
logger: loggerServiceModule,
asyncTasker: WorkflowTriggerTasker,
syncTasker: WorkflowSyncTasker,
},
});

export const moduleLoader = {
token,
loadModule,
} satisfies ModuleLoader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "@calcom/features/di/di";
import { moduleLoader as loggerServiceModule } from "@calcom/features/di/shared/services/logger.service";
import { WorkflowTriggerDevTasker } from "@calcom/features/ee/workflows/lib/tasker/WorkflowTriggerDevTasker";

import { WORKFLOW_TASKER_DI_TOKENS } from "./tokens";

const thisModule = createModule();
const token = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TRIGGER_TASKER;
const moduleToken = WORKFLOW_TASKER_DI_TOKENS.WORKFLOW_TRIGGER_TASKER_MODULE;
const loadModule = bindModuleToClassOnToken({
module: thisModule,
moduleToken,
token,
classs: WorkflowTriggerDevTasker,
depsMap: {
logger: loggerServiceModule,
},
});

export const moduleLoader = {
token,
loadModule,
} satisfies ModuleLoader;
10 changes: 10 additions & 0 deletions packages/features/ee/workflows/di/tasker/tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const WORKFLOW_TASKER_DI_TOKENS = {
WORKFLOW_SYNC_TASKER: Symbol("WorkflowSyncTasker"),
WORKFLOW_SYNC_TASKER_MODULE: Symbol("WorkflowSyncTaskerModule"),
WORKFLOW_TASKER: Symbol("WorkflowTasker"),
WORKFLOW_TASKER_MODULE: Symbol("WorkflowTaskerModule"),
WORKFLOW_TRIGGER_TASKER: Symbol("WorkflowTriggerDevTasker"),
WORKFLOW_TRIGGER_TASKER_MODULE: Symbol("WorkflowTriggerDevTaskerModule"),
WORKFLOW_TASK_SERVICE: Symbol("WorkflowTaskService"),
WORKFLOW_TASK_SERVICE_MODULE: Symbol("WorkflowTaskServiceModule"),
};
5 changes: 5 additions & 0 deletions packages/features/ee/workflows/di/tokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { WORKFLOW_TASKER_DI_TOKENS } from "./tasker/tokens";

export const WORKFLOW_DI_TOKENS = {
...WORKFLOW_TASKER_DI_TOKENS,
};
20 changes: 20 additions & 0 deletions packages/features/ee/workflows/lib/tasker/WorkflowSyncTasker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { nanoid } from "nanoid";

import type { ITaskerDependencies } from "@calcom/lib/tasker/types";

import type { IWorkflowTasker } from "./types";
import type { WorkflowTaskService } from "./WorkflowTaskService";

export interface IWorkflowSyncTaskerDependencies {
workflowTaskService: WorkflowTaskService;
}

export class WorkflowSyncTasker implements IWorkflowTasker {
constructor(public readonly dependencies: ITaskerDependencies & IWorkflowSyncTaskerDependencies) {}

async scheduleRescheduleWorkflows(payload: Parameters<IWorkflowTasker["scheduleRescheduleWorkflows"]>[0]) {
const runId = `sync_${nanoid(10)}`;
await this.dependencies.workflowTaskService.scheduleRescheduleWorkflows(payload);
return { runId };
}
}
Loading
Loading