refactor(api): extract timeline project read builders
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { summarizeHolidayOverlays, type formatHolidayOverlays } from "./timeline-holiday-read.js";
|
||||
import {
|
||||
anonymizeResourceOnEntry,
|
||||
createTimelineDateRange,
|
||||
fmtDate,
|
||||
rangesOverlap,
|
||||
@@ -8,6 +9,8 @@ import {
|
||||
toDate,
|
||||
} from "./timeline-read-shared.js";
|
||||
|
||||
type TimelineAnonymizationDirectory = Parameters<typeof anonymizeResourceOnEntry>[1];
|
||||
|
||||
export interface ResolveTimelineProjectContextPeriodInput {
|
||||
requestedStartDate?: string | undefined;
|
||||
requestedEndDate?: string | undefined;
|
||||
@@ -158,3 +161,117 @@ export function buildTimelineProjectContextSummary(input: {
|
||||
...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: ReturnType<typeof formatHolidayOverlays>;
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildTimelineShiftPreviewDetailResponse<TPreview>(input: {
|
||||
project: {
|
||||
id: string;
|
||||
name: string;
|
||||
shortCode: string | null;
|
||||
status: string;
|
||||
responsiblePerson: string | null;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
};
|
||||
requestedShift: {
|
||||
newStartDate: Date;
|
||||
newEndDate: Date;
|
||||
};
|
||||
preview: TPreview;
|
||||
}) {
|
||||
return {
|
||||
project: {
|
||||
id: input.project.id,
|
||||
name: input.project.name,
|
||||
shortCode: input.project.shortCode,
|
||||
status: input.project.status,
|
||||
responsiblePerson: input.project.responsiblePerson,
|
||||
startDate: fmtDate(input.project.startDate),
|
||||
endDate: fmtDate(input.project.endDate),
|
||||
},
|
||||
requestedShift: {
|
||||
newStartDate: fmtDate(input.requestedShift.newStartDate),
|
||||
newEndDate: fmtDate(input.requestedShift.newEndDate),
|
||||
},
|
||||
preview: input.preview,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,8 +7,11 @@ import { getAnonymizationDirectory } from "../lib/anonymization.js";
|
||||
import { controllerProcedure } from "../trpc.js";
|
||||
import { loadProjectPlanningReadModel } from "./project-planning-read-model.js";
|
||||
import {
|
||||
buildTimelineProjectContextDetailResponse,
|
||||
buildTimelineProjectContextResponse,
|
||||
buildTimelineProjectAssignmentConflicts,
|
||||
buildTimelineProjectContextSummary,
|
||||
buildTimelineShiftPreviewDetailResponse,
|
||||
resolveTimelineProjectContextPeriod,
|
||||
} from "./timeline-project-context-support.js";
|
||||
import { buildTimelineShiftPlan } from "./timeline-shift-planning.js";
|
||||
@@ -148,20 +151,15 @@ export const timelineProjectReadProcedures = {
|
||||
} = await loadTimelineProjectContext(ctx.db, input.projectId);
|
||||
const directory = await getAnonymizationDirectory(ctx.db);
|
||||
|
||||
return {
|
||||
return buildTimelineProjectContextResponse({
|
||||
project,
|
||||
allocations: allocations.map((allocation) =>
|
||||
anonymizeResourceOnEntry(allocation, directory),
|
||||
),
|
||||
allocations,
|
||||
demands,
|
||||
assignments: assignments.map((assignment) =>
|
||||
anonymizeResourceOnEntry(assignment, directory),
|
||||
),
|
||||
allResourceAllocations: allResourceAllocations.map((allocation) =>
|
||||
anonymizeResourceOnEntry(allocation, directory),
|
||||
),
|
||||
assignments,
|
||||
allResourceAllocations,
|
||||
resourceIds,
|
||||
};
|
||||
directory,
|
||||
});
|
||||
}),
|
||||
|
||||
getProjectContextDetail: controllerProcedure
|
||||
@@ -201,35 +199,18 @@ export const timelineProjectReadProcedures = {
|
||||
allResourceAllocations: projectContext.allResourceAllocations,
|
||||
});
|
||||
|
||||
return {
|
||||
return buildTimelineProjectContextDetailResponse({
|
||||
project: projectContext.project,
|
||||
period: {
|
||||
startDate: fmtDate(period.startDate),
|
||||
endDate: fmtDate(period.endDate),
|
||||
},
|
||||
summary: buildTimelineProjectContextSummary({
|
||||
allocations: projectContext.allocations,
|
||||
demands: projectContext.demands,
|
||||
assignments: projectContext.assignments,
|
||||
resourceIds: projectContext.resourceIds,
|
||||
allResourceAllocations: projectContext.allResourceAllocations,
|
||||
assignmentConflicts,
|
||||
holidayOverlays: formattedHolidayOverlays,
|
||||
}),
|
||||
allocations: projectContext.allocations.map((allocation) =>
|
||||
anonymizeResourceOnEntry(allocation, directory),
|
||||
),
|
||||
period,
|
||||
allocations: projectContext.allocations,
|
||||
demands: projectContext.demands,
|
||||
assignments: projectContext.assignments.map((assignment) =>
|
||||
anonymizeResourceOnEntry(assignment, directory),
|
||||
),
|
||||
allResourceAllocations: projectContext.allResourceAllocations.map((allocation) =>
|
||||
anonymizeResourceOnEntry(allocation, directory),
|
||||
),
|
||||
assignments: projectContext.assignments,
|
||||
allResourceAllocations: projectContext.allResourceAllocations,
|
||||
resourceIds: projectContext.resourceIds,
|
||||
assignmentConflicts,
|
||||
holidayOverlays: formattedHolidayOverlays,
|
||||
resourceIds: projectContext.resourceIds,
|
||||
};
|
||||
directory,
|
||||
});
|
||||
}),
|
||||
|
||||
previewShift: controllerProcedure
|
||||
@@ -258,22 +239,14 @@ export const timelineProjectReadProcedures = {
|
||||
previewTimelineProjectShift(ctx.db, input),
|
||||
]);
|
||||
|
||||
return {
|
||||
project: {
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
shortCode: project.shortCode,
|
||||
status: project.status,
|
||||
responsiblePerson: project.responsiblePerson,
|
||||
startDate: fmtDate(project.startDate),
|
||||
endDate: fmtDate(project.endDate),
|
||||
},
|
||||
return buildTimelineShiftPreviewDetailResponse({
|
||||
project,
|
||||
requestedShift: {
|
||||
newStartDate: fmtDate(input.newStartDate),
|
||||
newEndDate: fmtDate(input.newEndDate),
|
||||
newStartDate: input.newStartDate,
|
||||
newEndDate: input.newEndDate,
|
||||
},
|
||||
preview,
|
||||
};
|
||||
});
|
||||
}),
|
||||
|
||||
getBudgetStatus: controllerProcedure
|
||||
|
||||
Reference in New Issue
Block a user