feat(platform): checkpoint current implementation state
This commit is contained in:
@@ -77,6 +77,16 @@ export interface TimelineAllocationCarveResult {
|
||||
resourceId: string | null;
|
||||
}
|
||||
|
||||
export interface TimelineAllocationExtractResult {
|
||||
action: "unchanged" | "extracted";
|
||||
allocationGroupId: string;
|
||||
extractedAllocationId: string;
|
||||
updatedAllocationIds: string[];
|
||||
createdAllocationIds: string[];
|
||||
projectId: string;
|
||||
resourceId: string | null;
|
||||
}
|
||||
|
||||
export async function carveTimelineAllocationRange(input: {
|
||||
db: PrismaClient;
|
||||
allocationId: string;
|
||||
@@ -183,3 +193,119 @@ export async function carveTimelineAllocationRange(input: {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function extractTimelineAllocationFragment(input: {
|
||||
db: PrismaClient;
|
||||
allocationId: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
}): Promise<TimelineAllocationExtractResult> {
|
||||
const resolved = await loadAllocationEntry(input.db, input.allocationId);
|
||||
if (resolved.kind !== "assignment") {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Only staffed assignments can currently be extracted into fragments.",
|
||||
});
|
||||
}
|
||||
|
||||
const extractStart = toUtcCalendarDate(input.startDate);
|
||||
const extractEnd = toUtcCalendarDate(input.endDate);
|
||||
if (extractEnd < extractStart) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Extract end date must be on or after the extract start date.",
|
||||
});
|
||||
}
|
||||
|
||||
const assignment = resolved.assignment;
|
||||
const assignmentStart = toUtcCalendarDate(assignment.startDate);
|
||||
const assignmentEnd = toUtcCalendarDate(assignment.endDate);
|
||||
if (extractStart < assignmentStart || extractEnd > assignmentEnd) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "The requested extract range must be fully inside the existing allocation.",
|
||||
});
|
||||
}
|
||||
|
||||
const { groupId, metadata } = readFragmentMetadata(assignment.metadata, assignment.id);
|
||||
const hasLeftFragment = extractStart > assignmentStart;
|
||||
const hasRightFragment = extractEnd < assignmentEnd;
|
||||
|
||||
if (!hasLeftFragment && !hasRightFragment) {
|
||||
return {
|
||||
action: "unchanged",
|
||||
allocationGroupId: groupId,
|
||||
extractedAllocationId: assignment.id,
|
||||
updatedAllocationIds: [],
|
||||
createdAllocationIds: [],
|
||||
projectId: assignment.projectId,
|
||||
resourceId: assignment.resourceId,
|
||||
};
|
||||
}
|
||||
|
||||
return input.db.$transaction(async (tx) => {
|
||||
const createdAllocationIds: string[] = [];
|
||||
|
||||
const updated = await updateAssignment(
|
||||
tx as unknown as Parameters<typeof updateAssignment>[0],
|
||||
assignment.id,
|
||||
{
|
||||
startDate: extractStart,
|
||||
endDate: extractEnd,
|
||||
metadata,
|
||||
},
|
||||
);
|
||||
|
||||
if (hasLeftFragment) {
|
||||
const createdLeft = await createAssignment(
|
||||
tx as unknown as Parameters<typeof createAssignment>[0],
|
||||
{
|
||||
demandRequirementId: assignment.demandRequirementId ?? undefined,
|
||||
resourceId: assignment.resourceId,
|
||||
projectId: assignment.projectId,
|
||||
startDate: assignmentStart,
|
||||
endDate: addDays(extractStart, -1),
|
||||
hoursPerDay: assignment.hoursPerDay,
|
||||
percentage: assignment.percentage,
|
||||
role: assignment.role ?? undefined,
|
||||
roleId: assignment.roleId ?? undefined,
|
||||
dailyCostCents: assignment.dailyCostCents,
|
||||
status: toSharedAllocationStatus(assignment.status),
|
||||
metadata,
|
||||
},
|
||||
);
|
||||
createdAllocationIds.push(createdLeft.id);
|
||||
}
|
||||
|
||||
if (hasRightFragment) {
|
||||
const createdRight = await createAssignment(
|
||||
tx as unknown as Parameters<typeof createAssignment>[0],
|
||||
{
|
||||
demandRequirementId: assignment.demandRequirementId ?? undefined,
|
||||
resourceId: assignment.resourceId,
|
||||
projectId: assignment.projectId,
|
||||
startDate: addDays(extractEnd, 1),
|
||||
endDate: assignmentEnd,
|
||||
hoursPerDay: assignment.hoursPerDay,
|
||||
percentage: assignment.percentage,
|
||||
role: assignment.role ?? undefined,
|
||||
roleId: assignment.roleId ?? undefined,
|
||||
dailyCostCents: assignment.dailyCostCents,
|
||||
status: toSharedAllocationStatus(assignment.status),
|
||||
metadata,
|
||||
},
|
||||
);
|
||||
createdAllocationIds.push(createdRight.id);
|
||||
}
|
||||
|
||||
return {
|
||||
action: "extracted" as const,
|
||||
allocationGroupId: groupId,
|
||||
extractedAllocationId: updated.id,
|
||||
updatedAllocationIds: [updated.id],
|
||||
createdAllocationIds,
|
||||
projectId: assignment.projectId,
|
||||
resourceId: assignment.resourceId,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user