Skip to content

Commit

Permalink
refactor: loadUsers and move to separate file (calcom#15532)
Browse files Browse the repository at this point in the history
* refactor: loadUsers and move to separate file

* fix: improvement

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
  • Loading branch information
3 people authored and p6l-richard committed Jul 22, 2024
1 parent 431345d commit 7c201f8
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 74 deletions.
75 changes: 1 addition & 74 deletions packages/features/bookings/lib/handleNewBooking.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { App, DestinationCalendar, EventTypeCustomInput } from "@prisma/client";
import { Prisma } from "@prisma/client";
import type { IncomingMessage } from "http";
import { isValidPhoneNumber } from "libphonenumber-js";
// eslint-disable-next-line no-restricted-imports
import { cloneDeep } from "lodash";
Expand Down Expand Up @@ -41,7 +40,6 @@ import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger";
import { isEventTypeLoggingEnabled } from "@calcom/features/bookings/lib/isEventTypeLoggingEnabled";
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import {
allowDisablingAttendeeConfirmationEmails,
allowDisablingHostConfirmationEmails,
Expand Down Expand Up @@ -81,7 +79,6 @@ import { getPiiFreeCalendarEvent, getPiiFreeEventType, getPiiFreeUser } from "@c
import { safeStringify } from "@calcom/lib/safeStringify";
import { checkBookingLimits, checkDurationLimits, getLuckyUser } from "@calcom/lib/server";
import { getTranslation } from "@calcom/lib/server/i18n";
import { UserRepository } from "@calcom/lib/server/repository/user";
import { slugify } from "@calcom/lib/slugify";
import { updateWebUser as syncServicesUpdateWebUser } from "@calcom/lib/sync/SyncServiceManager";
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
Expand Down Expand Up @@ -110,6 +107,7 @@ import { checkForConflicts } from "./conflictChecker/checkForConflicts";
import { getAllCredentials } from "./getAllCredentialsForUsersOnEvent/getAllCredentials";
import { refreshCredentials } from "./getAllCredentialsForUsersOnEvent/refreshCredentials";
import getBookingDataSchema from "./getBookingDataSchema";
import { loadUsers } from "./handleNewBooking/loadUsers";
import handleSeats from "./handleSeats/handleSeats";
import type { BookingSeat } from "./handleSeats/types";

Expand Down Expand Up @@ -292,40 +290,6 @@ type IsFixedAwareUser = User & {
priority?: number;
};

const loadUsers = async (eventType: NewBookingEventType, dynamicUserList: string[], req: IncomingMessage) => {
try {
if (!eventType.id) {
if (!Array.isArray(dynamicUserList) || dynamicUserList.length === 0) {
throw new Error("dynamicUserList is not properly defined or empty.");
}
const { isValidOrgDomain, currentOrgDomain } = orgDomainConfig(req);
const users = await findUsersByUsername({
usernameList: dynamicUserList,
orgSlug: isValidOrgDomain ? currentOrgDomain : null,
});
return users;
}
const hosts = eventType.hosts || [];

if (!Array.isArray(hosts)) {
throw new Error("eventType.hosts is not properly defined.");
}

const users = hosts.map(({ user, isFixed, priority }) => ({
...user,
isFixed,
priority,
}));

return users.length ? users : eventType.users;
} catch (error) {
if (error instanceof HttpError || error instanceof Prisma.PrismaClientKnownRequestError) {
throw new HttpError({ statusCode: 400, message: error.message });
}
throw new HttpError({ statusCode: 500, message: "Unable to load users" });
}
};

export async function ensureAvailableUsers(
eventType: Awaited<ReturnType<typeof getEventTypesFromDB>> & {
users: IsFixedAwareUser[];
Expand Down Expand Up @@ -2650,40 +2614,3 @@ function handleCustomInputs(
}
});
}

/**
* This method is mostly same as the one in UserRepository but it includes a lot more relations which are specific requirement here
* TODO: Figure out how to keep it in UserRepository and use it here
*/
export const findUsersByUsername = async ({
usernameList,
orgSlug,
}: {
orgSlug: string | null;
usernameList: string[];
}) => {
log.debug("findUsersByUsername", { usernameList, orgSlug });
const { where, profiles } = await UserRepository._getWhereClauseForFindingUsersByUsername({
orgSlug,
usernameList,
});
return (
await prisma.user.findMany({
where,
select: {
...userSelect.select,
credentials: {
select: credentialForCalendarServiceSelect,
},
metadata: true,
},
})
).map((user) => {
const profile = profiles?.find((profile) => profile.user.id === user.id) ?? null;
return {
...user,
organizationId: profile?.organizationId ?? null,
profile,
};
});
};
87 changes: 87 additions & 0 deletions packages/features/bookings/lib/handleNewBooking/loadUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Prisma } from "@prisma/client";
import type { IncomingMessage } from "http";

import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { HttpError } from "@calcom/lib/http-error";
import logger from "@calcom/lib/logger";
import { UserRepository } from "@calcom/lib/server/repository/user";
import prisma, { userSelect } from "@calcom/prisma";
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";

import type { NewBookingEventType } from "../handleNewBooking";

const log = logger.getSubLogger({ prefix: ["[loadUsers]:handleNewBooking "] });

type EventType = Pick<NewBookingEventType, "hosts" | "users" | "id">;

export const loadUsers = async (eventType: EventType, dynamicUserList: string[], req: IncomingMessage) => {
try {
const { currentOrgDomain } = orgDomainConfig(req);

return eventType.id
? await loadUsersByEventType(eventType)
: await loadDynamicUsers(dynamicUserList, currentOrgDomain);
} catch (error) {
if (error instanceof HttpError || error instanceof Prisma.PrismaClientKnownRequestError) {
throw new HttpError({ statusCode: 400, message: error.message });
}
throw new HttpError({ statusCode: 500, message: "Unable to load users" });
}
};

const loadUsersByEventType = async (eventType: EventType): Promise<NewBookingEventType["users"]> => {
const hosts = eventType.hosts || [];
const users = hosts.map(({ user, isFixed, priority }) => ({
...user,
isFixed,
priority,
}));
return users.length ? users : eventType.users;
};

const loadDynamicUsers = async (dynamicUserList: string[], currentOrgDomain: string | null) => {
if (!Array.isArray(dynamicUserList) || dynamicUserList.length === 0) {
throw new Error("dynamicUserList is not properly defined or empty.");
}
return findUsersByUsername({
usernameList: dynamicUserList,
orgSlug: !!currentOrgDomain ? currentOrgDomain : null,
});
};

/**
* This method is mostly same as the one in UserRepository but it includes a lot more relations which are specific requirement here
* TODO: Figure out how to keep it in UserRepository and use it here
*/
export const findUsersByUsername = async ({
usernameList,
orgSlug,
}: {
orgSlug: string | null;
usernameList: string[];
}) => {
log.debug("findUsersByUsername", { usernameList, orgSlug });
const { where, profiles } = await UserRepository._getWhereClauseForFindingUsersByUsername({
orgSlug,
usernameList,
});
return (
await prisma.user.findMany({
where,
select: {
...userSelect.select,
credentials: {
select: credentialForCalendarServiceSelect,
},
metadata: true,
},
})
).map((user) => {
const profile = profiles?.find((profile) => profile.user.id === user.id) ?? null;
return {
...user,
organizationId: profile?.organizationId ?? null,
profile,
};
});
};

0 comments on commit 7c201f8

Please sign in to comment.