import { TRPCError } from "@trpc/server"; import { countCalendarDaysInPeriod } from "../lib/vacation-day-count.js"; import { VACATION_BALANCE_TYPES, buildVacationDeductionSnapshotWriteData, calculateVacationDeductionSnapshot, type VacationChargeableInput, } from "../lib/vacation-deduction-snapshot.js"; import type { TRPCContext } from "../trpc.js"; type VacationDb = TRPCContext["db"]; type VacationDeductionWriteData = ReturnType; export async function calculateVacationEffectiveDays( db: VacationDb, vacation: VacationChargeableInput, ): Promise { if (!VACATION_BALANCE_TYPES.has(vacation.type)) { return countCalendarDaysInPeriod(vacation); } const snapshot = await calculateVacationDeductionSnapshot(db, vacation); return snapshot.deductedDays; } export async function assertVacationStillChargeable( db: VacationDb, vacation: VacationChargeableInput, ): Promise { if (!VACATION_BALANCE_TYPES.has(vacation.type)) { return; } const effectiveDays = await calculateVacationEffectiveDays(db, vacation); if (effectiveDays <= 0) { throw new TRPCError({ code: "BAD_REQUEST", message: "Vacation no longer deducts any vacation days for the current holiday calendar and cannot be approved", }); } } export async function resolveVacationCreationChargeability( db: VacationDb, vacation: VacationChargeableInput, ): Promise<{ effectiveDays: number | null; deductionSnapshotWriteData: VacationDeductionWriteData | null; }> { if (!VACATION_BALANCE_TYPES.has(vacation.type)) { return { effectiveDays: null, deductionSnapshotWriteData: null, }; } const deductionSnapshot = await calculateVacationDeductionSnapshot(db, vacation); const effectiveDays = deductionSnapshot.deductedDays; if (effectiveDays <= 0) { throw new TRPCError({ code: "BAD_REQUEST", message: "Selected vacation period only contains public holidays and does not deduct any vacation days", }); } return { effectiveDays, deductionSnapshotWriteData: buildVacationDeductionSnapshotWriteData(deductionSnapshot), }; } export async function buildVacationApprovalWriteData( db: VacationDb, vacation: VacationChargeableInput, ): Promise { if (!VACATION_BALANCE_TYPES.has(vacation.type)) { return { deductedDays: 0 }; } return buildVacationDeductionSnapshotWriteData( await calculateVacationDeductionSnapshot(db, vacation), ); }