refactor(api): extract timeline project budget mapping

This commit is contained in:
2026-03-31 15:18:43 +02:00
parent a018d04251
commit ea10851fe4
3 changed files with 166 additions and 34 deletions
@@ -1,4 +1,5 @@
import { TRPCError } from "@trpc/server";
import type { Allocation } from "@capakraken/shared";
import { summarizeHolidayOverlays, type formatHolidayOverlays } from "./timeline-holiday-read.js";
import {
anonymizeResourceOnEntry,
@@ -162,6 +163,79 @@ export function buildTimelineProjectContextSummary(input: {
};
}
export function buildTimelineShiftValidationBookings(
bookings: Array<{
id: string;
resourceId: string | null;
projectId: string | null;
startDate: Date;
endDate: Date;
hoursPerDay: number;
status: string;
}>,
) {
return bookings
.filter(
(
booking,
): booking is typeof booking & { resourceId: string; projectId: string } =>
booking.resourceId !== null && booking.projectId !== null,
)
.map((booking) => ({
id: booking.id,
resourceId: booking.resourceId,
projectId: booking.projectId,
startDate: booking.startDate,
endDate: booking.endDate,
hoursPerDay: booking.hoursPerDay,
status: booking.status,
}));
}
export function buildTimelineBudgetStatusAllocations(
bookings: Array<{
status: string;
dailyCostCents: number;
startDate: Date;
endDate: Date;
hoursPerDay: number;
}>,
): Pick<
Allocation,
"status" | "dailyCostCents" | "startDate" | "endDate" | "hoursPerDay"
>[] {
return bookings.map((booking) => ({
status: booking.status as Allocation["status"],
dailyCostCents: booking.dailyCostCents,
startDate: booking.startDate,
endDate: booking.endDate,
hoursPerDay: booking.hoursPerDay,
}));
}
export function buildTimelineBudgetStatusResponse<TBudgetStatus extends object>(input: {
project: {
name: string;
shortCode: string | null;
budgetCents: number;
};
budgetStatus: TBudgetStatus;
totalAllocations: number;
}): TBudgetStatus & {
projectName: string;
projectCode: string;
totalAllocations: number;
budgetCents: number;
} {
return {
...input.budgetStatus,
projectName: input.project.name,
projectCode: input.project.shortCode ?? "",
totalAllocations: input.totalAllocations,
budgetCents: input.project.budgetCents,
};
}
export function buildTimelineProjectContextResponse<
TProject,
TAllocation extends { resource?: { id: string } | null },