import { describe, expect, it, vi } from "vitest"; import { listAssignmentBookings } from "../index.js"; describe("listAssignmentBookings", () => { it("returns assignments with cost metadata", async () => { const db = { assignment: { findMany: vi.fn().mockResolvedValue([ { id: "asn_1", projectId: "proj_1", resourceId: "res_1", startDate: new Date("2026-03-01T00:00:00.000Z"), endDate: new Date("2026-03-02T00:00:00.000Z"), hoursPerDay: 6, dailyCostCents: 900, status: "CONFIRMED", project: { id: "proj_1", name: "Alpha", shortCode: "ALPHA", status: "ACTIVE", orderType: "CHARGEABLE", dynamicFields: null, }, resource: { id: "res_1", displayName: "Alice", chapter: "CGI", }, }, { id: "asn_2", projectId: "proj_2", resourceId: "res_2", startDate: new Date("2026-03-03T00:00:00.000Z"), endDate: new Date("2026-03-03T00:00:00.000Z"), hoursPerDay: 4, dailyCostCents: 500, status: "PROPOSED", project: { id: "proj_2", name: "Bravo", shortCode: "BRAVO", status: "DRAFT", orderType: "INTERNAL", dynamicFields: null, }, resource: { id: "res_2", displayName: "Bob", chapter: "Lighting", }, }, ]), }, }; const result = await listAssignmentBookings(db as never, { startDate: new Date("2026-03-01T00:00:00.000Z"), endDate: new Date("2026-03-31T00:00:00.000Z"), }); expect(result).toEqual([ { id: "asn_1", projectId: "proj_1", resourceId: "res_1", startDate: new Date("2026-03-01T00:00:00.000Z"), endDate: new Date("2026-03-02T00:00:00.000Z"), hoursPerDay: 6, dailyCostCents: 900, status: "CONFIRMED", project: { id: "proj_1", name: "Alpha", shortCode: "ALPHA", status: "ACTIVE", orderType: "CHARGEABLE", dynamicFields: null, }, resource: { id: "res_1", displayName: "Alice", chapter: "CGI", }, }, { id: "asn_2", projectId: "proj_2", resourceId: "res_2", startDate: new Date("2026-03-03T00:00:00.000Z"), endDate: new Date("2026-03-03T00:00:00.000Z"), hoursPerDay: 4, dailyCostCents: 500, status: "PROPOSED", project: { id: "proj_2", name: "Bravo", shortCode: "BRAVO", status: "DRAFT", orderType: "INTERNAL", dynamicFields: null, }, resource: { id: "res_2", displayName: "Bob", chapter: "Lighting", }, }, ]); }); it("supports unbounded resource context queries when no date window is provided", async () => { const db = { assignment: { findMany: vi.fn().mockResolvedValue([]), }, }; await listAssignmentBookings(db as never, { resourceIds: ["res_1", "res_2"], }); expect(db.assignment.findMany).toHaveBeenCalledWith({ where: { status: { not: "CANCELLED" }, resourceId: { in: ["res_1", "res_2"] }, }, select: { id: true, projectId: true, resourceId: true, startDate: true, endDate: true, hoursPerDay: true, dailyCostCents: true, status: true, project: { select: { id: true, name: true, shortCode: true, status: true, orderType: true, clientId: true, dynamicFields: true, }, }, resource: { select: { id: true, displayName: true, chapter: true }, }, }, }); }); it("rejects partial date bounds", async () => { const db = { assignment: { findMany: vi.fn(), }, }; await expect( listAssignmentBookings(db as never, { startDate: new Date("2026-03-01T00:00:00.000Z"), }), ).rejects.toThrow("startDate and endDate must be provided together"); expect(db.assignment.findMany).not.toHaveBeenCalled(); }); it("supports excluding explicit assignment ids", async () => { const db = { assignment: { findMany: vi.fn().mockResolvedValue([]), }, }; await listAssignmentBookings(db as never, { resourceIds: ["res_1"], excludeAssignmentIds: ["asn_1"], }); expect(db.assignment.findMany).toHaveBeenCalledWith({ where: { status: { not: "CANCELLED" }, resourceId: { in: ["res_1"] }, id: { notIn: ["asn_1"] }, }, select: { id: true, projectId: true, resourceId: true, startDate: true, endDate: true, hoursPerDay: true, dailyCostCents: true, status: true, project: { select: { id: true, name: true, shortCode: true, status: true, orderType: true, clientId: true, dynamicFields: true, }, }, resource: { select: { id: true, displayName: true, chapter: true }, }, }, }); }); });