fix(dashboard): stabilize budget forecast derivation typing
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
type BudgetForecastRow,
|
||||
getDashboardBudgetForecast,
|
||||
getDashboardChargeabilityOverview,
|
||||
getDashboardDemand,
|
||||
@@ -66,6 +67,55 @@ type DashboardDemandInput = z.infer<typeof dashboardDemandInputSchema>;
|
||||
type DashboardDetailInput = z.infer<typeof dashboardDetailInputSchema>;
|
||||
type DashboardChargeabilityOverviewInput = z.infer<typeof dashboardChargeabilityOverviewInputSchema>;
|
||||
|
||||
type DashboardBudgetForecastCalendarLocation = {
|
||||
countryCode: string | null;
|
||||
countryName: string | null;
|
||||
federalState: string | null;
|
||||
metroCityName: string | null;
|
||||
activeAssignmentCount: number;
|
||||
burnRateCents: number;
|
||||
};
|
||||
|
||||
type DashboardBudgetForecastDerivation = {
|
||||
periodStart: string;
|
||||
periodEnd: string;
|
||||
calendarContextCount: number;
|
||||
holidayAwareAssignmentCount: number;
|
||||
fallbackAssignmentCount: number;
|
||||
baseBurnRateCents: number;
|
||||
adjustedBurnRateCents: number;
|
||||
publicHolidayDayEquivalent: number;
|
||||
publicHolidayCostDeductionCents: number;
|
||||
absenceDayEquivalent: number;
|
||||
absenceCostDeductionCents: number;
|
||||
};
|
||||
|
||||
type DashboardBudgetForecastDetail = {
|
||||
forecasts: Array<{
|
||||
projectId: string | null;
|
||||
projectName: string;
|
||||
shortCode: string;
|
||||
clientId: string | null;
|
||||
clientName: string | null;
|
||||
budget: string;
|
||||
budgetCents: number;
|
||||
spent: string;
|
||||
spentCents: number;
|
||||
remaining: string;
|
||||
remainingCents: number;
|
||||
projected: string;
|
||||
projectedCents: number;
|
||||
burnRate: string;
|
||||
burnRateCents: number;
|
||||
utilization: string;
|
||||
estimatedExhaustionDate: string | null;
|
||||
activeAssignmentCount: number | null;
|
||||
calendarLocations: DashboardBudgetForecastCalendarLocation[];
|
||||
derivation: DashboardBudgetForecastDerivation | null;
|
||||
burnStatus: "ahead" | "on_track" | "not_started";
|
||||
}>;
|
||||
};
|
||||
|
||||
function round1(value: number): number {
|
||||
return Math.round(value * 10) / 10;
|
||||
}
|
||||
@@ -98,7 +148,7 @@ function mapProjectHealthDetailRows(rows: Awaited<ReturnType<typeof getDashboard
|
||||
};
|
||||
}
|
||||
|
||||
function mapBudgetForecastDetailRows(rows: Awaited<ReturnType<typeof getDashboardBudgetForecast>>) {
|
||||
function mapBudgetForecastDetailRows(rows: BudgetForecastRow[]): DashboardBudgetForecastDetail {
|
||||
return {
|
||||
forecasts: rows.map((forecast) => ({
|
||||
projectId: forecast.projectId ?? null,
|
||||
@@ -124,6 +174,7 @@ function mapBudgetForecastDetailRows(rows: Awaited<ReturnType<typeof getDashboar
|
||||
estimatedExhaustionDate: forecast.estimatedExhaustionDate,
|
||||
activeAssignmentCount: forecast.activeAssignmentCount ?? null,
|
||||
calendarLocations: forecast.calendarLocations ?? [],
|
||||
derivation: forecast.derivation ?? null,
|
||||
burnStatus: forecast.pctUsed >= 100
|
||||
? "ahead"
|
||||
: forecast.burnRate > 0
|
||||
@@ -374,9 +425,11 @@ export async function getDashboardChargeabilityOverviewRead(
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getDashboardBudgetForecastRead(ctx: DashboardProcedureContext) {
|
||||
export async function getDashboardBudgetForecastRead(
|
||||
ctx: DashboardProcedureContext,
|
||||
): Promise<BudgetForecastRow[]> {
|
||||
const cacheKey = "budgetForecast";
|
||||
const cached = await cacheGet<Awaited<ReturnType<typeof getDashboardBudgetForecast>>>(cacheKey);
|
||||
const cached = await cacheGet<BudgetForecastRow[]>(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
const result = await getDashboardBudgetForecast(ctx.db);
|
||||
@@ -384,8 +437,10 @@ export async function getDashboardBudgetForecastRead(ctx: DashboardProcedureCont
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getDashboardBudgetForecastDetail(ctx: DashboardProcedureContext) {
|
||||
const budgetForecast = await getDashboardBudgetForecast(ctx.db);
|
||||
export async function getDashboardBudgetForecastDetail(
|
||||
ctx: DashboardProcedureContext,
|
||||
): Promise<DashboardBudgetForecastDetail> {
|
||||
const budgetForecast: BudgetForecastRow[] = await getDashboardBudgetForecast(ctx.db);
|
||||
return mapBudgetForecastDetailRows(budgetForecast);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user