Files
CapaKraken/packages/api/src/router/timeline-entry-read.ts
T

112 lines
4.0 KiB
TypeScript

import { z } from "zod";
import { getAnonymizationDirectory } from "../lib/anonymization.js";
import { controllerProcedure, protectedProcedure } from "../trpc.js";
import {
anonymizeResourceOnEntry,
buildSelfServiceTimelineInput,
createEmptyTimelineEntriesView,
createTimelineDateRange,
createTimelineFilters,
fmtDate,
loadTimelineEntriesReadModel,
summarizeTimelineEntries,
TimelineWindowFiltersSchema,
} from "./timeline-read-shared.js";
import {
formatHolidayOverlays,
loadTimelineHolidayOverlaysForReadModel,
summarizeHolidayOverlays,
} from "./timeline-holiday-read.js";
export const timelineEntryReadProcedures = {
getEntries: controllerProcedure
.input(TimelineWindowFiltersSchema)
.query(async ({ ctx, input }) => {
const readModel = await loadTimelineEntriesReadModel(ctx.db, input);
const directory = await getAnonymizationDirectory(ctx.db);
return readModel.allocations.map((allocation) => anonymizeResourceOnEntry(allocation, directory));
}),
getEntriesView: controllerProcedure
.input(TimelineWindowFiltersSchema)
.query(async ({ ctx, input }) => {
const [readModel, directory] = await Promise.all([
loadTimelineEntriesReadModel(ctx.db, input),
getAnonymizationDirectory(ctx.db),
]);
return {
...readModel,
allocations: readModel.allocations.map((allocation) => anonymizeResourceOnEntry(allocation, directory)),
assignments: readModel.assignments.map((assignment) => anonymizeResourceOnEntry(assignment, directory)),
};
}),
getMyEntriesView: protectedProcedure
.input(TimelineWindowFiltersSchema)
.query(async ({ ctx, input }) => {
const selfServiceInput = await buildSelfServiceTimelineInput(ctx, input);
if (!selfServiceInput) {
return createEmptyTimelineEntriesView();
}
const [readModel, directory] = await Promise.all([
loadTimelineEntriesReadModel(ctx.db, selfServiceInput),
getAnonymizationDirectory(ctx.db),
]);
return {
...readModel,
allocations: readModel.allocations.map((allocation) => anonymizeResourceOnEntry(allocation, directory)),
assignments: readModel.assignments.map((assignment) => anonymizeResourceOnEntry(assignment, directory)),
};
}),
getEntriesDetail: controllerProcedure
.input(
z.object({
startDate: z.string().optional(),
endDate: z.string().optional(),
durationDays: z.number().int().min(1).max(366).optional(),
resourceIds: z.array(z.string()).optional(),
projectIds: z.array(z.string()).optional(),
clientIds: z.array(z.string()).optional(),
chapters: z.array(z.string()).optional(),
eids: z.array(z.string()).optional(),
countryCodes: z.array(z.string()).optional(),
}),
)
.query(async ({ ctx, input }) => {
const { startDate, endDate } = createTimelineDateRange(input);
const filters = createTimelineFilters(input);
const timelineInput = { ...filters, startDate, endDate };
const [readModel, directory] = await Promise.all([
loadTimelineEntriesReadModel(ctx.db, timelineInput),
getAnonymizationDirectory(ctx.db),
]);
const holidayOverlays = await loadTimelineHolidayOverlaysForReadModel(
ctx.db,
timelineInput,
readModel,
);
const formattedHolidayOverlays = formatHolidayOverlays(holidayOverlays);
return {
period: {
startDate: fmtDate(startDate),
endDate: fmtDate(endDate),
},
filters,
summary: {
...summarizeTimelineEntries(readModel),
...summarizeHolidayOverlays(formattedHolidayOverlays),
},
allocations: readModel.allocations.map((allocation) => anonymizeResourceOnEntry(allocation, directory)),
demands: readModel.demands,
assignments: readModel.assignments.map((assignment) => anonymizeResourceOnEntry(assignment, directory)),
holidayOverlays: formattedHolidayOverlays,
};
}),
};