* fix: hide branding for teams * fix: remove unused organizationId and username fields from profiles select Addresses Cubic AI review feedback (confidence 9/10) to select only the profile fields that are actually used. The organizationId and username fields were fetched but never referenced in this function. Co-Authored-By: unknown <> * fix: unit tests * fix: add prisma named export to test mock Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * Add tests: packages/features/profile/lib/hideBranding.test.ts Generated by Paragon from proposal for PR #27643 * chore: implement cubic feedback * fix: merge conflicts * fix: unit tests * fixup * refactor: implement DI pattern for event type service * fix: atoms build --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
122 lines
4.2 KiB
TypeScript
122 lines
4.2 KiB
TypeScript
import { sendAttendeeRequestEmailAndSMS, sendOrganizerRequestEmail } from "@calcom/emails/email-manager";
|
|
import { getWebhookProducer } from "@calcom/features/di/webhooks/containers/webhook";
|
|
import { CreditService } from "@calcom/features/ee/billing/credit-service";
|
|
import { getAllWorkflowsFromEventType } from "@calcom/features/ee/workflows/lib/getAllWorkflowsFromEventType";
|
|
import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService";
|
|
import type { Workflow } from "@calcom/features/ee/workflows/lib/types";
|
|
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
|
|
import logger from "@calcom/lib/logger";
|
|
import { safeStringify } from "@calcom/lib/safeStringify";
|
|
import type { Prisma } from "@calcom/prisma/client";
|
|
import { WorkflowTriggerEvents } from "@calcom/prisma/enums";
|
|
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
|
import type { CalendarEvent } from "@calcom/types/Calendar";
|
|
|
|
const log = logger.getSubLogger({ prefix: ["[handleBookingRequested] book:user"] });
|
|
|
|
/**
|
|
* Supposed to do whatever is needed when a booking is requested.
|
|
*/
|
|
export async function handleBookingRequested(args: {
|
|
evt: CalendarEvent;
|
|
/** When booking is from a platform/OAuth client, pass so platform webhook subscribers are notified */
|
|
oAuthClientId?: string | null;
|
|
booking: {
|
|
smsReminderNumber: string | null;
|
|
eventType: {
|
|
workflows: {
|
|
workflow: Workflow;
|
|
}[];
|
|
owner: {
|
|
hideBranding: boolean;
|
|
} | null;
|
|
team?: {
|
|
parentId: number | null;
|
|
} | null;
|
|
currency: string;
|
|
hosts?: {
|
|
user: {
|
|
email: string;
|
|
destinationCalendar?: {
|
|
primaryEmail: string | null;
|
|
} | null;
|
|
};
|
|
}[];
|
|
description: string | null;
|
|
id: number;
|
|
length: number;
|
|
price: number;
|
|
requiresConfirmation: boolean;
|
|
title: string;
|
|
teamId?: number | null;
|
|
metadata: Prisma.JsonValue;
|
|
} | null;
|
|
eventTypeId: number | null;
|
|
userId: number | null;
|
|
id: number;
|
|
};
|
|
}) {
|
|
const { evt, booking, oAuthClientId } = args;
|
|
|
|
log.debug("Emails: Sending booking requested emails");
|
|
|
|
await sendOrganizerRequestEmail({ ...evt }, booking?.eventType?.metadata as EventTypeMetadata);
|
|
await sendAttendeeRequestEmailAndSMS(
|
|
{ ...evt },
|
|
evt.attendees[0],
|
|
booking?.eventType?.metadata as EventTypeMetadata
|
|
);
|
|
|
|
const orgId = await getOrgIdFromMemberOrTeamId({
|
|
memberId: booking.userId,
|
|
teamId: booking.eventType?.teamId,
|
|
});
|
|
|
|
try {
|
|
if (!evt.uid) {
|
|
log.error("Cannot queue BOOKING_REQUESTED webhook: missing booking uid");
|
|
} else {
|
|
try {
|
|
// Keep params in sync with RegularBookingService (non-payment path) so
|
|
// subscriber filtering (userId, eventTypeId, teamId, orgId, oAuthClientId) is consistent.
|
|
const webhookProducer = getWebhookProducer();
|
|
await webhookProducer.queueBookingRequestedWebhook({
|
|
bookingUid: evt.uid,
|
|
userId: booking.userId ?? undefined,
|
|
eventTypeId: booking.eventTypeId ?? undefined,
|
|
teamId: booking.eventType?.teamId ?? undefined,
|
|
orgId,
|
|
oAuthClientId: oAuthClientId ?? undefined,
|
|
});
|
|
} catch (error) {
|
|
log.error("Error queueing BOOKING_REQUESTED webhook", safeStringify(error));
|
|
}
|
|
}
|
|
|
|
const workflows = await getAllWorkflowsFromEventType(booking.eventType, booking.userId);
|
|
if (workflows.length > 0) {
|
|
const creditService = new CreditService();
|
|
|
|
await WorkflowService.scheduleWorkflowsFilteredByTriggerEvent({
|
|
workflows,
|
|
smsReminderNumber: booking.smsReminderNumber,
|
|
hideBranding: evt.hideBranding,
|
|
calendarEvent: {
|
|
...evt,
|
|
bookerUrl: evt.bookerUrl as string,
|
|
eventType: {
|
|
slug: evt.type,
|
|
hosts: booking.eventType?.hosts,
|
|
schedulingType: evt.schedulingType,
|
|
},
|
|
},
|
|
triggers: [WorkflowTriggerEvents.BOOKING_REQUESTED],
|
|
creditCheckFn: creditService.hasAvailableCredits.bind(creditService),
|
|
});
|
|
}
|
|
} catch (error) {
|
|
// Silently fail
|
|
log.error("Error in handleBookingRequested", safeStringify(error));
|
|
}
|
|
}
|