import { beforeEach, describe, expect, it, vi } from "vitest"; import { VacationType } from "@capakraken/db"; import { SystemRole } from "@capakraken/shared"; vi.mock("@capakraken/application", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, approveEstimateVersion: vi.fn(), cloneEstimate: vi.fn(), commitDispoImportBatch: vi.fn(), countPlanningEntries: vi.fn().mockResolvedValue({ countsByRoleId: new Map() }), createEstimateExport: vi.fn(), createEstimatePlanningHandoff: vi.fn(), createEstimateRevision: vi.fn(), assessDispoImportReadiness: vi.fn(), loadResourceDailyAvailabilityContexts: vi.fn().mockResolvedValue(new Map()), getDashboardDemand: vi.fn().mockResolvedValue([]), getDashboardBudgetForecast: vi.fn().mockResolvedValue([]), getDashboardOverview: vi.fn(), getDashboardSkillGapSummary: vi.fn().mockResolvedValue({ roleGaps: [], totalOpenPositions: 0, skillSupplyTop10: [], resourcesByRole: [], }), getDashboardProjectHealth: vi.fn().mockResolvedValue([]), getDashboardPeakTimes: vi.fn().mockResolvedValue([]), getDashboardTopValueResources: vi.fn().mockResolvedValue([]), getEstimateById: vi.fn(), listAssignmentBookings: vi.fn().mockResolvedValue([]), stageDispoImportBatch: vi.fn(), submitEstimateVersion: vi.fn(), updateEstimateDraft: vi.fn(), }; }); import { executeTool } from "../router/assistant-tools.js"; import { createToolContext } from "./assistant-tools-vacation-entitlement-test-helpers.js"; describe("assistant vacation balance tools", () => { beforeEach(() => { vi.clearAllMocks(); }); it("routes vacation balance through the real vacation workflow", async () => { const vacationFindMany = vi.fn().mockImplementation(async (args?: any) => { if (args?.where?.type === VacationType.PUBLIC_HOLIDAY) { return []; } if (args?.where?.type?.in) { return [ { type: VacationType.ANNUAL, startDate: new Date("2026-01-05T00:00:00.000Z"), endDate: new Date("2026-01-06T00:00:00.000Z"), status: "APPROVED", isHalfDay: false, }, { type: VacationType.ANNUAL, startDate: new Date("2026-02-03T00:00:00.000Z"), endDate: new Date("2026-02-03T00:00:00.000Z"), status: "PENDING", isHalfDay: true, }, ]; } if (args?.where?.type === VacationType.SICK) { return [ { startDate: new Date("2026-03-10T00:00:00.000Z"), endDate: new Date("2026-03-10T00:00:00.000Z"), isHalfDay: false, }, ]; } return []; }); const ctx = createToolContext({ resource: { findUnique: vi.fn().mockResolvedValue({ id: "res_1", eid: "EMP-001", displayName: "Alice Example", userId: "user_1", chapter: "Delivery", federalState: "BY", countryId: "country_de", metroCityId: null, country: { code: "DE", name: "Germany" }, metroCity: null, }), }, holidayCalendar: { findMany: vi.fn().mockResolvedValue([]), }, systemSettings: { findUnique: vi.fn().mockResolvedValue({ vacationDefaultDays: 30 }), }, vacationEntitlement: { findUnique: vi.fn().mockResolvedValue(null), create: vi.fn().mockResolvedValue({ id: "ent_2026", resourceId: "res_1", year: 2026, entitledDays: 30, carryoverDays: 0, usedDays: 0, pendingDays: 0, }), update: vi.fn().mockImplementation(async (args?: any) => ({ id: "ent_2026", resourceId: "res_1", year: 2026, entitledDays: 30, carryoverDays: 0, usedDays: args?.data?.usedDays ?? 0, pendingDays: args?.data?.pendingDays ?? 0, })), }, vacation: { findMany: vacationFindMany, }, }, { userRole: SystemRole.ADMIN }); const result = await executeTool( "get_vacation_balance", JSON.stringify({ resourceId: "res_1", year: 2026 }), ctx, ); expect(JSON.parse(result.content)).toEqual(expect.objectContaining({ resource: "Alice Example", eid: "EMP-001", year: 2026, entitlement: 30, carryOver: 0, taken: 1, pending: 0.5, remaining: 28.5, sickDays: 1, deductionSummary: { formula: "remaining = entitlement - taken - pending", approvedVacationCount: 1, pendingVacationCount: 1, approvedRequestedDays: 2, pendingRequestedDays: 0.5, approvedDeductedDays: 1, pendingDeductedDays: 0.5, excludedHolidayDates: ["2026-01-06"], holidayBasisVariants: ["Germany / BY"], sources: { hasCalendarHolidays: true, hasLegacyPublicHolidayEntries: false, }, }, vacations: [ expect.objectContaining({ type: "ANNUAL", status: "APPROVED", startDate: "2026-01-05", endDate: "2026-01-06", isHalfDay: false, requestedDays: 2, deductedDays: 1, holidayCountryCode: "DE", holidayCountryName: "Germany", holidayFederalState: "BY", holidayMetroCityName: null, holidayCalendarDates: ["2026-01-06"], holidayLegacyPublicHolidayDates: [], holidayDetails: [{ date: "2026-01-06", source: "CALENDAR" }], holidayContext: { countryCode: "DE", countryName: "Germany", federalState: "BY", metroCityName: null, sources: { hasCalendarHolidays: true, hasLegacyPublicHolidayEntries: false, }, }, }), expect.objectContaining({ type: "ANNUAL", status: "PENDING", startDate: "2026-02-03", endDate: "2026-02-03", isHalfDay: true, requestedDays: 0.5, deductedDays: 0.5, holidayCountryCode: "DE", holidayCountryName: "Germany", holidayFederalState: "BY", holidayMetroCityName: null, holidayCalendarDates: [], holidayLegacyPublicHolidayDates: [], holidayDetails: [], holidayContext: { countryCode: "DE", countryName: "Germany", federalState: "BY", metroCityName: null, sources: { hasCalendarHolidays: false, hasLegacyPublicHolidayEntries: false, }, }, }), ], })); }); });