b41c1d2501
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61) Co-authored-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com> Co-committed-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com>
178 lines
5.4 KiB
TypeScript
178 lines
5.4 KiB
TypeScript
import { AllocationStatus } from "@nexus/shared";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { updateAllocationEntry } from "../index.js";
|
|
|
|
describe("allocation entry resolution helpers", () => {
|
|
it("updates an explicit demand requirement", async () => {
|
|
const existingDemand = {
|
|
id: "demand_1",
|
|
projectId: "project_1",
|
|
startDate: new Date("2026-03-16"),
|
|
endDate: new Date("2026-03-20"),
|
|
hoursPerDay: 4,
|
|
percentage: 50,
|
|
role: "FX Artist",
|
|
roleId: "role_fx",
|
|
headcount: 1,
|
|
status: AllocationStatus.PROPOSED,
|
|
metadata: {},
|
|
createdAt: new Date("2026-03-13"),
|
|
updatedAt: new Date("2026-03-13"),
|
|
project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
|
|
roleEntity: { id: "role_fx", name: "FX Artist", color: "#222222" },
|
|
};
|
|
const updatedDemand = {
|
|
...existingDemand,
|
|
headcount: 2,
|
|
status: AllocationStatus.CONFIRMED,
|
|
metadata: { source: "entry-test" },
|
|
updatedAt: new Date("2026-03-14"),
|
|
};
|
|
|
|
const demandRequirementFindUnique = vi.fn().mockResolvedValue(existingDemand);
|
|
const demandRequirementUpdate = vi.fn().mockResolvedValue(updatedDemand);
|
|
const assignmentFindUnique = vi.fn().mockResolvedValue(null);
|
|
const assignmentUpdate = vi.fn();
|
|
const auditLogCreate = vi.fn().mockResolvedValue({});
|
|
|
|
const result = await updateAllocationEntry(
|
|
{
|
|
demandRequirement: {
|
|
findUnique: demandRequirementFindUnique,
|
|
update: demandRequirementUpdate,
|
|
},
|
|
assignment: {
|
|
findUnique: assignmentFindUnique,
|
|
update: assignmentUpdate,
|
|
},
|
|
auditLog: { create: auditLogCreate },
|
|
} as never,
|
|
{
|
|
id: "demand_1",
|
|
demandRequirementUpdate: {
|
|
headcount: 2,
|
|
status: AllocationStatus.CONFIRMED,
|
|
metadata: { source: "entry-test" },
|
|
},
|
|
assignmentUpdate: {},
|
|
},
|
|
);
|
|
|
|
expect(result.strategy).toBe("explicit_demand");
|
|
expect(result.allocation.id).toBe("demand_1");
|
|
expect(result.allocation.isPlaceholder).toBe(true);
|
|
expect(result.allocation.headcount).toBe(2);
|
|
expect(demandRequirementUpdate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
where: { id: "demand_1" },
|
|
data: expect.objectContaining({
|
|
headcount: 2,
|
|
status: AllocationStatus.CONFIRMED,
|
|
}),
|
|
}),
|
|
);
|
|
expect(assignmentUpdate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("updates an explicit assignment", async () => {
|
|
const existingAssignment = {
|
|
id: "assignment_1",
|
|
demandRequirementId: null,
|
|
resourceId: "resource_1",
|
|
projectId: "project_1",
|
|
startDate: new Date("2026-03-16"),
|
|
endDate: new Date("2026-03-20"),
|
|
hoursPerDay: 4,
|
|
percentage: 50,
|
|
role: "Compositor",
|
|
roleId: "role_comp",
|
|
dailyCostCents: 20000,
|
|
status: AllocationStatus.PROPOSED,
|
|
metadata: {},
|
|
createdAt: new Date("2026-03-13"),
|
|
updatedAt: new Date("2026-03-13"),
|
|
resource: {
|
|
id: "resource_1",
|
|
displayName: "Alice",
|
|
eid: "E-001",
|
|
lcrCents: 5000,
|
|
},
|
|
project: { id: "project_1", name: "Project One", shortCode: "PRJ" },
|
|
roleEntity: { id: "role_comp", name: "Compositor", color: "#111111" },
|
|
demandRequirement: null,
|
|
};
|
|
const updatedAssignment = {
|
|
...existingAssignment,
|
|
hoursPerDay: 6,
|
|
percentage: 75,
|
|
dailyCostCents: 30000,
|
|
status: AllocationStatus.ACTIVE,
|
|
updatedAt: new Date("2026-03-14"),
|
|
};
|
|
|
|
const demandRequirementFindUnique = vi.fn().mockResolvedValue(null);
|
|
const assignmentFindUnique = vi.fn().mockResolvedValue(existingAssignment);
|
|
const assignmentUpdate = vi.fn().mockResolvedValue(updatedAssignment);
|
|
const auditLogCreate = vi.fn().mockResolvedValue({});
|
|
|
|
const result = await updateAllocationEntry(
|
|
{
|
|
demandRequirement: {
|
|
findUnique: demandRequirementFindUnique,
|
|
},
|
|
assignment: {
|
|
findUnique: assignmentFindUnique,
|
|
update: assignmentUpdate,
|
|
},
|
|
auditLog: { create: auditLogCreate },
|
|
} as never,
|
|
{
|
|
id: "assignment_1",
|
|
demandRequirementUpdate: {},
|
|
assignmentUpdate: {
|
|
hoursPerDay: 6,
|
|
percentage: 75,
|
|
dailyCostCents: 30000,
|
|
status: AllocationStatus.ACTIVE,
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(result.strategy).toBe("explicit_assignment");
|
|
expect(result.allocation.id).toBe("assignment_1");
|
|
expect(assignmentUpdate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
where: { id: "assignment_1" },
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("throws NOT_FOUND when the id does not match any demand or assignment", async () => {
|
|
const demandRequirementFindUnique = vi.fn().mockResolvedValue(null);
|
|
const assignmentFindUnique = vi.fn().mockResolvedValue(null);
|
|
|
|
await expect(
|
|
updateAllocationEntry(
|
|
{
|
|
demandRequirement: {
|
|
findUnique: demandRequirementFindUnique,
|
|
},
|
|
assignment: {
|
|
findUnique: assignmentFindUnique,
|
|
},
|
|
} as never,
|
|
{
|
|
id: "nonexistent_id",
|
|
demandRequirementUpdate: {
|
|
status: AllocationStatus.CONFIRMED,
|
|
},
|
|
assignmentUpdate: {},
|
|
},
|
|
),
|
|
).rejects.toMatchObject({
|
|
code: "NOT_FOUND",
|
|
message: "Allocation not found",
|
|
});
|
|
});
|
|
});
|