diff --git a/packages/api/src/__tests__/timeline-allocation-mutation-support.test.ts b/packages/api/src/__tests__/timeline-allocation-mutation-support.test.ts index 097b215..dd2b30e 100644 --- a/packages/api/src/__tests__/timeline-allocation-mutation-support.test.ts +++ b/packages/api/src/__tests__/timeline-allocation-mutation-support.test.ts @@ -5,9 +5,6 @@ import { buildTimelineAllocationEntryUpdate, buildTimelineAllocationMetadata, buildTimelineBatchShiftAuditChanges, - buildTimelineQuickAssignAssignmentInput, - buildTimelineQuickAssignMetadata, - calculateTimelineAllocationPercentage, shiftTimelineAllocationWindow, validateTimelineAllocationDateRanges, } from "../router/timeline-allocation-mutation-support.js"; @@ -39,43 +36,6 @@ describe("timeline allocation mutation support", () => { )).toThrowError(TRPCError); }); - it("rounds allocation percentages and clamps them to 100", () => { - expect(calculateTimelineAllocationPercentage(3.9)).toBe(49); - expect(calculateTimelineAllocationPercentage(9)).toBe(100); - }); - - it("builds source metadata for quick assign operations", () => { - expect(buildTimelineQuickAssignMetadata("quickAssign")).toEqual({ source: "quickAssign" }); - expect(buildTimelineQuickAssignMetadata("batchQuickAssign")).toEqual({ source: "batchQuickAssign" }); - }); - - it("builds assignment create payloads for quick assign flows", () => { - expect( - buildTimelineQuickAssignAssignmentInput({ - resourceId: "resource_1", - projectId: "project_1", - startDate: new Date("2026-04-01T00:00:00.000Z"), - endDate: new Date("2026-04-05T00:00:00.000Z"), - hoursPerDay: 6, - role: "Engineer", - roleId: "role_1", - status: "PROPOSED", - source: "quickAssign", - }), - ).toEqual({ - resourceId: "resource_1", - projectId: "project_1", - startDate: new Date("2026-04-01T00:00:00.000Z"), - endDate: new Date("2026-04-05T00:00:00.000Z"), - hoursPerDay: 6, - percentage: 75, - role: "Engineer", - roleId: "role_1", - status: "PROPOSED", - metadata: { source: "quickAssign" }, - }); - }); - it("shifts and clamps allocation windows for each batch-shift mode", () => { expect( shiftTimelineAllocationWindow({ diff --git a/packages/api/src/__tests__/timeline-allocation-quick-assign-support.test.ts b/packages/api/src/__tests__/timeline-allocation-quick-assign-support.test.ts new file mode 100644 index 0000000..65ecd18 --- /dev/null +++ b/packages/api/src/__tests__/timeline-allocation-quick-assign-support.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from "vitest"; +import { + buildTimelineQuickAssignAssignmentInput, + buildTimelineQuickAssignMetadata, + calculateTimelineAllocationPercentage, +} from "../router/timeline-allocation-quick-assign-support.js"; + +describe("timeline allocation quick assign support", () => { + it("rounds allocation percentages and clamps them to 100", () => { + expect(calculateTimelineAllocationPercentage(3.9)).toBe(49); + expect(calculateTimelineAllocationPercentage(9)).toBe(100); + }); + + it("builds source metadata for quick assign operations", () => { + expect(buildTimelineQuickAssignMetadata("quickAssign")).toEqual({ source: "quickAssign" }); + expect(buildTimelineQuickAssignMetadata("batchQuickAssign")).toEqual({ source: "batchQuickAssign" }); + }); + + it("builds assignment create payloads for quick assign flows", () => { + expect( + buildTimelineQuickAssignAssignmentInput({ + resourceId: "resource_1", + projectId: "project_1", + startDate: new Date("2026-04-01T00:00:00.000Z"), + endDate: new Date("2026-04-05T00:00:00.000Z"), + hoursPerDay: 6, + role: "Engineer", + roleId: "role_1", + status: "PROPOSED", + source: "quickAssign", + }), + ).toEqual({ + resourceId: "resource_1", + projectId: "project_1", + startDate: new Date("2026-04-01T00:00:00.000Z"), + endDate: new Date("2026-04-05T00:00:00.000Z"), + hoursPerDay: 6, + percentage: 75, + role: "Engineer", + roleId: "role_1", + status: "PROPOSED", + metadata: { source: "quickAssign" }, + }); + }); +}); diff --git a/packages/api/src/router/timeline-allocation-mutation-support.ts b/packages/api/src/router/timeline-allocation-mutation-support.ts index 81713e1..4f09ec8 100644 --- a/packages/api/src/router/timeline-allocation-mutation-support.ts +++ b/packages/api/src/router/timeline-allocation-mutation-support.ts @@ -1,5 +1,4 @@ import { Prisma } from "@capakraken/db"; -import { AllocationStatus } from "@capakraken/shared"; import { TRPCError } from "@trpc/server"; export type TimelineBatchShiftMode = "move" | "resize-start" | "resize-end"; @@ -32,39 +31,6 @@ export function buildTimelineAllocationMetadata(input: { return { metadata, includeSaturday }; } -export function calculateTimelineAllocationPercentage(hoursPerDay: number): number { - return Math.min(100, Math.round((hoursPerDay / 8) * 100)); -} - -export function buildTimelineQuickAssignMetadata(source: "quickAssign" | "batchQuickAssign") { - return { source } satisfies Record; -} - -export function buildTimelineQuickAssignAssignmentInput(input: { - resourceId: string; - projectId: string; - startDate: Date; - endDate: Date; - hoursPerDay: number; - role: string; - roleId?: string | undefined; - status: AllocationStatus; - source: "quickAssign" | "batchQuickAssign"; -}) { - return { - resourceId: input.resourceId, - projectId: input.projectId, - startDate: input.startDate, - endDate: input.endDate, - hoursPerDay: input.hoursPerDay, - percentage: calculateTimelineAllocationPercentage(input.hoursPerDay), - role: input.role, - ...(input.roleId !== undefined ? { roleId: input.roleId } : {}), - status: input.status, - metadata: buildTimelineQuickAssignMetadata(input.source), - }; -} - export function validateTimelineAllocationDateRanges( ranges: Array<{ startDate: Date; endDate: Date }>, ): void { diff --git a/packages/api/src/router/timeline-allocation-procedure-support.ts b/packages/api/src/router/timeline-allocation-procedure-support.ts index 79a2ba4..c0aa181 100644 --- a/packages/api/src/router/timeline-allocation-procedure-support.ts +++ b/packages/api/src/router/timeline-allocation-procedure-support.ts @@ -9,9 +9,9 @@ import { } from "../sse/event-bus.js"; import { assertTimelineDateRangeValid, - buildTimelineQuickAssignAssignmentInput, validateTimelineAllocationDateRanges, } from "./timeline-allocation-mutation-support.js"; +import { buildTimelineQuickAssignAssignmentInput } from "./timeline-allocation-quick-assign-support.js"; import { applyTimelineBatchAllocationShift } from "./timeline-allocation-shift-support.js"; export async function createTimelineQuickAssignment( diff --git a/packages/api/src/router/timeline-allocation-quick-assign-support.ts b/packages/api/src/router/timeline-allocation-quick-assign-support.ts new file mode 100644 index 0000000..471fae1 --- /dev/null +++ b/packages/api/src/router/timeline-allocation-quick-assign-support.ts @@ -0,0 +1,34 @@ +import { AllocationStatus } from "@capakraken/shared"; + +export function calculateTimelineAllocationPercentage(hoursPerDay: number): number { + return Math.min(100, Math.round((hoursPerDay / 8) * 100)); +} + +export function buildTimelineQuickAssignMetadata(source: "quickAssign" | "batchQuickAssign") { + return { source } satisfies Record; +} + +export function buildTimelineQuickAssignAssignmentInput(input: { + resourceId: string; + projectId: string; + startDate: Date; + endDate: Date; + hoursPerDay: number; + role: string; + roleId?: string | undefined; + status: AllocationStatus; + source: "quickAssign" | "batchQuickAssign"; +}) { + return { + resourceId: input.resourceId, + projectId: input.projectId, + startDate: input.startDate, + endDate: input.endDate, + hoursPerDay: input.hoursPerDay, + percentage: calculateTimelineAllocationPercentage(input.hoursPerDay), + role: input.role, + ...(input.roleId !== undefined ? { roleId: input.roleId } : {}), + status: input.status, + metadata: buildTimelineQuickAssignMetadata(input.source), + }; +}