diff --git a/packages/api/src/__tests__/timeline-project-procedure-support.test.ts b/packages/api/src/__tests__/timeline-project-procedure-support.test.ts index 96f5ec1..91b795c 100644 --- a/packages/api/src/__tests__/timeline-project-procedure-support.test.ts +++ b/packages/api/src/__tests__/timeline-project-procedure-support.test.ts @@ -41,6 +41,7 @@ import { } from "../router/timeline-project-query-support.js"; import { readTimelineProjectBudgetStatusResponse, + readTimelineProjectShiftPreview, readTimelineProjectShiftPreviewDetail, } from "../router/timeline-project-procedure-support.js"; @@ -89,6 +90,24 @@ describe("timeline project procedure support", () => { }); }); + it("loads plain shift preview responses through procedure support", async () => { + previewTimelineProjectShiftMock.mockResolvedValueOnce({ valid: true } as never); + + await expect( + readTimelineProjectShiftPreview({} as never, { + projectId: "project_1", + newStartDate: new Date("2026-04-03T00:00:00.000Z"), + newEndDate: new Date("2026-04-12T00:00:00.000Z"), + }), + ).resolves.toEqual({ valid: true }); + + expect(previewTimelineProjectShiftMock).toHaveBeenCalledWith({}, { + projectId: "project_1", + newStartDate: new Date("2026-04-03T00:00:00.000Z"), + newEndDate: new Date("2026-04-12T00:00:00.000Z"), + }); + }); + it("builds budget status responses from project bookings", async () => { findTimelineProjectOrThrowMock.mockResolvedValueOnce({ id: "project_1", diff --git a/packages/api/src/__tests__/timeline-read-shared.test.ts b/packages/api/src/__tests__/timeline-read-shared.test.ts index 771b112..2346a81 100644 --- a/packages/api/src/__tests__/timeline-read-shared.test.ts +++ b/packages/api/src/__tests__/timeline-read-shared.test.ts @@ -3,6 +3,7 @@ import { buildTimelineEntriesDetailInput, TimelineDetailFiltersSchema, TimelineProjectContextDetailSchema, + TimelineProjectIdSchema, } from "../router/timeline-read-shared.js"; describe("timeline read shared", () => { @@ -68,5 +69,11 @@ describe("timeline read shared", () => { endDate: "2026-04-20", durationDays: undefined, }); + + expect(TimelineProjectIdSchema.parse({ + projectId: "project_1", + })).toEqual({ + projectId: "project_1", + }); }); }); diff --git a/packages/api/src/router/timeline-project-procedure-support.ts b/packages/api/src/router/timeline-project-procedure-support.ts index d036de1..8e22cc4 100644 --- a/packages/api/src/router/timeline-project-procedure-support.ts +++ b/packages/api/src/router/timeline-project-procedure-support.ts @@ -45,6 +45,17 @@ export async function readTimelineProjectShiftPreviewDetail( }); } +export async function readTimelineProjectShiftPreview( + db: TimelineProjectProcedureDb, + input: { + projectId: string; + newStartDate: Date; + newEndDate: Date; + }, +) { + return previewTimelineProjectShift(db, input); +} + export async function readTimelineProjectBudgetStatusResponse( db: TimelineProjectProcedureDb, projectId: string, diff --git a/packages/api/src/router/timeline-project-read.ts b/packages/api/src/router/timeline-project-read.ts index 21f62c0..a4fb489 100644 --- a/packages/api/src/router/timeline-project-read.ts +++ b/packages/api/src/router/timeline-project-read.ts @@ -1,9 +1,8 @@ import { ShiftProjectSchema } from "@capakraken/shared"; -import { z } from "zod"; import { controllerProcedure } from "../trpc.js"; -import { previewTimelineProjectShift } from "./timeline-project-load-support.js"; import { TimelineProjectContextDetailSchema, + TimelineProjectIdSchema, } from "./timeline-read-shared.js"; import { readTimelineProjectContextDetailResponse, @@ -11,12 +10,13 @@ import { } from "./timeline-project-context-procedure-support.js"; import { readTimelineProjectBudgetStatusResponse, + readTimelineProjectShiftPreview, readTimelineProjectShiftPreviewDetail, } from "./timeline-project-procedure-support.js"; export const timelineProjectReadProcedures = { getProjectContext: controllerProcedure - .input(z.object({ projectId: z.string() })) + .input(TimelineProjectIdSchema) .query(async ({ ctx, input }) => readTimelineProjectContextResponse(ctx.db, input.projectId)), getProjectContextDetail: controllerProcedure @@ -25,13 +25,13 @@ export const timelineProjectReadProcedures = { previewShift: controllerProcedure .input(ShiftProjectSchema) - .query(async ({ ctx, input }) => previewTimelineProjectShift(ctx.db, input)), + .query(async ({ ctx, input }) => readTimelineProjectShiftPreview(ctx.db, input)), getShiftPreviewDetail: controllerProcedure .input(ShiftProjectSchema) .query(async ({ ctx, input }) => readTimelineProjectShiftPreviewDetail(ctx.db, input)), getBudgetStatus: controllerProcedure - .input(z.object({ projectId: z.string() })) + .input(TimelineProjectIdSchema) .query(async ({ ctx, input }) => readTimelineProjectBudgetStatusResponse(ctx.db, input.projectId)), }; diff --git a/packages/api/src/router/timeline-read-shared.ts b/packages/api/src/router/timeline-read-shared.ts index 5c58b41..f8ad155 100644 --- a/packages/api/src/router/timeline-read-shared.ts +++ b/packages/api/src/router/timeline-read-shared.ts @@ -60,6 +60,10 @@ export const TimelineProjectContextDetailSchema = z.object({ durationDays: z.number().int().min(1).max(366).optional(), }); +export const TimelineProjectIdSchema = z.object({ + projectId: z.string(), +}); + type TimelineWindowFiltersInput = z.infer; export function getAssignmentResourceIds(