refactor(api): split dashboard detail shaping

This commit is contained in:
2026-03-31 22:26:52 +02:00
parent a9028290f2
commit 46d00c2635
3 changed files with 373 additions and 113 deletions
@@ -290,6 +290,40 @@ describe("dashboard router", () => {
staffingHealth: 40,
timelineHealth: 30,
compositeScore: 35,
budgetCents: 100_000,
spentCents: 82_000,
remainingBudgetCents: 18_000,
budgetUtilizationPercent: 82,
demandHeadcountTotal: 5,
demandHeadcountFilled: 2,
demandHeadcountOpen: 3,
demandRequirementCount: 2,
plannedEndDate: new Date("2026-06-30T00:00:00.000Z"),
daysUntilEndDate: 12,
timelineStatus: "DUE_SOON",
calendarLocations: [
{
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Munich",
assignmentCount: 2,
spentCents: 52_000,
},
],
derivation: {
periodStart: "2026-06-01",
periodEnd: "2026-06-30",
calendarContextCount: 1,
holidayAwareAssignmentCount: 2,
fallbackAssignmentCount: 0,
baseSpentCents: 90_000,
adjustedSpentCents: 82_000,
publicHolidayDayEquivalent: 1,
publicHolidayCostDeductionCents: 5_000,
absenceDayEquivalent: 0.6,
absenceCostDeductionCents: 3_000,
},
},
{
id: "project_healthy",
@@ -302,6 +336,18 @@ describe("dashboard router", () => {
staffingHealth: 92,
timelineHealth: 86,
compositeScore: 89,
budgetCents: 200_000,
spentCents: 20_000,
remainingBudgetCents: 180_000,
budgetUtilizationPercent: 10,
demandHeadcountTotal: 4,
demandHeadcountFilled: 4,
demandHeadcountOpen: 0,
demandRequirementCount: 1,
plannedEndDate: new Date("2026-09-15T00:00:00.000Z"),
daysUntilEndDate: 89,
timelineStatus: "ON_TRACK",
calendarLocations: [],
},
]);
@@ -321,6 +367,50 @@ describe("dashboard router", () => {
staffing: 40,
timeline: 30,
rating: "critical",
budgetBasis: {
budgetCents: 100_000,
spentCents: 82_000,
remainingBudgetCents: 18_000,
budgetUtilizationPercent: 82,
calendarLocations: [
{
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Munich",
assignmentCount: 2,
spentCents: 52_000,
},
],
derivation: {
periodStart: "2026-06-01",
periodEnd: "2026-06-30",
calendarContextCount: 1,
holidayAwareAssignmentCount: 2,
fallbackAssignmentCount: 0,
baseSpentCents: 90_000,
adjustedSpentCents: 82_000,
publicHolidayDayEquivalent: 1,
publicHolidayCostDeductionCents: 5_000,
absenceDayEquivalent: 0.6,
absenceCostDeductionCents: 3_000,
},
},
staffingBasis: {
demandHeadcountTotal: 5,
demandHeadcountFilled: 2,
demandHeadcountOpen: 3,
demandRequirementCount: 2,
},
timelineBasis: {
plannedEndDate: "2026-06-30T00:00:00.000Z",
daysUntilEndDate: 12,
timelineStatus: "DUE_SOON",
},
context: {
clientId: "client_1",
clientName: "Acme",
},
},
{
projectId: "project_healthy",
@@ -332,6 +422,29 @@ describe("dashboard router", () => {
staffing: 92,
timeline: 86,
rating: "healthy",
budgetBasis: {
budgetCents: 200_000,
spentCents: 20_000,
remainingBudgetCents: 180_000,
budgetUtilizationPercent: 10,
calendarLocations: [],
derivation: null,
},
staffingBasis: {
demandHeadcountTotal: 4,
demandHeadcountFilled: 4,
demandHeadcountOpen: 0,
demandRequirementCount: 1,
},
timelineBasis: {
plannedEndDate: "2026-09-15T00:00:00.000Z",
daysUntilEndDate: 89,
timelineStatus: "ON_TRACK",
},
context: {
clientId: "client_1",
clientName: "Acme",
},
},
],
summary: {
@@ -476,6 +589,19 @@ describe("dashboard router", () => {
estimatedExhaustionDate: "2026-06-30",
pctUsed: 40,
activeAssignmentCount: 2,
derivation: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
calendarContextCount: 1,
holidayAwareAssignmentCount: 2,
fallbackAssignmentCount: 0,
baseBurnRateCents: 12_000,
adjustedBurnRateCents: 10_000,
publicHolidayDayEquivalent: 1,
publicHolidayCostDeductionCents: 1_000,
absenceDayEquivalent: 0.5,
absenceCostDeductionCents: 1_000,
},
calendarLocations: [
{
countryCode: "DE",
@@ -496,6 +622,11 @@ describe("dashboard router", () => {
expect(result[0]).toMatchObject({
projectName: "Alpha",
activeAssignmentCount: 2,
derivation: {
holidayAwareAssignmentCount: 2,
baseBurnRateCents: 12_000,
adjustedBurnRateCents: 10_000,
},
calendarLocations: [
expect.objectContaining({
countryCode: "DE",
@@ -522,6 +653,19 @@ describe("dashboard router", () => {
estimatedExhaustionDate: "2026-06-30",
pctUsed: 40,
activeAssignmentCount: 2,
derivation: {
periodStart: "2026-03-01",
periodEnd: "2026-03-31",
calendarContextCount: 1,
holidayAwareAssignmentCount: 2,
fallbackAssignmentCount: 0,
baseBurnRateCents: 12_000,
adjustedBurnRateCents: 10_000,
publicHolidayDayEquivalent: 1,
publicHolidayCostDeductionCents: 1_000,
absenceDayEquivalent: 0.5,
absenceCostDeductionCents: 1_000,
},
calendarLocations: [
{
countryCode: "DE",
@@ -551,6 +695,13 @@ describe("dashboard router", () => {
projectedCents: 100_000,
burnRateCents: 10_000,
utilization: "40%",
derivation: expect.objectContaining({
holidayAwareAssignmentCount: 2,
baseBurnRateCents: 12_000,
adjustedBurnRateCents: 10_000,
publicHolidayCostDeductionCents: 1_000,
absenceCostDeductionCents: 1_000,
}),
burnStatus: "on_track",
calendarLocations: [
expect.objectContaining({
@@ -597,6 +748,7 @@ describe("dashboard router", () => {
valueScore: 91,
lcrCents: 9_500,
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Augsburg",
},
@@ -644,6 +796,7 @@ describe("dashboard router", () => {
lcr: "95,00 EUR",
valueScore: 91,
countryCode: "DE",
countryName: "Germany",
federalState: "BY",
metroCityName: "Augsburg",
},