122 lines
3.8 KiB
TypeScript
122 lines
3.8 KiB
TypeScript
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<typeof loadTimelineHolidayOverlays>[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,
|
|
};
|
|
}
|