Files
CapaKraken/packages/api/src/router/timeline-allocation-shift-support.ts
T

75 lines
2.1 KiB
TypeScript

import { findAllocationEntry, updateAllocationEntry } from "@capakraken/application";
import type { PrismaClient } from "@capakraken/db";
import { TRPCError } from "@trpc/server";
import {
buildTimelineBatchShiftAuditChanges,
shiftTimelineAllocationWindow,
type TimelineBatchShiftMode,
} from "./timeline-allocation-batch-shift-support.js";
export async function applyTimelineBatchAllocationShift(input: {
db: PrismaClient;
allocationIds: string[];
daysDelta: number;
mode: TimelineBatchShiftMode;
}) {
if (input.daysDelta === 0) {
return [];
}
const entries = await Promise.all(
input.allocationIds.map((allocationId) => findAllocationEntry(input.db, allocationId)),
);
const resolved = entries.filter(
(entry): entry is NonNullable<typeof entry> => entry !== null,
);
if (resolved.length === 0) {
throw new TRPCError({ code: "NOT_FOUND", message: "No allocations found" });
}
return input.db.$transaction(async (tx) => {
const updated = [];
for (const entry of resolved) {
const existing = entry.entry;
const shiftedWindow = shiftTimelineAllocationWindow({
startDate: existing.startDate,
endDate: existing.endDate,
daysDelta: input.daysDelta,
mode: input.mode,
});
const result = await updateAllocationEntry(
tx as unknown as Parameters<typeof updateAllocationEntry>[0],
{
id: existing.id,
demandRequirementUpdate: {
startDate: shiftedWindow.startDate,
endDate: shiftedWindow.endDate,
},
assignmentUpdate: {
startDate: shiftedWindow.startDate,
endDate: shiftedWindow.endDate,
},
},
);
updated.push(result.allocation);
}
await tx.auditLog.create({
data: {
entityType: "Allocation",
entityId: input.allocationIds.join(","),
action: "UPDATE",
changes: buildTimelineBatchShiftAuditChanges({
mode: input.mode,
daysDelta: input.daysDelta,
count: resolved.length,
}),
},
});
return updated;
});
}