Files
calendar/packages/features/insights/server/virtual-queues.ts
T
6de715b884 feat: Round Robin timestamp basis (#21337)
* add rrTimeStampBasis to prisma schema

* add rr time stamp basis setting

* update migration

* add getLuckyUser logic

* add rrTimestampBasis to tests

* add load balancing warning message

* disable load balancing logic

* disable load balancing in event type settings

* add missing translations

* fix UI

* disable load balancing on all team event types

* don't show routing forms in router position

* use correct interval times

* fix variable naming

* fix event type update handler

* add test to booking.test.ts

* add test for getting interval times

* remove not needed prop

* fix label

* improve warning message

* fix removing maxLeadTreshold

* fix typo

* fix disabling maxLeadThreshold

* add back missing translation

* improve rr reset interval label

* fix rr_load_balancing_disabled text

* improve test

* fix description

* only use rrTimestampBasis in weights round robin

* fix dropdown width

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2025-06-12 11:37:38 +01:00

92 lines
2.9 KiB
TypeScript

import { readonlyPrisma as prisma } from "@calcom/prisma";
import { getSerializableForm } from "@calcom/routing-forms/lib/getSerializableForm";
class VirtualQueuesInsights {
static async getUserRelevantTeamRoutingForms({ userId }: { userId: number }) {
type JsonField = { [key: string]: any };
type RoutingFormType = {
id: string;
description: string | null;
position: number;
routes: JsonField | null;
createdAt: Date;
updatedAt: Date;
name: string;
fields: JsonField | null;
userId: number;
teamId: number | null;
disabled: boolean;
settings: JsonField | null;
updatedById: number | null;
};
const formsRedirectingToWeightedRR: RoutingFormType[] = await prisma.$queryRaw<RoutingFormType[]>`
WITH RECURSIVE json_array_elements_recursive AS (
SELECT f.id, f."teamId",
jsonb_array_elements(f.routes::jsonb) as route
FROM "App_RoutingForms_Form" f
WHERE f."teamId" IN (
SELECT "teamId"
FROM "Membership"
WHERE "userId" = ${userId}
)
)
SELECT DISTINCT f.*,
jsonb_build_object(
'parentId', t."parentId",
'parent', CASE WHEN p.id IS NOT NULL THEN jsonb_build_object('slug', p.slug) ELSE NULL END,
'metadata', t.metadata
) as team,
jsonb_build_object(
'id', u.id,
'username', u.username,
'movedToProfileId', u."movedToProfileId"
) as "user"
FROM "App_RoutingForms_Form" f
INNER JOIN json_array_elements_recursive r ON f.id = r.id
INNER JOIN "EventType" e ON (r.route->>'action')::jsonb->>'eventTypeId' = e.id::text
INNER JOIN "Team" t ON f."teamId" = t.id
LEFT JOIN "Team" p ON t."parentId" = p.id
INNER JOIN "users" u ON f."userId" = u.id
WHERE e."schedulingType" = 'roundRobin'
AND e."isRRWeightsEnabled" = true
AND (
EXISTS (
SELECT 1
FROM "Host" h
WHERE h."eventTypeId" = e.id
AND h."userId" = ${userId}
)
OR EXISTS (
SELECT 1
FROM "Membership" m
WHERE m."teamId" = f."teamId"
AND m."userId" = ${userId}
AND m.role = 'ADMIN'
)
OR EXISTS (
SELECT 1
FROM "Membership" m
WHERE m."teamId" = t."parentId"
AND m."userId" = ${userId}
AND m.role = 'ADMIN'
)
)
AND (t."rrTimestampBasis" IS NULL OR t."rrTimestampBasis" = 'CREATED_AT')
`;
// Convert the raw forms to serializable format
const serializableForms = await Promise.all(
formsRedirectingToWeightedRR.map(async (form) => {
const serializedForm = await getSerializableForm({ form });
return serializedForm;
})
);
return serializableForms;
}
}
export { VirtualQueuesInsights };