import { TRPCError } from "@trpc/server"; import { buildTimelineProjectAssignmentConflicts, } from "./timeline-project-conflict-support.js"; import { formatHolidayOverlays, loadTimelineHolidayOverlays, } from "./timeline-holiday-read.js"; import { createTimelineDateRange, fmtDate, toDate, } from "./timeline-read-shared.js"; export interface ResolveTimelineProjectContextPeriodInput { requestedStartDate?: string | undefined; requestedEndDate?: string | undefined; durationDays?: number | undefined; projectStartDate?: Date | null | undefined; projectEndDate?: Date | null | undefined; firstAssignmentStartDate?: Date | string | null | undefined; firstDemandStartDate?: Date | string | null | undefined; } export function resolveTimelineProjectContextPeriod( input: ResolveTimelineProjectContextPeriodInput, ) { const startDate = input.requestedStartDate ? createTimelineDateRange({ startDate: input.requestedStartDate, durationDays: 1, }).startDate : input.projectStartDate ?? (input.firstAssignmentStartDate ? toDate(input.firstAssignmentStartDate) : null) ?? (input.firstDemandStartDate ? toDate(input.firstDemandStartDate) : null) ?? createTimelineDateRange({ durationDays: 1 }).startDate; const endDate = input.requestedEndDate ? createTimelineDateRange({ startDate: fmtDate(startDate) ?? undefined, endDate: input.requestedEndDate, }).endDate : input.projectEndDate ?? createTimelineDateRange({ startDate: fmtDate(startDate) ?? undefined, durationDays: input.durationDays ?? 21, }).endDate; if (endDate < startDate) { throw new TRPCError({ code: "BAD_REQUEST", message: "endDate must be on or after startDate.", }); } return { startDate, endDate }; } export async function loadTimelineProjectContextDetailArtifacts( db: Parameters[0], input: { projectId: string; requestedStartDate?: string | undefined; requestedEndDate?: string | undefined; durationDays?: number | undefined; projectStartDate?: Date | null | undefined; projectEndDate?: Date | null | undefined; firstAssignmentStartDate?: Date | string | null | undefined; firstDemandStartDate?: Date | string | null | undefined; assignments: Array<{ id: string; resourceId: string | null; resource?: { displayName?: string | null } | null; startDate: Date | string; endDate: Date | string; hoursPerDay: number; }>; allResourceAllocations: Array<{ id: string; resourceId: string | null; projectId: string | null; project?: { name?: string | null; shortCode?: string | null } | null; startDate: Date | string; endDate: Date | string; hoursPerDay: number; status: string; }>; resourceIds: string[]; }, ) { const period = resolveTimelineProjectContextPeriod({ requestedStartDate: input.requestedStartDate, requestedEndDate: input.requestedEndDate, durationDays: input.durationDays, projectStartDate: input.projectStartDate, projectEndDate: input.projectEndDate, firstAssignmentStartDate: input.firstAssignmentStartDate, firstDemandStartDate: input.firstDemandStartDate, }); const holidayOverlays = input.resourceIds.length > 0 ? formatHolidayOverlays(await loadTimelineHolidayOverlays(db, { startDate: period.startDate, endDate: period.endDate, resourceIds: input.resourceIds, projectIds: [input.projectId], })) : []; const assignmentConflicts = buildTimelineProjectAssignmentConflicts({ projectId: input.projectId, assignments: input.assignments, allResourceAllocations: input.allResourceAllocations, }); return { period, holidayOverlays, assignmentConflicts, }; }