From fc12a5739ece49432e88f2cd8fcf5b5236c8d119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Tue, 31 Mar 2026 23:24:14 +0200 Subject: [PATCH] feat(api): expose demand pipeline explainability --- .../assistant-tools-dashboard-detail.test.ts | 9 +++++++++ .../dashboard-procedure-support.test.ts | 20 ++++++++++++++++++- .../src/__tests__/dashboard-router.test.ts | 18 +++++++++++++++++ .../src/router/dashboard-procedure-support.ts | 11 ++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/packages/api/src/__tests__/assistant-tools-dashboard-detail.test.ts b/packages/api/src/__tests__/assistant-tools-dashboard-detail.test.ts index 91ddf1b..db0a789 100644 --- a/packages/api/src/__tests__/assistant-tools-dashboard-detail.test.ts +++ b/packages/api/src/__tests__/assistant-tools-dashboard-detail.test.ts @@ -231,6 +231,15 @@ describe("assistant dashboard tools detail aggregation", () => { allocatedHours: 120, }, ], + explainability: { + periodStart: "2026-01-01", + periodEnd: "2026-06-30", + periodWorkingHoursBase: 1040, + requiredHours: 2080, + fillPct: 50, + demandSource: "DEMAND_REQUIREMENTS", + calendarContextCount: 1, + }, }, ], chargeabilityByChapter: [ diff --git a/packages/api/src/__tests__/dashboard-procedure-support.test.ts b/packages/api/src/__tests__/dashboard-procedure-support.test.ts index c1198cd..985d567 100644 --- a/packages/api/src/__tests__/dashboard-procedure-support.test.ts +++ b/packages/api/src/__tests__/dashboard-procedure-support.test.ts @@ -202,7 +202,16 @@ describe("dashboard procedure support", () => { requiredFTEs: 3, resourceCount: 1, allocatedHours: 80, - derivation: { calendarLocations: [{ countryCode: "DE", countryName: "Germany" }] }, + derivation: { + periodStart: "2026-03-01", + periodEnd: "2026-06-30", + periodWorkingHoursBase: 672, + requiredHours: 2016, + requiredFTEs: 3, + fillPct: 40, + demandSource: "DEMAND_REQUIREMENTS", + calendarLocations: [{ countryCode: "DE", countryName: "Germany" }], + }, }, ]); @@ -251,6 +260,15 @@ describe("dashboard procedure support", () => { allocatedResources: 1, allocatedHours: 80, calendarLocations: [{ countryCode: "DE", countryName: "Germany" }], + explainability: { + periodStart: "2026-03-01", + periodEnd: "2026-06-30", + periodWorkingHoursBase: 672, + requiredHours: 2016, + fillPct: 40, + demandSource: "DEMAND_REQUIREMENTS", + calendarContextCount: 1, + }, }, ], chargeabilityByChapter: [ diff --git a/packages/api/src/__tests__/dashboard-router.test.ts b/packages/api/src/__tests__/dashboard-router.test.ts index c7f5676..9c96a05 100644 --- a/packages/api/src/__tests__/dashboard-router.test.ts +++ b/packages/api/src/__tests__/dashboard-router.test.ts @@ -791,9 +791,17 @@ describe("dashboard router", () => { requiredFTEs: 4, resourceCount: 2, derivation: { + periodStart: "2026-01-01", + periodEnd: "2026-06-30", + periodWorkingHoursBase: 1040, + requiredHours: 2080, + requiredFTEs: 4, + fillPct: 50, + demandSource: "DEMAND_REQUIREMENTS", calendarLocations: [ { countryCode: "DE", + countryName: "Germany", federalState: "BY", metroCityName: "Augsburg", resourceCount: 2, @@ -851,12 +859,22 @@ describe("dashboard router", () => { calendarLocations: [ { countryCode: "DE", + countryName: "Germany", federalState: "BY", metroCityName: "Augsburg", resourceCount: 2, allocatedHours: 120, }, ], + explainability: { + periodStart: "2026-01-01", + periodEnd: "2026-06-30", + periodWorkingHoursBase: 1040, + requiredHours: 2080, + fillPct: 50, + demandSource: "DEMAND_REQUIREMENTS", + calendarContextCount: 1, + }, }, ], chargeabilityByChapter: [ diff --git a/packages/api/src/router/dashboard-procedure-support.ts b/packages/api/src/router/dashboard-procedure-support.ts index 4eb9498..e5576c8 100644 --- a/packages/api/src/router/dashboard-procedure-support.ts +++ b/packages/api/src/router/dashboard-procedure-support.ts @@ -276,6 +276,17 @@ export async function getDashboardDetail(ctx: DashboardProcedureContext, input: allocatedResources: row.resourceCount, allocatedHours: row.allocatedHours, calendarLocations: row.derivation?.calendarLocations ?? [], + explainability: row.derivation + ? { + periodStart: row.derivation.periodStart, + periodEnd: row.derivation.periodEnd, + periodWorkingHoursBase: row.derivation.periodWorkingHoursBase, + requiredHours: row.derivation.requiredHours, + fillPct: row.derivation.fillPct, + demandSource: row.derivation.demandSource, + calendarContextCount: row.derivation.calendarLocations.length, + } + : null, })) .filter((row) => row.needed > 0) .sort((left, right) => right.needed - left.needed)