fix: Handle account user lookup fields for queued form responses (#23811)
* Add constants for queued response id query string * Ignore eslint - app store imports * Return `routingFormResponseId` or `queuedFormResponseId` from URL params * Pass routingForm params to `getTeamMemberEmailForResponseOrContact` * Handle getting form responses for queued form responses * Type fix * add test * Add tests --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
co-authored by
Hariom Balhara
Udit Takkar
parent
e9c6af562e
commit
88391c7942
@@ -5,7 +5,10 @@ import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
|
||||
import { getCRMContactOwnerForRRLeadSkip } from "@calcom/app-store/_utils/CRMRoundRobinSkip";
|
||||
import bookingFormHandlers from "@calcom/app-store/routing-forms/appBookingFormHandler";
|
||||
import { ROUTING_FORM_RESPONSE_ID_QUERY_STRING } from "@calcom/app-store/routing-forms/lib/constants";
|
||||
import {
|
||||
ROUTING_FORM_RESPONSE_ID_QUERY_STRING,
|
||||
ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING,
|
||||
} from "@calcom/app-store/routing-forms/lib/constants";
|
||||
import { RouteActionType } from "@calcom/app-store/routing-forms/zod";
|
||||
import { getTeamMemberEmailForResponseOrContactUsingUrlQuery } from "@calcom/lib/server/getTeamMemberEmailFromCrm";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
@@ -52,24 +55,22 @@ function mockBookingFormHandler({
|
||||
);
|
||||
}
|
||||
|
||||
async function createRoutingFormWithResponse({
|
||||
formData,
|
||||
}: {
|
||||
formData: {
|
||||
routes: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
queryValue?: any;
|
||||
action: {
|
||||
eventTypeId: number;
|
||||
type: RouteActionType;
|
||||
value: string;
|
||||
};
|
||||
attributeRoutingConfig: {
|
||||
skipContactOwner: boolean;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
}) {
|
||||
type RoutingFormData = {
|
||||
routes: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
queryValue?: any;
|
||||
action: {
|
||||
eventTypeId: number;
|
||||
type: RouteActionType;
|
||||
value: string;
|
||||
};
|
||||
attributeRoutingConfig: {
|
||||
skipContactOwner: boolean;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
async function _createRoutingFormBase({ formData }: { formData: RoutingFormData }) {
|
||||
const user = await prismock.user.create({
|
||||
data: {
|
||||
name: "Routing Form User",
|
||||
@@ -100,6 +101,12 @@ async function createRoutingFormWithResponse({
|
||||
},
|
||||
});
|
||||
|
||||
return { form, routeId };
|
||||
}
|
||||
|
||||
async function createRoutingFormWithResponse({ formData }: { formData: RoutingFormData }) {
|
||||
const { form, routeId } = await _createRoutingFormBase({ formData });
|
||||
|
||||
const responseRecord = await prismock.app_RoutingForms_FormResponse.create({
|
||||
data: {
|
||||
chosenRouteId: routeId,
|
||||
@@ -115,6 +122,26 @@ async function createRoutingFormWithResponse({
|
||||
return { form, responseRecord };
|
||||
}
|
||||
|
||||
async function createRoutingFormWithQueuedResponse({ formData }: { formData: RoutingFormData }) {
|
||||
const { form, routeId } = await _createRoutingFormBase({ formData });
|
||||
|
||||
const queuedResponseId = v4();
|
||||
const queuedResponseRecord = await prismock.app_RoutingForms_QueuedFormResponse.create({
|
||||
data: {
|
||||
id: queuedResponseId,
|
||||
chosenRouteId: routeId,
|
||||
response: {},
|
||||
form: {
|
||||
connect: {
|
||||
id: form.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return { form, queuedResponseRecord };
|
||||
}
|
||||
|
||||
async function createHostForEvent({
|
||||
eventTypeData,
|
||||
userData,
|
||||
@@ -254,166 +281,250 @@ describe("getTeamMemberEmailForResponseOrContactUsingUrlQuery", () => {
|
||||
});
|
||||
|
||||
describe("Booking form handler", () => {
|
||||
it("should return teamMember email through booking form handler when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
describe("when responseId is provided", () => {
|
||||
it("should return teamMember email through booking form handler when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(teamMemberEmail);
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
it("should return null when skipContactOwner is true even when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
// Because skipContactOwner is true, the booking form handler should return null
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
|
||||
expect(result.email).toBe(teamMemberEmail);
|
||||
it("should return null when when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided but the returned email isn't an event member", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "ownerNotInEventType@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
const SOME_OTHER_EVENT_ID = 200;
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: SOME_OTHER_EVENT_ID,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
|
||||
it("should return null when cal.routingFormResponseId is provided but cal.salesforce.xxxx is not", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.somethingelse.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
});
|
||||
describe("when queuedFormResponseId is provided", () => {
|
||||
it("should return teamMember email through booking form handler when cal.queuedFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
it("should return null when skipContactOwner is true even when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
const { queuedResponseRecord } = await createRoutingFormWithQueuedResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING]: queuedResponseRecord.id,
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(teamMemberEmail);
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
it("should return null when skipContactOwner is true even when cal.queuedFormResponseId and cal.salesforce.xxxx=true is provided", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
// Because skipContactOwner is true, the booking form handler should return null
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
|
||||
it("should return null when when cal.routingFormResponseId and cal.salesforce.xxxx=true is provided but the returned email isn't an event member", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "ownerNotInEventType@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
const SOME_OTHER_EVENT_ID = 200;
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: SOME_OTHER_EVENT_ID,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
const { queuedResponseRecord } = await createRoutingFormWithQueuedResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: true },
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING]: queuedResponseRecord.id,
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
// Because skipContactOwner is true, the booking form handler should return null
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.salesforce.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
|
||||
it("should return null when cal.routingFormResponseId is provided but cal.salesforce.xxxx is not", async () => {
|
||||
const bookerEmail = "booker@example.com";
|
||||
const teamMemberEmail = "owner@example.com";
|
||||
mockBookingFormHandler({ bookerEmail, teamMemberEmail });
|
||||
await createHostForEvent({
|
||||
eventTypeData: {
|
||||
id: mockEventData.id,
|
||||
},
|
||||
userData: {
|
||||
email: teamMemberEmail,
|
||||
},
|
||||
});
|
||||
|
||||
const { responseRecord } = await createRoutingFormWithResponse({
|
||||
formData: {
|
||||
routes: [
|
||||
{
|
||||
action: {
|
||||
eventTypeId: 1,
|
||||
type: RouteActionType.EventTypeRedirectUrl,
|
||||
value: "/team/sales",
|
||||
},
|
||||
attributeRoutingConfig: { skipContactOwner: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const result = await getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
query: {
|
||||
email: bookerEmail,
|
||||
[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]: responseRecord.id.toString(),
|
||||
"cal.somethingelse.xxx": "true",
|
||||
},
|
||||
eventData: mockEventData,
|
||||
});
|
||||
|
||||
expect(result.email).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export const ROUTING_FORM_RESPONSE_ID_QUERY_STRING = "cal.routingFormResponseId";
|
||||
export const ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING = "cal.queuedFormResponseId";
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
<div id="cal-booking-routingFormFullPrerender">
|
||||
<hr/>
|
||||
<a href="?only=ns:routingFormFullPrerender&debug=1¶m.email=test@example.com">Routing Form - Prerender Headless Router itself queuing the form response</a>
|
||||
NOTE: Pass query param param.formId=FORM_UID_HERE to test with a particular routing form
|
||||
<p>1. As page is loading, we prerender the headless router for the email passed as param.email</p>
|
||||
<p>2. Whenever email changes and onblur happens, the prerender is triggered for the new email and previous prerendered modal is removed</p>
|
||||
<p>3. The prerender of the headless router queues the form response and doesn't really record it. When the actual booking is made, the form response is recorded from the queue</p>
|
||||
@@ -145,7 +146,8 @@
|
||||
});
|
||||
window.routingFormFullPrerender = {
|
||||
buildRouterUrl: ({skills, location, name, email, formId}) => {
|
||||
return `router?form=${formId}&skills=${skills}&Location=${location}&name=${name}&Email=${email}&Rating=5`;
|
||||
// Send `email` as well as `Email` because E2e Tests currently use `Email` and `email` is needed by contact owner lookup. It doesn't accept Uppercase Email
|
||||
return `router?form=${formId}&skills=${skills}&Location=${location}&name=${name}&Email=${email}&email=${email}&Rating=5`;
|
||||
},
|
||||
onFormSubmit: (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import type { ParsedUrlQuery } from "querystring";
|
||||
|
||||
/* eslint-disable */
|
||||
import { getCRMContactOwnerForRRLeadSkip } from "@calcom/app-store/_utils/CRMRoundRobinSkip";
|
||||
import { ROUTING_FORM_RESPONSE_ID_QUERY_STRING } from "@calcom/app-store/routing-forms/lib/constants";
|
||||
import {
|
||||
ROUTING_FORM_RESPONSE_ID_QUERY_STRING,
|
||||
ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING,
|
||||
} from "@calcom/app-store/routing-forms/lib/constants";
|
||||
import { enabledAppSlugs } from "@calcom/app-store/routing-forms/lib/enabledApps";
|
||||
import type { AttributeRoutingConfig, LocalRoute } from "@calcom/app-store/routing-forms/types/types";
|
||||
import { zodRoutes as routesSchema } from "@calcom/app-store/routing-forms/zod";
|
||||
|
||||
/* eslint-enable */
|
||||
import logger from "@calcom/lib/logger";
|
||||
import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import { RoutingFormResponseRepository } from "@calcom/lib/server/repository/formResponse";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Prisma } from "@calcom/prisma/client";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
@@ -38,16 +45,25 @@ async function findUserByEmailWhoIsAHostOfEventType({
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the form response id or the queued response id */
|
||||
function getRoutingFormResponseIdFromQuery(query: ParsedUrlQuery) {
|
||||
const routingFormResponseIdAsNumber = Number(query[ROUTING_FORM_RESPONSE_ID_QUERY_STRING]);
|
||||
const routingFormResponseId = isNaN(routingFormResponseIdAsNumber) ? null : routingFormResponseIdAsNumber;
|
||||
return routingFormResponseId;
|
||||
|
||||
if (routingFormResponseId) return { routingFormResponseId, queuedFormResponseId: null };
|
||||
|
||||
const queuedFormResponseId = query[ROUTING_FORM_QUEUED_RESPONSE_ID_QUERY_STRING];
|
||||
if (queuedFormResponseId && typeof queuedFormResponseId === "string")
|
||||
return { queuedFormResponseId, routingFormResponseId: null };
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getAttributeRoutingConfig(
|
||||
data:
|
||||
| {
|
||||
routingFormResponseId: number;
|
||||
routingFormResponseId?: number | null;
|
||||
queuedFormResponseId?: string | null;
|
||||
eventTypeId: number;
|
||||
}
|
||||
| {
|
||||
@@ -57,20 +73,14 @@ async function getAttributeRoutingConfig(
|
||||
if ("route" in data) {
|
||||
return data.route.attributeRoutingConfig ?? null;
|
||||
}
|
||||
const { routingFormResponseId } = data;
|
||||
const { routingFormResponseId, queuedFormResponseId } = data;
|
||||
const routingFormResponseRepository = new RoutingFormResponseRepository(prisma);
|
||||
|
||||
const routingFormResponseQuery = await prisma.app_RoutingForms_FormResponse.findUnique({
|
||||
where: {
|
||||
id: routingFormResponseId,
|
||||
},
|
||||
include: {
|
||||
form: {
|
||||
select: {
|
||||
routes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const routingFormResponseQuery = routingFormResponseId
|
||||
? await routingFormResponseRepository.findFormResponseIncludeForm({ routingFormResponseId })
|
||||
: queuedFormResponseId
|
||||
? await routingFormResponseRepository.findQueuedFormResponseIncludeForm({ queuedFormResponseId })
|
||||
: null;
|
||||
|
||||
if (!routingFormResponseQuery || !routingFormResponseQuery?.form.routes) return null;
|
||||
const parsedRoutes = routesSchema.safeParse(routingFormResponseQuery?.form.routes);
|
||||
@@ -196,12 +206,14 @@ async function getTeamMemberEmailForResponseOrContact({
|
||||
bookerEmail,
|
||||
eventData,
|
||||
routingFormResponseId,
|
||||
queuedFormResponseId,
|
||||
chosenRoute,
|
||||
crmAppSlug,
|
||||
}: {
|
||||
bookerEmail: string;
|
||||
eventData: EventData;
|
||||
routingFormResponseId?: number | null;
|
||||
queuedFormResponseId?: string | null;
|
||||
/**
|
||||
* If provided, we won't go look for the route from DB.
|
||||
*/
|
||||
@@ -216,11 +228,12 @@ async function getTeamMemberEmailForResponseOrContact({
|
||||
const eventTypeId = eventData.id;
|
||||
if (eventData.schedulingType !== SchedulingType.ROUND_ROBIN) return returnNullValue;
|
||||
|
||||
const attributeRoutingConfigGetterData = routingFormResponseId
|
||||
? { routingFormResponseId, eventTypeId }
|
||||
: chosenRoute
|
||||
? { route: chosenRoute }
|
||||
: null;
|
||||
const attributeRoutingConfigGetterData =
|
||||
routingFormResponseId || queuedFormResponseId
|
||||
? { routingFormResponseId, queuedFormResponseId, eventTypeId }
|
||||
: chosenRoute
|
||||
? { route: chosenRoute }
|
||||
: null;
|
||||
|
||||
// If we have found crmAppSlug, it means that the CRM App in the routing-form will handle the logic
|
||||
if (attributeRoutingConfigGetterData && crmAppSlug) {
|
||||
@@ -271,13 +284,15 @@ export async function getTeamMemberEmailForResponseOrContactUsingUrlQuery({
|
||||
|
||||
const crmAppSlug = getEnabledRoutingFormAppSlugFromQuery(query);
|
||||
|
||||
const routingFormResponseId = getRoutingFormResponseIdFromQuery(query);
|
||||
const routingFormResponseIdAndQueuedFormResponseId = getRoutingFormResponseIdFromQuery(query);
|
||||
|
||||
return await getTeamMemberEmailForResponseOrContact({
|
||||
bookerEmail: query.email,
|
||||
eventData,
|
||||
routingFormResponseId,
|
||||
chosenRoute,
|
||||
crmAppSlug,
|
||||
...(routingFormResponseIdAndQueuedFormResponseId
|
||||
? { ...routingFormResponseIdAndQueuedFormResponseId }
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user