fix(api): honor vacation deduction snapshots
This commit is contained in:
@@ -11,6 +11,9 @@ import { createTRPCRouter, adminProcedure, managerProcedure, protectedProcedure
|
||||
import { createAuditEntry } from "../lib/audit.js";
|
||||
import { loadResourceHolidayContext } from "../lib/resource-holiday-context.js";
|
||||
import { countCalendarDaysInPeriod, countVacationChargeableDays } from "../lib/vacation-day-count.js";
|
||||
import {
|
||||
countVacationChargeableDaysFromSnapshot,
|
||||
} from "../lib/vacation-deduction-snapshot.js";
|
||||
|
||||
/** Types that consume from annual leave balance */
|
||||
const BALANCE_TYPES: VacationType[] = [VacationType.ANNUAL, VacationType.OTHER];
|
||||
@@ -230,6 +233,40 @@ function calculateCarryoverDays(entitlement: {
|
||||
return Math.max(0, entitlement.entitledDays - entitlement.usedDays - entitlement.pendingDays);
|
||||
}
|
||||
|
||||
async function calculateEntitlementVacationDays(
|
||||
yearStart: Date,
|
||||
yearEnd: Date,
|
||||
vacation: {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
isHalfDay: boolean;
|
||||
deductedDays: number | null;
|
||||
holidayCountryCode: string | null;
|
||||
holidayFederalState: string | null;
|
||||
holidayMetroCityName: string | null;
|
||||
holidayCalendarDates: import("@capakraken/db").Prisma.JsonValue | null;
|
||||
holidayLegacyPublicHolidayDates: import("@capakraken/db").Prisma.JsonValue | null;
|
||||
},
|
||||
getLegacyHolidayContext: () => Promise<Awaited<ReturnType<typeof loadResourceHolidayContext>>>,
|
||||
): Promise<number> {
|
||||
const persistedDays = countVacationChargeableDaysFromSnapshot(vacation, yearStart, yearEnd);
|
||||
if (persistedDays !== null) {
|
||||
return persistedDays;
|
||||
}
|
||||
|
||||
const holidayContext = await getLegacyHolidayContext();
|
||||
return countVacationChargeableDays({
|
||||
vacation,
|
||||
periodStart: yearStart,
|
||||
periodEnd: yearEnd,
|
||||
countryCode: holidayContext.countryCode,
|
||||
federalState: holidayContext.federalState,
|
||||
metroCityName: holidayContext.metroCityName,
|
||||
calendarHolidayStrings: holidayContext.calendarHolidayStrings,
|
||||
publicHolidayStrings: holidayContext.publicHolidayStrings,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recompute used/pending days from actual vacation records and update the cached values.
|
||||
*/
|
||||
@@ -281,7 +318,6 @@ async function syncEntitlement(
|
||||
: entitlement;
|
||||
const yearStart = new Date(`${year}-01-01T00:00:00.000Z`);
|
||||
const yearEnd = new Date(`${year}-12-31T00:00:00.000Z`);
|
||||
const holidayContext = await loadResourceHolidayContext(db, resourceId, yearStart, yearEnd);
|
||||
|
||||
const vacations = await db.vacation.findMany({
|
||||
where: {
|
||||
@@ -291,23 +327,37 @@ async function syncEntitlement(
|
||||
endDate: { gte: yearStart },
|
||||
status: { in: [VacationStatus.APPROVED, VacationStatus.PENDING] },
|
||||
},
|
||||
select: { startDate: true, endDate: true, status: true, isHalfDay: true },
|
||||
select: {
|
||||
startDate: true,
|
||||
endDate: true,
|
||||
status: true,
|
||||
isHalfDay: true,
|
||||
deductedDays: true,
|
||||
holidayCountryCode: true,
|
||||
holidayFederalState: true,
|
||||
holidayMetroCityName: true,
|
||||
holidayCalendarDates: true,
|
||||
holidayLegacyPublicHolidayDates: true,
|
||||
},
|
||||
});
|
||||
|
||||
let usedDays = 0;
|
||||
let pendingDays = 0;
|
||||
let legacyHolidayContextPromise: Promise<Awaited<ReturnType<typeof loadResourceHolidayContext>>> | null = null;
|
||||
const getLegacyHolidayContext = async () => {
|
||||
if (!legacyHolidayContextPromise) {
|
||||
legacyHolidayContextPromise = loadResourceHolidayContext(db, resourceId, yearStart, yearEnd);
|
||||
}
|
||||
return legacyHolidayContextPromise;
|
||||
};
|
||||
|
||||
for (const v of vacations) {
|
||||
const days = countVacationChargeableDays({
|
||||
vacation: v,
|
||||
periodStart: yearStart,
|
||||
periodEnd: yearEnd,
|
||||
countryCode: holidayContext.countryCode,
|
||||
federalState: holidayContext.federalState,
|
||||
metroCityName: holidayContext.metroCityName,
|
||||
calendarHolidayStrings: holidayContext.calendarHolidayStrings,
|
||||
publicHolidayStrings: holidayContext.publicHolidayStrings,
|
||||
});
|
||||
const days = await calculateEntitlementVacationDays(
|
||||
yearStart,
|
||||
yearEnd,
|
||||
v,
|
||||
getLegacyHolidayContext,
|
||||
);
|
||||
if (v.status === VacationStatus.APPROVED) usedDays += days;
|
||||
else pendingDays += days;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user