feat(platform): harden access scoping and delivery baseline
This commit is contained in:
@@ -1,15 +1,23 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { inferProcedureInput } from "@trpc/server";
|
||||
import type { AppRouter } from "../router/index.js";
|
||||
import { SystemRole } from "@capakraken/shared";
|
||||
import { rateCardRouter } from "../router/rate-card.js";
|
||||
import { createCallerFactory } from "../trpc.js";
|
||||
|
||||
// Minimal mock helpers
|
||||
function mockCtx(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
ctx: {
|
||||
session: { user: { id: "user_1", systemRole: "MANAGER" } },
|
||||
db: overrides,
|
||||
const createCaller = createCallerFactory(rateCardRouter);
|
||||
|
||||
function createControllerCaller(db: Record<string, unknown>) {
|
||||
return createCaller({
|
||||
session: {
|
||||
user: { email: "controller@example.com", name: "Controller", image: null },
|
||||
expires: "2099-01-01T00:00:00.000Z",
|
||||
},
|
||||
};
|
||||
db: db as never,
|
||||
dbUser: {
|
||||
id: "user_1",
|
||||
systemRole: SystemRole.CONTROLLER,
|
||||
permissionOverrides: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe("rateCard router", () => {
|
||||
@@ -60,6 +68,52 @@ describe("rateCard router", () => {
|
||||
});
|
||||
|
||||
describe("resolveRate", () => {
|
||||
it("resolves a resource-based rate through the canonical router query", async () => {
|
||||
const db = {
|
||||
resource: {
|
||||
findUnique: vi.fn().mockResolvedValue({
|
||||
id: "res_1",
|
||||
displayName: "Bruce Banner",
|
||||
chapter: "Delivery",
|
||||
areaRole: { name: "Pipeline TD" },
|
||||
}),
|
||||
},
|
||||
role: {
|
||||
findFirst: vi.fn().mockResolvedValue({ id: "role_1" }),
|
||||
},
|
||||
rateCard: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "rc_2026",
|
||||
name: "Standard 2026",
|
||||
client: null,
|
||||
lines: [
|
||||
{
|
||||
id: "line_1",
|
||||
chapter: "Delivery",
|
||||
seniority: "Senior",
|
||||
costRateCents: 12_000,
|
||||
billRateCents: 18_000,
|
||||
role: { id: "role_1", name: "Pipeline TD" },
|
||||
},
|
||||
],
|
||||
},
|
||||
]),
|
||||
},
|
||||
};
|
||||
|
||||
const caller = createControllerCaller(db);
|
||||
const result = await caller.resolveBestRate({ resourceId: "res_1" });
|
||||
|
||||
expect(result).toEqual({
|
||||
rateCard: "Standard 2026",
|
||||
resource: "Bruce Banner",
|
||||
rate: "120,00 EUR",
|
||||
rateCents: 12000,
|
||||
matchedBy: "role: Pipeline TD",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns the most specific matching line", () => {
|
||||
const lines = [
|
||||
{ id: "rcl_1", roleId: null, chapter: "Digital Content Production", costRateCents: 7000, billRateCents: 12000 },
|
||||
|
||||
Reference in New Issue
Block a user