feat(api): expose peak times explainability

This commit is contained in:
2026-03-31 23:25:36 +02:00
parent fc12a5739e
commit a8fcc4dacb
4 changed files with 108 additions and 2 deletions
@@ -64,6 +64,7 @@ describe("assistant dashboard tools detail aggregation", () => {
calendarContextCount: 1, calendarContextCount: 1,
resourceCount: 4, resourceCount: 4,
groupCount: 1, groupCount: 1,
baseAvailableHours: 416.2,
calendarLocations: [ calendarLocations: [
{ {
countryCode: "DE", countryCode: "DE",
@@ -79,6 +80,10 @@ describe("assistant dashboard tools detail aggregation", () => {
remainingCapacityHours: 79.8, remainingCapacityHours: 79.8,
overbookedHours: 0, overbookedHours: 0,
utilizationPct: 80, utilizationPct: 80,
effectiveAvailableHours: 400.2,
publicHolidayHoursDeduction: 16,
absenceDayEquivalent: 1.5,
absenceHoursDeduction: 12.5,
}, },
}, },
]); ]);
@@ -190,6 +195,19 @@ describe("assistant dashboard tools detail aggregation", () => {
effectiveAvailableHours: 400.2, effectiveAvailableHours: 400.2,
}, },
], ],
explainability: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
resourceCount: 4,
groupCount: 1,
baseAvailableHours: 416.2,
effectiveAvailableHours: 400.2,
publicHolidayHoursDeduction: 16,
absenceDayEquivalent: 1.5,
absenceHoursDeduction: 12.5,
remainingCapacityHours: 79.8,
overbookedHours: 0,
},
}, },
], ],
topResources: [ topResources: [
@@ -167,8 +167,19 @@ describe("dashboard procedure support", () => {
capacityHours: 200.12, capacityHours: 200.12,
utilizationPct: 80, utilizationPct: 80,
derivation: { derivation: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
calendarContextCount: 1, calendarContextCount: 1,
resourceCount: 5,
groupCount: 2,
baseAvailableHours: 216,
effectiveAvailableHours: 200.12,
publicHolidayHoursDeduction: 8,
absenceDayEquivalent: 1,
absenceHoursDeduction: 7.88,
calendarLocations: [{ countryCode: "DE", federalState: "BY", metroCityName: "Munich" }], calendarLocations: [{ countryCode: "DE", federalState: "BY", metroCityName: "Munich" }],
remainingCapacityHours: 39.78,
overbookedHours: 0,
}, },
}, },
]); ]);
@@ -228,6 +239,19 @@ describe("dashboard procedure support", () => {
utilizationPct: 80, utilizationPct: 80,
calendarContextCount: 1, calendarContextCount: 1,
calendarLocations: [{ countryCode: "DE", federalState: "BY", metroCityName: "Munich" }], calendarLocations: [{ countryCode: "DE", federalState: "BY", metroCityName: "Munich" }],
explainability: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
resourceCount: 5,
groupCount: 2,
baseAvailableHours: 216,
effectiveAvailableHours: 200.12,
publicHolidayHoursDeduction: 8,
absenceDayEquivalent: 1,
absenceHoursDeduction: 7.88,
remainingCapacityHours: 39.78,
overbookedHours: 0,
},
}, },
], ],
topResources: [ topResources: [
@@ -757,6 +757,33 @@ describe("dashboard router", () => {
totalHours: 320.4, totalHours: 320.4,
capacityHours: 400.2, capacityHours: 400.2,
utilizationPct: 80, utilizationPct: 80,
derivation: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
calendarContextCount: 1,
resourceCount: 4,
groupCount: 1,
baseAvailableHours: 416.2,
effectiveAvailableHours: 400.2,
publicHolidayHoursDeduction: 16,
absenceDayEquivalent: 1.5,
absenceHoursDeduction: 12.5,
calendarLocations: [
{
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Augsburg",
resourceCount: 4,
effectiveAvailableHours: 400.2,
},
],
bookedHours: 320.4,
capacityHours: 400.2,
remainingCapacityHours: 79.8,
overbookedHours: 0,
utilizationPct: 80,
},
}, },
]); ]);
vi.mocked(getDashboardTopValueResources).mockResolvedValue([ vi.mocked(getDashboardTopValueResources).mockResolvedValue([
@@ -823,8 +850,30 @@ describe("dashboard router", () => {
totalHoursPerDay: 320.4, totalHoursPerDay: 320.4,
capacityHours: 400.2, capacityHours: 400.2,
utilizationPct: 80, utilizationPct: 80,
calendarContextCount: 0, calendarContextCount: 1,
calendarLocations: [], calendarLocations: [
{
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Augsburg",
resourceCount: 4,
effectiveAvailableHours: 400.2,
},
],
explainability: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
resourceCount: 4,
groupCount: 1,
baseAvailableHours: 416.2,
effectiveAvailableHours: 400.2,
publicHolidayHoursDeduction: 16,
absenceDayEquivalent: 1.5,
absenceHoursDeduction: 12.5,
remainingCapacityHours: 79.8,
overbookedHours: 0,
},
}, },
], ],
topResources: [ topResources: [
@@ -242,6 +242,21 @@ export async function getDashboardDetail(ctx: DashboardProcedureContext, input:
utilizationPct: entry.utilizationPct ?? null, utilizationPct: entry.utilizationPct ?? null,
calendarContextCount: entry.derivation?.calendarContextCount ?? 0, calendarContextCount: entry.derivation?.calendarContextCount ?? 0,
calendarLocations: entry.derivation?.calendarLocations ?? [], calendarLocations: entry.derivation?.calendarLocations ?? [],
explainability: entry.derivation
? {
periodStart: entry.derivation.periodStart,
periodEnd: entry.derivation.periodEnd,
resourceCount: entry.derivation.resourceCount,
groupCount: entry.derivation.groupCount,
baseAvailableHours: entry.derivation.baseAvailableHours,
effectiveAvailableHours: entry.derivation.effectiveAvailableHours,
publicHolidayHoursDeduction: entry.derivation.publicHolidayHoursDeduction,
absenceDayEquivalent: entry.derivation.absenceDayEquivalent,
absenceHoursDeduction: entry.derivation.absenceHoursDeduction,
remainingCapacityHours: entry.derivation.remainingCapacityHours,
overbookedHours: entry.derivation.overbookedHours,
}
: null,
})); }));
} }