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 => 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[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; }); }