diff --git a/apps/web/modules/api/v2/management/lib/tests/utils.test.ts b/apps/web/modules/api/v2/management/lib/tests/utils.test.ts index 1d8eaf81f9..44c49d929c 100644 --- a/apps/web/modules/api/v2/management/lib/tests/utils.test.ts +++ b/apps/web/modules/api/v2/management/lib/tests/utils.test.ts @@ -12,6 +12,7 @@ describe("pickCommonFilter", () => { order: "asc", startDate: new Date("2023-01-01"), endDate: new Date("2023-12-31"), + filterDateField: "createdAt", } as TGetFilter; const result = pickCommonFilter(params); expect(result).toEqual(params); @@ -27,6 +28,7 @@ describe("pickCommonFilter", () => { order: undefined, startDate: undefined, endDate: undefined, + filterDateField: undefined, }); }); @@ -70,5 +72,32 @@ describe("pickCommonFilter", () => { const result = buildCommonFilterQuery(query, params); expect(result).toEqual({}); }); + + test("applies filterDateField with updatedAt when provided", () => { + const query: Prisma.WebhookFindManyArgs = { where: {} }; + const params = { + startDate: new Date("2023-01-01"), + endDate: new Date("2023-12-31"), + filterDateField: "updatedAt", + } as TGetFilter; + const result = buildCommonFilterQuery(query, params); + const updatedAt = result.where?.updatedAt as Prisma.DateTimeFilter | undefined; + expect(updatedAt?.gte).toEqual(params.startDate); + expect(updatedAt?.lte).toEqual(params.endDate); + expect(result.where?.createdAt).toBeUndefined(); + }); + + test("defaults to createdAt when filterDateField is not provided", () => { + const query: Prisma.WebhookFindManyArgs = { where: {} }; + const params = { + startDate: new Date("2023-01-01"), + endDate: new Date("2023-12-31"), + } as TGetFilter; + const result = buildCommonFilterQuery(query, params); + const createdAt = result.where?.createdAt as Prisma.DateTimeFilter | undefined; + expect(createdAt?.gte).toEqual(params.startDate); + expect(createdAt?.lte).toEqual(params.endDate); + expect(result.where?.updatedAt).toBeUndefined(); + }); }); }); diff --git a/apps/web/modules/api/v2/management/lib/utils.test.ts b/apps/web/modules/api/v2/management/lib/utils.test.ts new file mode 100644 index 0000000000..36f13e25f4 --- /dev/null +++ b/apps/web/modules/api/v2/management/lib/utils.test.ts @@ -0,0 +1,43 @@ +import { Prisma } from "@prisma/client"; +import { describe, expect, it } from "vitest"; +import { buildCommonFilterQuery } from "./utils"; + +describe("buildCommonFilterQuery", () => { + // Test for line 32: spread existing date filter when adding startDate + it("should preserve existing date filter when adding startDate", () => { + const query: Prisma.ResponseFindManyArgs = { + where: { + createdAt: { + lte: new Date("2024-12-31"), + }, + }, + }; + const startDate = new Date("2024-01-01"); + + const result = buildCommonFilterQuery(query, { startDate }); + + expect(result.where?.createdAt).toEqual({ + lte: new Date("2024-12-31"), + gte: startDate, + }); + }); + + // Test for line 45: spread existing date filter when adding endDate + it("should preserve existing date filter when adding endDate", () => { + const query: Prisma.ResponseFindManyArgs = { + where: { + createdAt: { + gte: new Date("2024-01-01"), + }, + }, + }; + const endDate = new Date("2024-12-31"); + + const result = buildCommonFilterQuery(query, { endDate }); + + expect(result.where?.createdAt).toEqual({ + gte: new Date("2024-01-01"), + lte: endDate, + }); + }); +}); diff --git a/apps/web/modules/api/v2/management/lib/utils.ts b/apps/web/modules/api/v2/management/lib/utils.ts index 63e0ec6e6d..1934cab327 100644 --- a/apps/web/modules/api/v2/management/lib/utils.ts +++ b/apps/web/modules/api/v2/management/lib/utils.ts @@ -2,8 +2,8 @@ import { Prisma } from "@prisma/client"; import { TGetFilter } from "@/modules/api/v2/types/api-filter"; export function pickCommonFilter(params: T) { - const { limit, skip, sortBy, order, startDate, endDate } = params; - return { limit, skip, sortBy, order, startDate, endDate }; + const { limit, skip, sortBy, order, startDate, endDate, filterDateField } = params; + return { limit, skip, sortBy, order, startDate, endDate, filterDateField }; } type HasFindMany = @@ -15,19 +15,21 @@ type HasFindMany = | Prisma.ContactAttributeKeyFindManyArgs; export function buildCommonFilterQuery(query: T, params: TGetFilter): T { - const { limit, skip, sortBy, order, startDate, endDate } = params || {}; + const { limit, skip, sortBy, order, startDate, endDate, filterDateField = "createdAt" } = params || {}; let filteredQuery = { ...query, }; + const dateField = filterDateField; + if (startDate) { filteredQuery = { ...filteredQuery, where: { ...filteredQuery.where, - createdAt: { - ...((filteredQuery.where?.createdAt as Prisma.DateTimeFilter) ?? {}), + [dateField]: { + ...(filteredQuery.where?.[dateField] as Prisma.DateTimeFilter), gte: startDate, }, }, @@ -39,8 +41,8 @@ export function buildCommonFilterQuery(query: T, params: ...filteredQuery, where: { ...filteredQuery.where, - createdAt: { - ...((filteredQuery.where?.createdAt as Prisma.DateTimeFilter) ?? {}), + [dateField]: { + ...(filteredQuery.where?.[dateField] as Prisma.DateTimeFilter), lte: endDate, }, }, diff --git a/apps/web/modules/api/v2/types/api-filter.ts b/apps/web/modules/api/v2/types/api-filter.ts index 07b4187128..66ceda186e 100644 --- a/apps/web/modules/api/v2/types/api-filter.ts +++ b/apps/web/modules/api/v2/types/api-filter.ts @@ -7,6 +7,7 @@ export const ZGetFilter = z.object({ order: z.enum(["asc", "desc"]).optional().default("desc").describe("Sort order"), startDate: z.coerce.date().optional().describe("Start date"), endDate: z.coerce.date().optional().describe("End date"), + filterDateField: z.enum(["createdAt", "updatedAt"]).optional().describe("Date field to filter by"), }); export type TGetFilter = z.infer; diff --git a/docs/api-v2-reference/openapi.yml b/docs/api-v2-reference/openapi.yml index 5ce5c44582..31b34646f8 100644 --- a/docs/api-v2-reference/openapi.yml +++ b/docs/api-v2-reference/openapi.yml @@ -611,6 +611,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by - in: query name: surveyId schema: @@ -1708,6 +1718,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by - in: query name: environmentId description: The environment ID to filter by @@ -2242,6 +2262,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by - in: query name: surveyIds schema: @@ -2699,6 +2729,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by responses: "200": description: Teams retrieved successfully. @@ -3003,6 +3043,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by - in: query name: teamId schema: @@ -3301,6 +3351,16 @@ paths: schema: type: string description: End date + - in: query + name: filterDateField + description: Date field to filter by + schema: + type: string + enum: + - createdAt + - updatedAt + default: createdAt + description: Date field to filter by - in: query name: id schema: