import { fmtDate, } from "./timeline-read-shared.js"; import { anonymizeResourceOnEntry, summarizeTimelineEntries, } from "./timeline-entry-response-support.js"; import { summarizeHolidayOverlays, } from "./timeline-holiday-read.js"; type TimelineAnonymizationDirectory = Parameters[1]; export function buildTimelineProjectContextSummary(input: { allocations: Array<{ projectId: string | null; resourceId: string | null }>; demands: Array<{ projectId: string | null }>; assignments: Array<{ projectId: string | null; resourceId: string | null }>; resourceIds: string[]; allResourceAllocations: unknown[]; assignmentConflicts: Array<{ crossProjectOverlapCount: number }>; holidayOverlays: Parameters[0]; }) { return { ...summarizeTimelineEntries({ allocations: input.allocations, demands: input.demands, assignments: input.assignments, }), resourceIds: input.resourceIds.length, allResourceAllocationCount: input.allResourceAllocations.length, conflictedAssignmentCount: input.assignmentConflicts.filter( (item) => item.crossProjectOverlapCount > 0, ).length, ...summarizeHolidayOverlays(input.holidayOverlays), }; } export function buildTimelineProjectContextResponse< TProject, TAllocation extends { resource?: { id: string } | null }, TDemand, TAssignment extends { resource?: { id: string } | null }, TBooking extends { resource?: { id: string } | null }, >(input: { project: TProject; allocations: TAllocation[]; demands: TDemand[]; assignments: TAssignment[]; allResourceAllocations: TBooking[]; resourceIds: string[]; directory: TimelineAnonymizationDirectory; }) { return { project: input.project, allocations: input.allocations.map((allocation) => anonymizeResourceOnEntry(allocation, input.directory), ), demands: input.demands, assignments: input.assignments.map((assignment) => anonymizeResourceOnEntry(assignment, input.directory), ), allResourceAllocations: input.allResourceAllocations.map((allocation) => anonymizeResourceOnEntry(allocation, input.directory), ), resourceIds: input.resourceIds, }; } export function buildTimelineProjectContextDetailResponse< TProject, TAllocation extends { projectId: string | null; resourceId: string | null; resource?: { id: string } | null; }, TDemand extends { projectId: string | null }, TAssignment extends { projectId: string | null; resourceId: string | null; resource?: { id: string } | null; }, TBooking extends { resource?: { id: string } | null }, TConflict extends { crossProjectOverlapCount: number }, >(input: { project: TProject; period: { startDate: Date; endDate: Date }; allocations: TAllocation[]; demands: TDemand[]; assignments: TAssignment[]; allResourceAllocations: TBooking[]; resourceIds: string[]; assignmentConflicts: TConflict[]; holidayOverlays: Parameters[0]; directory: TimelineAnonymizationDirectory; }) { const base = buildTimelineProjectContextResponse({ project: input.project, allocations: input.allocations, demands: input.demands, assignments: input.assignments, allResourceAllocations: input.allResourceAllocations, resourceIds: input.resourceIds, directory: input.directory, }); return { ...base, period: { startDate: fmtDate(input.period.startDate), endDate: fmtDate(input.period.endDate), }, summary: buildTimelineProjectContextSummary({ allocations: input.allocations, demands: input.demands, assignments: input.assignments, resourceIds: input.resourceIds, allResourceAllocations: input.allResourceAllocations, assignmentConflicts: input.assignmentConflicts, holidayOverlays: input.holidayOverlays, }), assignmentConflicts: input.assignmentConflicts, holidayOverlays: input.holidayOverlays, }; }