import { beforeEach, describe, expect, it, vi } from "vitest"; import { PermissionKey, SystemRole } from "@capakraken/shared"; vi.mock("@capakraken/application", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, countPlanningEntries: vi.fn().mockResolvedValue({ countsByRoleId: new Map() }), getDashboardBudgetForecast: vi.fn().mockResolvedValue([]), getDashboardPeakTimes: vi.fn().mockResolvedValue([]), listAssignmentBookings: vi.fn().mockResolvedValue([]), }; }); import { countPlanningEntries } from "@capakraken/application"; import { executeTool } from "../router/assistant-tools.js"; import { createToolContext } from "./assistant-tools-master-data-read-test-helpers.js"; describe("assistant master data rate lookup tools", () => { beforeEach(() => { vi.clearAllMocks(); vi.mocked(countPlanningEntries).mockResolvedValue({ countsByRoleId: new Map() }); }); it("routes rate lookup reads through the rate-card router path", async () => { const db = { rateCard: { findMany: vi.fn().mockResolvedValue([ { id: "rc_client", name: "Client 2026", client: { id: "client_1", name: "Acme Mobility" }, lines: [ { id: "line_best", chapter: "Delivery", seniority: "Senior", costRateCents: 12_000, billRateCents: 18_000, role: { id: "role_1", name: "Pipeline TD" }, }, ], }, { id: "rc_default", name: "Default 2026", client: null, lines: [ { id: "line_alt", chapter: "Delivery", seniority: "Senior", costRateCents: 11_000, billRateCents: 17_000, role: { id: "role_1", name: "Pipeline TD" }, }, ], }, ]), }, role: { findFirst: vi.fn().mockResolvedValue({ id: "role_1" }), }, }; const ctx = createToolContext(db, { userRole: SystemRole.CONTROLLER, permissions: [PermissionKey.VIEW_COSTS], }); const result = await executeTool( "lookup_rate", JSON.stringify({ clientId: "client_1", chapter: "Delivery", roleName: "Pipeline", seniority: "Senior", }), ctx, ); expect(db.rateCard.findMany).toHaveBeenCalledWith({ where: { isActive: true, OR: [{ clientId: "client_1" }, { clientId: null }], }, include: { lines: { select: { id: true, chapter: true, seniority: true, costRateCents: true, billRateCents: true, role: { select: { id: true, name: true } }, }, }, client: { select: { id: true, name: true } }, }, orderBy: [{ effectiveFrom: "desc" }], }); expect(db.role.findFirst).toHaveBeenCalledWith({ where: { name: { contains: "Pipeline", mode: "insensitive" } }, select: { id: true }, }); expect(JSON.parse(result.content)).toEqual({ bestMatch: { rateCardName: "Client 2026", clientId: "client_1", clientName: "Acme Mobility", lineId: "line_best", chapter: "Delivery", seniority: "Senior", roleName: "Pipeline TD", costRateCents: 12000, billRateCents: 18000, score: 10, costRate: "120,00 EUR", billRate: "180,00 EUR", }, alternatives: [ { rateCardName: "Default 2026", clientId: null, clientName: null, lineId: "line_alt", chapter: "Delivery", seniority: "Senior", roleName: "Pipeline TD", costRateCents: 11000, billRateCents: 17000, score: 7, costRate: "110,00 EUR", billRate: "170,00 EUR", }, ], totalCandidates: 2, }); }); });