feat(api): include skill gaps in dashboard detail

This commit is contained in:
2026-03-31 23:46:07 +02:00
parent 2de5a0eede
commit f2d511ebc8
5 changed files with 115 additions and 2 deletions
@@ -9,6 +9,7 @@ import {
getDashboardOverview,
getDashboardPeakTimes,
getDashboardProjectHealth,
getDashboardSkillGapSummary,
getDashboardTopValueResources,
} from "./assistant-tools-dashboard-test-helpers.js";
@@ -209,6 +210,21 @@ describe("assistant dashboard tools detail aggregation", () => {
},
},
]);
vi.mocked(getDashboardSkillGapSummary).mockResolvedValue({
roleGaps: [
{ role: "Pipeline TD", needed: 4, filled: 1, gap: 3, fillRate: 25 },
{ role: "Lighting TD", needed: 2, filled: 1, gap: 1, fillRate: 50 },
],
totalOpenPositions: 4,
skillSupplyTop10: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
});
const ctx = createToolContext(
{
@@ -384,6 +400,21 @@ describe("assistant dashboard tools detail aggregation", () => {
},
},
],
skillGaps: {
totalOpenPositions: 4,
roleGaps: [
{ role: "Pipeline TD", gap: 3, needed: 4, filled: 1, fillRate: 25 },
{ role: "Lighting TD", gap: 1, needed: 2, filled: 1, fillRate: 50 },
],
topSkillsInSupply: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
},
});
});
});
@@ -34,6 +34,7 @@ import {
getDashboardOverview,
getDashboardPeakTimes,
getDashboardProjectHealth,
getDashboardSkillGapSummary,
getDashboardTopValueResources,
} from "@capakraken/application";
import { cacheGet } from "../lib/cache.js";
@@ -293,6 +294,21 @@ describe("dashboard procedure support", () => {
},
},
]);
vi.mocked(getDashboardSkillGapSummary).mockResolvedValue({
roleGaps: [
{ role: "Pipeline TD", needed: 4, filled: 1, gap: 3, fillRate: 25 },
{ role: "Lighting TD", needed: 2, filled: 1, gap: 1, fillRate: 50 },
],
totalOpenPositions: 4,
skillSupplyTop10: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
});
try {
const result = await getDashboardDetail(createContext(), { section: "all" });
@@ -417,6 +433,21 @@ describe("dashboard procedure support", () => {
},
},
],
skillGaps: {
totalOpenPositions: 4,
roleGaps: [
{ role: "Pipeline TD", gap: 3, needed: 4, filled: 1, fillRate: 25 },
{ role: "Lighting TD", gap: 1, needed: 2, filled: 1, fillRate: 50 },
],
topSkillsInSupply: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
},
});
expect(getDashboardChargeabilityOverview).toHaveBeenCalledWith(
@@ -11,6 +11,7 @@ vi.mock("@capakraken/application", async (importOriginal) => {
getDashboardTopValueResources: vi.fn(),
getDashboardChargeabilityOverview: vi.fn(),
getDashboardBudgetForecast: vi.fn(),
getDashboardSkillGapSummary: vi.fn(),
getDashboardProjectHealth: vi.fn(),
};
});
@@ -33,6 +34,7 @@ import {
getDashboardChargeabilityOverview,
getDashboardBudgetForecast,
getDashboardProjectHealth,
getDashboardSkillGapSummary,
} from "@capakraken/application";
import { dashboardRouter } from "../router/dashboard.js";
import { createCallerFactory } from "../trpc.js";
@@ -786,6 +788,21 @@ describe("dashboard router", () => {
},
},
]);
vi.mocked(getDashboardSkillGapSummary).mockResolvedValue({
roleGaps: [
{ role: "Pipeline TD", needed: 4, filled: 1, gap: 3, fillRate: 25 },
{ role: "Lighting TD", needed: 2, filled: 1, gap: 1, fillRate: 50 },
],
totalOpenPositions: 4,
skillSupplyTop10: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
});
vi.mocked(getDashboardTopValueResources).mockResolvedValue([
{
id: "res_1",
@@ -1048,6 +1065,21 @@ describe("dashboard router", () => {
},
},
],
skillGaps: {
totalOpenPositions: 4,
roleGaps: [
{ role: "Pipeline TD", gap: 3, needed: 4, filled: 1, fillRate: 25 },
{ role: "Lighting TD", gap: 1, needed: 2, filled: 1, fillRate: 50 },
],
topSkillsInSupply: [
{ skill: "houdini", resourceCount: 5 },
{ skill: "nuke", resourceCount: 4 },
],
resourcesByRole: [
{ role: "Compositor", count: 6 },
{ role: "Pipeline TD", count: 2 },
],
},
});
expect(getDashboardPeakTimes).toHaveBeenCalledWith(
expect.anything(),
@@ -1066,6 +1098,7 @@ describe("dashboard router", () => {
watchlistThreshold: 15,
}),
);
expect(getDashboardSkillGapSummary).toHaveBeenCalledWith(expect.anything());
expect(getDashboardProjectHealth).toHaveBeenCalledTimes(1);
});
});