import { VacationStatus, VacationType } from "@capakraken/db"; import { getResolvedCalendarHolidayStrings, toIsoDate } from "./holiday-availability.js"; type ResourceHolidayContextDb = { resource: { findUnique: (args: any) => any; }; country?: { findUnique: (args: any) => any; }; metroCity?: { findUnique: (args: any) => any; }; holidayCalendar?: { findMany: (args: any) => any; }; vacation: { findMany: (args: any) => any; }; }; export type ResourceHolidayContext = { countryId?: string | null; countryCode?: string | null; countryName?: string | null; federalState?: string | null; metroCityId?: string | null; metroCityName?: string | null; calendarHolidayStrings: string[]; publicHolidayStrings: string[]; }; function clampToDay(value: Date): Date { const date = new Date(value); date.setUTCHours(0, 0, 0, 0); return date; } export async function loadResourceHolidayContext( db: ResourceHolidayContextDb, resourceId: string, periodStart: Date, periodEnd: Date, ): Promise { const resource = typeof db.resource?.findUnique === "function" ? await db.resource.findUnique({ where: { id: resourceId }, select: { federalState: true, countryId: true, metroCityId: true, country: { select: { code: true, name: true } }, metroCity: { select: { name: true } }, }, }) : null; const holidayVacations = typeof db.vacation?.findMany === "function" ? await db.vacation.findMany({ where: { resourceId, type: VacationType.PUBLIC_HOLIDAY, status: VacationStatus.APPROVED, startDate: { lte: periodEnd }, endDate: { gte: periodStart }, }, select: { startDate: true, endDate: true }, }) : []; const calendarHolidayStrings = await getResolvedCalendarHolidayStrings(db, { periodStart, periodEnd, countryId: resource?.countryId ?? null, countryCode: resource?.country?.code ?? null, federalState: resource?.federalState ?? null, metroCityId: resource?.metroCityId ?? null, metroCityName: resource?.metroCity?.name ?? null, }); const publicHolidayStrings = new Set(); for (const holiday of holidayVacations) { const cursor = clampToDay(new Date(Math.max(holiday.startDate.getTime(), periodStart.getTime()))); const end = clampToDay(new Date(Math.min(holiday.endDate.getTime(), periodEnd.getTime()))); while (cursor <= end) { publicHolidayStrings.add(toIsoDate(cursor)); cursor.setUTCDate(cursor.getUTCDate() + 1); } } return { countryId: resource?.countryId ?? null, countryCode: resource?.country?.code ?? null, countryName: resource?.country?.name ?? null, federalState: resource?.federalState ?? null, metroCityId: resource?.metroCityId ?? null, metroCityName: resource?.metroCity?.name ?? null, calendarHolidayStrings, publicHolidayStrings: [...publicHolidayStrings].sort(), }; }