fix: fix data expose issue in routing form insights (#18207)
This commit is contained in:
@@ -56,11 +56,12 @@ function FormCard({ formName, fields }: FormCardProps) {
|
||||
|
||||
export function FailedBookingsByField() {
|
||||
const { filter } = useFilterContext();
|
||||
const { selectedTeamId, isAll, initialConfig, selectedRoutingFormId } = filter;
|
||||
const { selectedTeamId, selectedUserId, isAll, initialConfig, selectedRoutingFormId } = filter;
|
||||
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);
|
||||
|
||||
const { data } = trpc.viewer.insights.failedBookingsByField.useQuery(
|
||||
{
|
||||
userId: selectedUserId ?? undefined,
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: !!isAll,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
|
||||
@@ -33,6 +33,7 @@ import { useFilterContext } from "../context/provider";
|
||||
|
||||
interface DownloadButtonProps {
|
||||
teamId?: number;
|
||||
userId?: number;
|
||||
isAll?: boolean;
|
||||
routingFormId?: string;
|
||||
dateRange: [Dayjs, Dayjs, string | null];
|
||||
@@ -41,6 +42,7 @@ interface DownloadButtonProps {
|
||||
}
|
||||
|
||||
function DownloadButton({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
@@ -57,6 +59,7 @@ function DownloadButton({
|
||||
|
||||
try {
|
||||
const result = await utils.viewer.insights.routedToPerPeriodCsv.fetch({
|
||||
userId: userId ?? undefined,
|
||||
teamId: teamId ?? undefined,
|
||||
startDate: dateRange[0]?.toISOString() ?? "",
|
||||
endDate: dateRange[1]?.toISOString() ?? "",
|
||||
@@ -97,6 +100,7 @@ interface FormCardProps {
|
||||
onSearchChange: (value: string) => void;
|
||||
children: ReactNode;
|
||||
teamId?: number;
|
||||
userId?: number;
|
||||
isAll?: boolean;
|
||||
routingFormId?: string;
|
||||
dateRange: [Dayjs, Dayjs, string | null];
|
||||
@@ -109,6 +113,7 @@ function FormCard({
|
||||
onSearchChange,
|
||||
children,
|
||||
teamId,
|
||||
userId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
dateRange,
|
||||
@@ -141,6 +146,7 @@ function FormCard({
|
||||
/>
|
||||
</div>
|
||||
<DownloadButton
|
||||
userId={userId}
|
||||
teamId={teamId}
|
||||
isAll={isAll}
|
||||
routingFormId={routingFormId}
|
||||
@@ -214,7 +220,7 @@ const getPerformanceBadge = (performance: RoutedToTableRow["performance"], t: TF
|
||||
export function RoutedToPerPeriod() {
|
||||
const { t } = useLocale();
|
||||
const { filter } = useFilterContext();
|
||||
const { selectedTeamId, isAll, selectedRoutingFormId, dateRange } = filter;
|
||||
const { selectedTeamId, selectedUserId, isAll, selectedRoutingFormId, dateRange } = filter;
|
||||
const [selectedPeriod, setSelectedPeriod] = useQueryState("selectedPeriod", {
|
||||
defaultValue: "perWeek",
|
||||
});
|
||||
@@ -233,6 +239,7 @@ export function RoutedToPerPeriod() {
|
||||
const { data, fetchNextPage, isFetchingNextPage, hasNextPage, isLoading } =
|
||||
trpc.viewer.insights.routedToPerPeriod.useInfiniteQuery(
|
||||
{
|
||||
userId: selectedUserId ?? undefined,
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
startDate: dateRange[0]?.toISOString() ?? "",
|
||||
endDate: dateRange[1]?.toISOString() ?? "",
|
||||
@@ -327,6 +334,7 @@ export function RoutedToPerPeriod() {
|
||||
onPeriodChange={setSelectedPeriod}
|
||||
searchQuery={searchQuery}
|
||||
onSearchChange={setSearchQuery}
|
||||
userId={selectedUserId ?? undefined}
|
||||
teamId={selectedTeamId ?? undefined}
|
||||
isAll={isAll}
|
||||
routingFormId={selectedRoutingFormId ?? undefined}
|
||||
@@ -369,6 +377,7 @@ export function RoutedToPerPeriod() {
|
||||
onPeriodChange={setSelectedPeriod}
|
||||
searchQuery={searchQuery}
|
||||
onSearchChange={setSearchQuery}
|
||||
userId={selectedUserId ?? undefined}
|
||||
teamId={selectedTeamId ?? undefined}
|
||||
isAll={isAll}
|
||||
routingFormId={selectedRoutingFormId ?? undefined}
|
||||
|
||||
@@ -266,8 +266,17 @@ export function RoutingFormResponsesTableContent({
|
||||
const tableContainerRef = useRef<HTMLDivElement>(null);
|
||||
const { copyToClipboard } = useCopy();
|
||||
|
||||
const { dateRange, selectedTeamId, isAll, initialConfig, selectedRoutingFormId, selectedMemberUserId } =
|
||||
filter;
|
||||
const {
|
||||
dateRange,
|
||||
selectedTeamId,
|
||||
isAll,
|
||||
initialConfig,
|
||||
selectedRoutingFormId,
|
||||
selectedMemberUserId,
|
||||
selectedUserId,
|
||||
selectedBookingStatus,
|
||||
selectedRoutingFormFilter,
|
||||
} = filter;
|
||||
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);
|
||||
const [startDate, endDate] = dateRange;
|
||||
|
||||
@@ -276,6 +285,7 @@ export function RoutingFormResponsesTableContent({
|
||||
const { data: headers, isLoading: isHeadersLoading } =
|
||||
trpc.viewer.insights.routingFormResponsesHeaders.useQuery(
|
||||
{
|
||||
userId: selectedUserId ?? undefined,
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: isAll ?? false,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
@@ -291,7 +301,8 @@ export function RoutingFormResponsesTableContent({
|
||||
teamId: selectedTeamId,
|
||||
startDate: startDate.toISOString(),
|
||||
endDate: endDate.toISOString(),
|
||||
userId: selectedMemberUserId ?? undefined,
|
||||
userId: selectedUserId ?? undefined,
|
||||
memberUserId: selectedMemberUserId ?? undefined,
|
||||
isAll: isAll ?? false,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
columnFilters,
|
||||
|
||||
@@ -36,7 +36,8 @@ export const RoutingKPICards = () => {
|
||||
eventTypeId: selectedEventTypeId ?? undefined,
|
||||
isAll,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
userId: selectedMemberUserId ?? undefined,
|
||||
userId: selectedUserId ?? undefined,
|
||||
memberUserId: selectedMemberUserId ?? undefined,
|
||||
bookingStatus: selectedBookingStatus ?? undefined,
|
||||
fieldFilter: selectedRoutingFormFilter ?? undefined,
|
||||
},
|
||||
|
||||
@@ -96,6 +96,7 @@ export function FiltersProvider({ children }: { children: React.ReactNode }) {
|
||||
|
||||
// Use the custom hook
|
||||
const { mostPopularForm } = useDefaultRoutingForm({
|
||||
userId: userIdParsed,
|
||||
teamId: teamIdParsed,
|
||||
isAll: safe.success ? !!safe.data.teamId : false,
|
||||
routingFormId: routingFormIdParsed,
|
||||
|
||||
@@ -29,6 +29,7 @@ const RoutingDownload = () => {
|
||||
endDate: filter.dateRange[1].toISOString(),
|
||||
teamId: filter.selectedTeamId ?? undefined,
|
||||
userId: filter.selectedUserId ?? undefined,
|
||||
memberUserId: filter.selectedMemberUserId ?? undefined,
|
||||
routingFormId: filter.selectedRoutingFormId ?? undefined,
|
||||
bookingStatus: filter.selectedBookingStatus ?? undefined,
|
||||
fieldFilter: filter.selectedRoutingFormFilter ?? undefined,
|
||||
|
||||
@@ -34,6 +34,7 @@ export const FilterType = ({ showRoutingFilters = false }: { showRoutingFilters?
|
||||
// Query routing form field options when showRoutingFilters is true
|
||||
const { data: routingFormFieldOptions } = trpc.viewer.insights.getRoutingFormFieldOptions.useQuery(
|
||||
{
|
||||
userId: selectedUserId ?? -1,
|
||||
teamId: selectedTeamId ?? -1,
|
||||
isAll: !!isAll,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
|
||||
@@ -9,10 +9,11 @@ import { useFilterContext } from "../context/provider";
|
||||
export const RoutingFormFieldFilter = ({ fieldId }: { fieldId: string }) => {
|
||||
const { t } = useLocale();
|
||||
const { filter, setConfigFilters } = useFilterContext();
|
||||
const { selectedTeamId, isAll, selectedRoutingFormId, selectedRoutingFormFilter } = filter;
|
||||
const { selectedTeamId, selectedUserId, isAll, selectedRoutingFormId, selectedRoutingFormFilter } = filter;
|
||||
|
||||
const { data: fieldOptions } = trpc.viewer.insights.getRoutingFormFieldOptions.useQuery(
|
||||
{
|
||||
userId: selectedUserId ?? undefined,
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: !!isAll,
|
||||
routingFormId: selectedRoutingFormId ?? undefined,
|
||||
|
||||
@@ -20,11 +20,12 @@ export const RoutingFormFilterList = memo(
|
||||
({ showOnlyWhenSelectedInContext = true }: { showOnlyWhenSelectedInContext?: boolean }) => {
|
||||
const { t } = useLocale();
|
||||
const { filter, setConfigFilters } = useFilterContext();
|
||||
const { selectedTeamId, selectedRoutingFormId, isAll } = filter;
|
||||
const { selectedTeamId, selectedUserId, selectedRoutingFormId, isAll } = filter;
|
||||
const { selectedFilter } = filter;
|
||||
|
||||
const { data: allForms } = trpc.viewer.insights.getRoutingFormsForFilters.useQuery(
|
||||
{
|
||||
userId: selectedUserId ?? undefined,
|
||||
teamId: selectedTeamId ?? undefined,
|
||||
isAll: isAll ?? false,
|
||||
},
|
||||
|
||||
@@ -100,6 +100,7 @@ export const TeamAndSelfList = ({
|
||||
selectedTeamId: data[0].id,
|
||||
selectedUserId: null,
|
||||
selectedTeamName: null,
|
||||
selectedRoutingFormId: null,
|
||||
isAll: true,
|
||||
});
|
||||
}}
|
||||
@@ -127,12 +128,14 @@ export const TeamAndSelfList = ({
|
||||
selectedEventTypeId: null,
|
||||
selectedMemberUserId: null,
|
||||
selectedFilter: null,
|
||||
selectedRoutingFormId: null,
|
||||
});
|
||||
} else if (!e.target.checked) {
|
||||
setConfigFilters({
|
||||
selectedTeamId: isOrgDataAvailable ? data[0].id : null,
|
||||
selectedTeamName: null,
|
||||
isAll: true,
|
||||
selectedRoutingFormId: null,
|
||||
isAll: isOrgDataAvailable,
|
||||
});
|
||||
}
|
||||
}}
|
||||
@@ -155,7 +158,9 @@ export const TeamAndSelfList = ({
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setConfigFilters({
|
||||
selectedRoutingFormId: null,
|
||||
selectedUserId: session.data?.user.id,
|
||||
selectedMemberUserId: null,
|
||||
selectedTeamId: null,
|
||||
isAll: false,
|
||||
});
|
||||
@@ -164,6 +169,7 @@ export const TeamAndSelfList = ({
|
||||
selectedTeamId: isOrgDataAvailable ? data[0].id : null,
|
||||
selectedUserId: null,
|
||||
selectedTeamName: null,
|
||||
selectedRoutingFormId: null,
|
||||
isAll: isOrgDataAvailable,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
|
||||
export function useDefaultRoutingForm({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
onRoutingFormChange,
|
||||
}: {
|
||||
userId: number | null | undefined;
|
||||
teamId: number | null | undefined;
|
||||
isAll: boolean;
|
||||
routingFormId: string | null | undefined;
|
||||
@@ -24,6 +26,7 @@ export function useDefaultRoutingForm({
|
||||
// Query to get routing forms list
|
||||
const { data: routingForms } = trpc.viewer.insights.getRoutingFormsForFilters.useQuery(
|
||||
{
|
||||
userId: userId ?? undefined,
|
||||
teamId: teamId ?? undefined,
|
||||
isAll,
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import { readonlyPrisma as prisma } from "@calcom/prisma";
|
||||
import type { BookingStatus } from "@calcom/prisma/enums";
|
||||
|
||||
type RoutingFormInsightsTeamFilter = {
|
||||
userId?: number | null;
|
||||
teamId?: number | null;
|
||||
isAll: boolean;
|
||||
organizationId?: number | null;
|
||||
@@ -20,7 +21,7 @@ type RoutingFormInsightsTeamFilter = {
|
||||
type RoutingFormInsightsFilter = RoutingFormInsightsTeamFilter & {
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
userId?: number | null;
|
||||
memberUserId?: number | null;
|
||||
searchQuery?: string | null;
|
||||
bookingStatus?: BookingStatus | "NO_BOOKING" | null;
|
||||
fieldFilter?: {
|
||||
@@ -32,6 +33,7 @@ type RoutingFormInsightsFilter = RoutingFormInsightsTeamFilter & {
|
||||
|
||||
class RoutingEventsInsights {
|
||||
private static async getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -55,23 +57,21 @@ class RoutingEventsInsights {
|
||||
|
||||
// Base where condition for forms
|
||||
const formsWhereCondition: Prisma.App_RoutingForms_FormWhereInput = {
|
||||
...(teamIds.length > 0 && {
|
||||
teamId: {
|
||||
in: teamIds,
|
||||
},
|
||||
}),
|
||||
...(teamIds.length > 0
|
||||
? {
|
||||
teamId: {
|
||||
in: teamIds,
|
||||
},
|
||||
}
|
||||
: {
|
||||
userId: userId ?? -1,
|
||||
teamId: null,
|
||||
}),
|
||||
...(routingFormId && {
|
||||
id: routingFormId,
|
||||
}),
|
||||
};
|
||||
|
||||
if (teamIds.length === 0 && !routingFormId) {
|
||||
if (!organizationId) {
|
||||
throw new Error("Organization ID is required");
|
||||
}
|
||||
formsWhereCondition.teamId = organizationId;
|
||||
}
|
||||
|
||||
return formsWhereCondition;
|
||||
}
|
||||
|
||||
@@ -83,12 +83,14 @@ class RoutingEventsInsights {
|
||||
organizationId,
|
||||
routingFormId,
|
||||
userId,
|
||||
memberUserId,
|
||||
searchQuery,
|
||||
bookingStatus,
|
||||
fieldFilter,
|
||||
}: Omit<RoutingFormInsightsFilter, "columnFilters">) {
|
||||
// Get team IDs based on organization if applicable
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -104,13 +106,13 @@ class RoutingEventsInsights {
|
||||
lte: dayjs(endDate).endOf("day").toDate(),
|
||||
},
|
||||
}),
|
||||
...(userId || bookingStatus || searchQuery
|
||||
...(memberUserId || bookingStatus || searchQuery
|
||||
? {
|
||||
...(bookingStatus === "NO_BOOKING"
|
||||
? { routedToBooking: null }
|
||||
: {
|
||||
routedToBooking: {
|
||||
...(userId && { userId }),
|
||||
...(memberUserId && { userId: memberUserId }),
|
||||
...(searchQuery && {
|
||||
user: {
|
||||
OR: [
|
||||
@@ -166,16 +168,23 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async getRoutingFormsForFilters({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
}: {
|
||||
userId?: number;
|
||||
teamId?: number;
|
||||
isAll: boolean;
|
||||
organizationId?: number | undefined;
|
||||
routingFormId?: string | undefined;
|
||||
}) {
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({ teamId, isAll, organizationId });
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
});
|
||||
return await prisma.app_RoutingForms_Form.findMany({
|
||||
where: formsWhereCondition,
|
||||
select: {
|
||||
@@ -200,9 +209,11 @@ class RoutingEventsInsights {
|
||||
cursor,
|
||||
limit,
|
||||
userId,
|
||||
memberUserId,
|
||||
columnFilters,
|
||||
}: Omit<RoutingFormInsightsFilter, "fieldFilter" | "bookingStatus"> & { cursor?: number; limit?: number }) {
|
||||
const formsTeamWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -218,8 +229,8 @@ class RoutingEventsInsights {
|
||||
);
|
||||
|
||||
let bookingWhereInput: Prisma.BookingWhereInput = {};
|
||||
if (userId) {
|
||||
bookingWhereInput.userId = userId;
|
||||
if (memberUserId) {
|
||||
bookingWhereInput.userId = memberUserId;
|
||||
}
|
||||
if (bookingStatusFilter) {
|
||||
bookingWhereInput = {
|
||||
@@ -329,12 +340,14 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async getRoutingFormFieldOptions({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
organizationId,
|
||||
}: RoutingFormInsightsTeamFilter) {
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
@@ -355,12 +368,14 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async getFailedBookingsByRoutingFormGroup({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
organizationId,
|
||||
}: RoutingFormInsightsTeamFilter) {
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -374,6 +389,10 @@ class RoutingEventsInsights {
|
||||
// @ts-expect-error it doest exist but TS isnt smart enough when its unmber or int filter
|
||||
teamConditions.push(`f."teamId" IN (${formsWhereCondition.teamId.in.join(",")})`);
|
||||
}
|
||||
// @ts-expect-error it doest exist but TS isnt smart enough when its unmber or int filter
|
||||
if (!formsWhereCondition.teamId?.in && userId) {
|
||||
teamConditions.push(`f.userId = '${userId}'`);
|
||||
}
|
||||
if (routingFormId) {
|
||||
teamConditions.push(`f.id = '${routingFormId}'`);
|
||||
}
|
||||
@@ -486,12 +505,14 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async getRoutingFormHeaders({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
routingFormId,
|
||||
}: RoutingFormInsightsTeamFilter) {
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -528,12 +549,14 @@ class RoutingEventsInsights {
|
||||
organizationId,
|
||||
routingFormId,
|
||||
userId,
|
||||
memberUserId,
|
||||
bookingStatus,
|
||||
fieldFilter,
|
||||
take,
|
||||
skip,
|
||||
}: Omit<RoutingFormInsightsFilter, "columnFilters"> & { take?: number; skip?: number }) {
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -587,13 +610,13 @@ class RoutingEventsInsights {
|
||||
lte: dayjs(endDate).endOf("day").toDate(),
|
||||
},
|
||||
}),
|
||||
...(userId || bookingStatus
|
||||
...(memberUserId || bookingStatus
|
||||
? {
|
||||
...(bookingStatus === "NO_BOOKING"
|
||||
? { routedToBooking: null }
|
||||
: {
|
||||
routedToBooking: {
|
||||
...(userId && { userId }),
|
||||
...(memberUserId && { userId: memberUserId }),
|
||||
...(bookingStatus && { status: bookingStatus }),
|
||||
},
|
||||
}),
|
||||
@@ -698,6 +721,7 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async routedToPerPeriod({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -730,6 +754,7 @@ class RoutingEventsInsights {
|
||||
|
||||
// Build the team conditions for the WHERE clause
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -743,6 +768,10 @@ class RoutingEventsInsights {
|
||||
// @ts-expect-error same as above
|
||||
teamConditions.push(`f."teamId" IN (${formsWhereCondition.teamId.in.join(",")})`);
|
||||
}
|
||||
// @ts-expect-error it does exist but TS isn't smart enough when it's number or int filter
|
||||
if (!formsWhereCondition.teamId?.in && userId) {
|
||||
teamConditions.push(`f.userId = '${userId}'`);
|
||||
}
|
||||
if (routingFormId) {
|
||||
teamConditions.push(`f.id = '${routingFormId}'`);
|
||||
}
|
||||
@@ -953,6 +982,7 @@ class RoutingEventsInsights {
|
||||
}
|
||||
|
||||
static async routedToPerPeriodCsv({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -979,6 +1009,7 @@ class RoutingEventsInsights {
|
||||
|
||||
// Build the team conditions for the WHERE clause
|
||||
const formsWhereCondition = await this.getWhereForTeamOrAllTeams({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId,
|
||||
@@ -992,6 +1023,10 @@ class RoutingEventsInsights {
|
||||
// @ts-expect-error same as above
|
||||
teamConditions.push(`f."teamId" IN (${formsWhereCondition.teamId.in.join(",")})`);
|
||||
}
|
||||
// @ts-expect-error it does exist but TS isn't smart enough when it's number or int filter
|
||||
if (!formsWhereCondition.teamId?.in && userId) {
|
||||
teamConditions.push(`f.userId = '${userId}'`);
|
||||
}
|
||||
if (routingFormId) {
|
||||
teamConditions.push(`f.id = '${routingFormId}'`);
|
||||
}
|
||||
|
||||
@@ -1552,10 +1552,11 @@ export const insightsRouter = router({
|
||||
}),
|
||||
|
||||
getRoutingFormsForFilters: userBelongsToTeamProcedure
|
||||
.input(z.object({ teamId: z.number().optional(), isAll: z.boolean() }))
|
||||
.input(z.object({ userId: z.number().optional(), teamId: z.number().optional(), isAll: z.boolean() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { teamId, isAll } = input;
|
||||
const { userId, teamId, isAll } = input;
|
||||
return await RoutingEventsInsights.getRoutingFormsForFilters({
|
||||
userId,
|
||||
teamId,
|
||||
isAll,
|
||||
organizationId: ctx.user.organizationId ?? undefined,
|
||||
@@ -1585,6 +1586,7 @@ export const insightsRouter = router({
|
||||
organizationId: ctx.user.organizationId ?? null,
|
||||
routingFormId: input.routingFormId ?? null,
|
||||
userId: input.userId ?? null,
|
||||
memberUserId: input.memberUserId ?? null,
|
||||
bookingStatus: input.bookingStatus ?? null,
|
||||
fieldFilter: input.fieldFilter ?? null,
|
||||
});
|
||||
@@ -1611,13 +1613,19 @@ export const insightsRouter = router({
|
||||
routingFormId: input.routingFormId ?? null,
|
||||
cursor: input.cursor,
|
||||
userId: input.userId ?? null,
|
||||
memberUserId: input.memberUserId ?? null,
|
||||
limit: input.limit,
|
||||
columnFilters: input.columnFilters,
|
||||
});
|
||||
}),
|
||||
getRoutingFormFieldOptions: userBelongsToTeamProcedure
|
||||
.input(
|
||||
z.object({ teamId: z.number().optional(), isAll: z.boolean(), routingFormId: z.string().optional() })
|
||||
z.object({
|
||||
userId: z.number().optional(),
|
||||
teamId: z.number().optional(),
|
||||
isAll: z.boolean(),
|
||||
routingFormId: z.string().optional(),
|
||||
})
|
||||
)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const options = await RoutingEventsInsights.getRoutingFormFieldOptions({
|
||||
@@ -1628,7 +1636,12 @@ export const insightsRouter = router({
|
||||
}),
|
||||
failedBookingsByField: userBelongsToTeamProcedure
|
||||
.input(
|
||||
z.object({ teamId: z.number().optional(), isAll: z.boolean(), routingFormId: z.string().optional() })
|
||||
z.object({
|
||||
userId: z.number().optional(),
|
||||
teamId: z.number().optional(),
|
||||
isAll: z.boolean(),
|
||||
routingFormId: z.string().optional(),
|
||||
})
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
return await RoutingEventsInsights.getFailedBookingsByRoutingFormGroup({
|
||||
@@ -1639,6 +1652,7 @@ export const insightsRouter = router({
|
||||
routingFormResponsesHeaders: userBelongsToTeamProcedure
|
||||
.input(
|
||||
z.object({
|
||||
userId: z.number().optional(),
|
||||
teamId: z.number().optional(),
|
||||
isAll: z.boolean(),
|
||||
routingFormId: z.string().optional(),
|
||||
@@ -1646,6 +1660,7 @@ export const insightsRouter = router({
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const headers = await RoutingEventsInsights.getRoutingFormHeaders({
|
||||
userId: input.userId ?? null,
|
||||
teamId: input.teamId ?? null,
|
||||
isAll: input.isAll,
|
||||
organizationId: ctx.user.organizationId ?? null,
|
||||
@@ -1669,8 +1684,18 @@ export const insightsRouter = router({
|
||||
})
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { teamId, startDate, endDate, userId, isAll, routingFormId, bookingStatus, fieldFilter, cursor } =
|
||||
input;
|
||||
const {
|
||||
teamId,
|
||||
startDate,
|
||||
endDate,
|
||||
userId,
|
||||
memberUserId,
|
||||
isAll,
|
||||
routingFormId,
|
||||
bookingStatus,
|
||||
fieldFilter,
|
||||
cursor,
|
||||
} = input;
|
||||
|
||||
if (!teamId && !userId) {
|
||||
return { data: [], hasMore: false, nextCursor: null };
|
||||
@@ -1682,6 +1707,7 @@ export const insightsRouter = router({
|
||||
startDate,
|
||||
endDate,
|
||||
userId,
|
||||
memberUserId,
|
||||
isAll: isAll ?? false,
|
||||
organizationId: ctx.user.organizationId,
|
||||
routingFormId,
|
||||
@@ -1719,9 +1745,11 @@ export const insightsRouter = router({
|
||||
})
|
||||
)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { teamId, startDate, endDate, period, cursor, limit, isAll, routingFormId, searchQuery } = input;
|
||||
const { teamId, userId, startDate, endDate, period, cursor, limit, isAll, routingFormId, searchQuery } =
|
||||
input;
|
||||
|
||||
return await RoutingEventsInsights.routedToPerPeriod({
|
||||
userId: userId ?? null,
|
||||
teamId: teamId ?? null,
|
||||
startDate,
|
||||
endDate,
|
||||
@@ -1747,6 +1775,7 @@ export const insightsRouter = router({
|
||||
const { startDate, endDate } = input;
|
||||
try {
|
||||
const csvData = await RoutingEventsInsights.routedToPerPeriodCsv({
|
||||
userId: input.userId ?? null,
|
||||
teamId: input.teamId ?? null,
|
||||
startDate,
|
||||
endDate,
|
||||
|
||||
Reference in New Issue
Block a user