Files
CapaKraken/packages/api/src/lib/vacation-deduction-snapshot.ts
T

121 lines
4.0 KiB
TypeScript

import { Prisma, VacationType } from "@capakraken/db";
import type { TRPCContext } from "../trpc.js";
import { loadResourceHolidayContext } from "./resource-holiday-context.js";
import { countVacationChargeableDays } from "./vacation-day-count.js";
export const VACATION_BALANCE_TYPES = new Set<VacationType>([
VacationType.ANNUAL,
VacationType.OTHER,
]);
export type VacationChargeableInput = {
resourceId: string;
type: VacationType;
startDate: Date;
endDate: Date;
isHalfDay: boolean;
};
export type VacationDeductionSnapshot = {
deductedDays: number;
holidayCountryCode: string | null;
holidayCountryName: string | null;
holidayFederalState: string | null;
holidayMetroCityName: string | null;
holidayCalendarDates: string[];
holidayLegacyPublicHolidayDates: string[];
};
type VacationSnapshotCarrier = {
deductedDays?: number | null;
holidayCountryCode?: string | null;
holidayFederalState?: string | null;
holidayMetroCityName?: string | null;
holidayCalendarDates?: Prisma.JsonValue | null;
holidayLegacyPublicHolidayDates?: Prisma.JsonValue | null;
startDate: Date;
endDate: Date;
isHalfDay: boolean;
};
function isStringArray(value: unknown): value is string[] {
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
}
export function parseVacationSnapshotDateList(value: Prisma.JsonValue | null | undefined): string[] {
return isStringArray(value) ? [...value].sort() : [];
}
export async function calculateVacationDeductionSnapshot(
db: TRPCContext["db"],
vacation: VacationChargeableInput,
): Promise<VacationDeductionSnapshot> {
const holidayContext = await loadResourceHolidayContext(
db,
vacation.resourceId,
vacation.startDate,
vacation.endDate,
);
return {
deductedDays: countVacationChargeableDays({
vacation,
countryCode: holidayContext.countryCode,
federalState: holidayContext.federalState,
metroCityName: holidayContext.metroCityName,
calendarHolidayStrings: holidayContext.calendarHolidayStrings,
publicHolidayStrings: holidayContext.publicHolidayStrings,
}),
holidayCountryCode: holidayContext.countryCode ?? null,
holidayCountryName: holidayContext.countryName ?? null,
holidayFederalState: holidayContext.federalState ?? null,
holidayMetroCityName: holidayContext.metroCityName ?? null,
holidayCalendarDates: [...holidayContext.calendarHolidayStrings].sort(),
holidayLegacyPublicHolidayDates: [...holidayContext.publicHolidayStrings].sort(),
};
}
export function buildVacationDeductionSnapshotWriteData(
snapshot: VacationDeductionSnapshot,
): {
deductedDays: number;
holidayCountryCode: string | null;
holidayCountryName: string | null;
holidayFederalState: string | null;
holidayMetroCityName: string | null;
holidayCalendarDates: Prisma.InputJsonValue;
holidayLegacyPublicHolidayDates: Prisma.InputJsonValue;
} {
return {
deductedDays: snapshot.deductedDays,
holidayCountryCode: snapshot.holidayCountryCode,
holidayCountryName: snapshot.holidayCountryName,
holidayFederalState: snapshot.holidayFederalState,
holidayMetroCityName: snapshot.holidayMetroCityName,
holidayCalendarDates: snapshot.holidayCalendarDates as unknown as Prisma.InputJsonValue,
holidayLegacyPublicHolidayDates:
snapshot.holidayLegacyPublicHolidayDates as unknown as Prisma.InputJsonValue,
};
}
export function countVacationChargeableDaysFromSnapshot(
vacation: VacationSnapshotCarrier,
periodStart?: Date,
periodEnd?: Date,
): number | null {
if (vacation.deductedDays == null) {
return null;
}
return countVacationChargeableDays({
vacation,
periodStart,
periodEnd,
countryCode: vacation.holidayCountryCode,
federalState: vacation.holidayFederalState,
metroCityName: vacation.holidayMetroCityName,
calendarHolidayStrings: parseVacationSnapshotDateList(vacation.holidayCalendarDates),
publicHolidayStrings: parseVacationSnapshotDateList(vacation.holidayLegacyPublicHolidayDates),
});
}