Files
calendar/packages/features/bookings/lib/handleBookingRequested.ts
T
Rajiv SahalGitHubunknown <>rajiv@cal.com <sahalrajiv6900@gmail.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
5d65a0f091 fix: hide cal branding for orgs/teams (#27643)
* 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>
2026-02-25 20:53:01 +09:00

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));
}
}