chore(repo): initialize planarchy workspace
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import { AllocationStatus, SystemRole } from "@planarchy/shared";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { roleRouter } from "../router/role.js";
|
||||
import { createCallerFactory } from "../trpc.js";
|
||||
|
||||
vi.mock("../sse/event-bus.js", () => ({
|
||||
emitRoleCreated: vi.fn(),
|
||||
emitRoleDeleted: vi.fn(),
|
||||
emitRoleUpdated: vi.fn(),
|
||||
}));
|
||||
|
||||
const createCaller = createCallerFactory(roleRouter);
|
||||
|
||||
function createManagerCaller(db: Record<string, unknown>) {
|
||||
return createCaller({
|
||||
session: {
|
||||
user: { email: "manager@example.com", name: "Manager", image: null },
|
||||
expires: "2026-03-13T00:00:00.000Z",
|
||||
},
|
||||
db: db as never,
|
||||
dbUser: {
|
||||
id: "user_1",
|
||||
systemRole: SystemRole.MANAGER,
|
||||
permissionOverrides: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe("role router planning counts", () => {
|
||||
it("reports planning entry counts for roles", async () => {
|
||||
const db = {
|
||||
role: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "role_fx",
|
||||
name: "FX",
|
||||
description: null,
|
||||
color: "#111111",
|
||||
isActive: true,
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
_count: { resourceRoles: 2 },
|
||||
},
|
||||
]),
|
||||
},
|
||||
allocation: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "legacy_demand",
|
||||
resourceId: null,
|
||||
projectId: "project_1",
|
||||
startDate: new Date("2026-03-17"),
|
||||
endDate: new Date("2026-03-18"),
|
||||
hoursPerDay: 8,
|
||||
percentage: 100,
|
||||
role: "FX",
|
||||
roleId: "role_fx",
|
||||
isPlaceholder: true,
|
||||
headcount: 2,
|
||||
dailyCostCents: 0,
|
||||
status: AllocationStatus.PROPOSED,
|
||||
metadata: {},
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
},
|
||||
]),
|
||||
},
|
||||
demandRequirement: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "demand_1",
|
||||
projectId: "project_1",
|
||||
startDate: new Date("2026-03-17"),
|
||||
endDate: new Date("2026-03-18"),
|
||||
hoursPerDay: 8,
|
||||
percentage: 100,
|
||||
role: "FX",
|
||||
roleId: "role_fx",
|
||||
headcount: 2,
|
||||
status: AllocationStatus.PROPOSED,
|
||||
metadata: {},
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
},
|
||||
]),
|
||||
},
|
||||
assignment: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "assignment_1",
|
||||
demandRequirementId: null,
|
||||
resourceId: "resource_1",
|
||||
projectId: "project_1",
|
||||
startDate: new Date("2026-03-19"),
|
||||
endDate: new Date("2026-03-20"),
|
||||
hoursPerDay: 8,
|
||||
percentage: 100,
|
||||
role: "FX Lead",
|
||||
roleId: "role_fx",
|
||||
dailyCostCents: 32000,
|
||||
status: AllocationStatus.ACTIVE,
|
||||
metadata: {},
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
},
|
||||
]),
|
||||
},
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
const result = await caller.list({});
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]?._count.resourceRoles).toBe(2);
|
||||
expect(result[0]?._count.allocations).toBe(2);
|
||||
});
|
||||
|
||||
it("blocks deleting a role that is only used by explicit demand or assignment rows", async () => {
|
||||
const db = {
|
||||
role: {
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
id: "role_fx",
|
||||
name: "FX",
|
||||
description: null,
|
||||
color: "#111111",
|
||||
isActive: true,
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
_count: { resourceRoles: 0 },
|
||||
}),
|
||||
delete: vi.fn(),
|
||||
},
|
||||
allocation: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
demandRequirement: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "demand_1",
|
||||
projectId: "project_1",
|
||||
startDate: new Date("2026-03-17"),
|
||||
endDate: new Date("2026-03-18"),
|
||||
hoursPerDay: 8,
|
||||
percentage: 100,
|
||||
role: "FX",
|
||||
roleId: "role_fx",
|
||||
headcount: 1,
|
||||
status: AllocationStatus.PROPOSED,
|
||||
metadata: {},
|
||||
createdAt: new Date("2026-03-13"),
|
||||
updatedAt: new Date("2026-03-13"),
|
||||
},
|
||||
]),
|
||||
},
|
||||
assignment: {
|
||||
findMany: vi.fn().mockResolvedValue([]),
|
||||
},
|
||||
};
|
||||
|
||||
const caller = createManagerCaller(db);
|
||||
|
||||
await expect(caller.delete({ id: "role_fx" })).rejects.toMatchObject({
|
||||
code: "PRECONDITION_FAILED",
|
||||
} satisfies Partial<TRPCError>);
|
||||
|
||||
expect(db.role.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user