96 lines
3.3 KiB
TypeScript
96 lines
3.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
tx: {
|
|
projekt: { findFirst: vi.fn() },
|
|
projektMitglied: { findMany: vi.fn() },
|
|
projektTermin: { findMany: vi.fn() },
|
|
rechnung: { findMany: vi.fn() },
|
|
projektChecklist: { findMany: vi.fn() },
|
|
auftragPipelineStageConfig: { findFirst: vi.fn() },
|
|
acceptanceFormTemplate: { upsert: vi.fn(), findMany: vi.fn() },
|
|
projectTemplate: { upsert: vi.fn(), findMany: vi.fn() },
|
|
projektChecklistItem: { count: vi.fn() },
|
|
task: { findMany: vi.fn() },
|
|
fileEntityLink: { findMany: vi.fn() },
|
|
group: { findMany: vi.fn() },
|
|
kwpMaterialPosition: { findMany: vi.fn() },
|
|
},
|
|
}));
|
|
|
|
vi.mock("~/utils/db/.server/tenantRls.server", () => ({
|
|
withTenantRLS: async (_tenantId: string, callback: (tx: typeof mocks.tx) => Promise<unknown>) => callback(mocks.tx),
|
|
}));
|
|
|
|
import { loadProjectSubAreas } from "./auftragService.server";
|
|
|
|
describe("KWP material project sub-area", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mocks.tx.projekt.findFirst.mockResolvedValue({
|
|
id: "project-1",
|
|
tenantId: "tenant-1",
|
|
projektleiterId: null,
|
|
zustaendigePersonId: null,
|
|
stageId: "stage-1",
|
|
});
|
|
mocks.tx.acceptanceFormTemplate.upsert.mockResolvedValue({ id: "acceptance-default" });
|
|
mocks.tx.projectTemplate.upsert.mockResolvedValue({ id: "project-default" });
|
|
mocks.tx.projektMitglied.findMany.mockResolvedValue([]);
|
|
mocks.tx.projektTermin.findMany.mockResolvedValue([]);
|
|
mocks.tx.rechnung.findMany.mockResolvedValue([]);
|
|
mocks.tx.projektChecklist.findMany.mockResolvedValue([]);
|
|
mocks.tx.auftragPipelineStageConfig.findFirst.mockResolvedValue(null);
|
|
mocks.tx.acceptanceFormTemplate.findMany.mockResolvedValue([]);
|
|
mocks.tx.projectTemplate.findMany.mockResolvedValue([]);
|
|
mocks.tx.projektChecklistItem.count.mockResolvedValue(0);
|
|
mocks.tx.task.findMany.mockResolvedValue([]);
|
|
mocks.tx.fileEntityLink.findMany.mockResolvedValue([]);
|
|
mocks.tx.group.findMany.mockResolvedValue([]);
|
|
mocks.tx.kwpMaterialPosition.findMany.mockResolvedValue([
|
|
{
|
|
id: "material-1",
|
|
positionNumber: "01.01",
|
|
text: "Ventil",
|
|
longText: "DN 20",
|
|
quantity: "2",
|
|
unit: "Stk",
|
|
unitPrice: "12.50",
|
|
totalPrice: "25.00",
|
|
lastSyncedAt: new Date("2026-07-24T10:00:00.000Z"),
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("loads only active material positions from the bound tenant and project", async () => {
|
|
const result = await loadProjectSubAreas({
|
|
tenantId: "tenant-1",
|
|
projectId: "project-1",
|
|
ctx: {
|
|
userId: "user-1",
|
|
permissions: ["projects.read_all"],
|
|
roleIds: [],
|
|
groupIds: [],
|
|
},
|
|
});
|
|
|
|
expect(mocks.tx.kwpMaterialPosition.findMany).toHaveBeenCalledWith({
|
|
where: { tenantId: "tenant-1", projektId: "project-1", archivedAt: null },
|
|
select: {
|
|
id: true,
|
|
positionNumber: true,
|
|
text: true,
|
|
longText: true,
|
|
quantity: true,
|
|
unit: true,
|
|
unitPrice: true,
|
|
totalPrice: true,
|
|
lastSyncedAt: true,
|
|
},
|
|
orderBy: [{ positionNumber: "asc" }, { externalId: "asc" }],
|
|
take: 500,
|
|
});
|
|
expect(result.materials).toEqual([expect.objectContaining({ id: "material-1", text: "Ventil", totalPrice: "25.00" })]);
|
|
});
|
|
});
|