215 lines
6.4 KiB
TypeScript
215 lines
6.4 KiB
TypeScript
import { z } from "zod";
|
|
import {
|
|
reportEntitySchema,
|
|
ReportTemplateConfigSchema,
|
|
type EntityKey,
|
|
} from "./report-query-config.js";
|
|
|
|
export const RESOURCE_MONTH_RECOMMENDED_COLUMNS = [
|
|
"monthKey",
|
|
"displayName",
|
|
"eid",
|
|
"chapter",
|
|
"countryCode",
|
|
"countryName",
|
|
"federalState",
|
|
"metroCityName",
|
|
"orgUnitName",
|
|
"managementLevelGroupName",
|
|
"monthlyBaseWorkingDays",
|
|
"monthlyEffectiveWorkingDays",
|
|
"monthlyBaseAvailableHours",
|
|
"monthlyPublicHolidayCount",
|
|
"monthlyPublicHolidayWorkdayCount",
|
|
"monthlyPublicHolidayHoursDeduction",
|
|
"monthlyAbsenceDayEquivalent",
|
|
"monthlyAbsenceHoursDeduction",
|
|
"monthlySahHours",
|
|
"monthlyChargeabilityTargetPct",
|
|
"monthlyTargetHours",
|
|
"monthlyActualBookedHours",
|
|
"monthlyExpectedBookedHours",
|
|
"monthlyActualChargeabilityPct",
|
|
"monthlyExpectedChargeabilityPct",
|
|
"monthlyUnassignedHours",
|
|
] as const;
|
|
|
|
export const RESOURCE_MONTH_MINIMUM_AUDIT_COLUMNS = [
|
|
"monthKey",
|
|
"displayName",
|
|
"countryName",
|
|
"federalState",
|
|
"metroCityName",
|
|
"monthlyPublicHolidayCount",
|
|
"monthlyPublicHolidayHoursDeduction",
|
|
"monthlyAbsenceDayEquivalent",
|
|
"monthlyAbsenceHoursDeduction",
|
|
"monthlySahHours",
|
|
"monthlyTargetHours",
|
|
"monthlyActualBookedHours",
|
|
"monthlyUnassignedHours",
|
|
] as const;
|
|
|
|
export const ReportBlueprintSummarySchema = z.object({
|
|
id: z.string().min(1),
|
|
label: z.string().min(1),
|
|
description: z.string().min(1),
|
|
entity: reportEntitySchema,
|
|
templateName: z.string().min(1),
|
|
config: ReportTemplateConfigSchema,
|
|
});
|
|
|
|
export const ReportBlueprintCatalogSchema = z.array(ReportBlueprintSummarySchema);
|
|
|
|
export type ReportBlueprintSummary = z.infer<typeof ReportBlueprintSummarySchema>;
|
|
|
|
export type ResourceMonthTemplateCompleteness = {
|
|
scope: "resource_month";
|
|
isAuditReady: boolean;
|
|
isRecommendedComplete: boolean;
|
|
recommendedColumnCount: number;
|
|
selectedRecommendedColumnCount: number;
|
|
minimumAuditColumnCount: number;
|
|
selectedMinimumAuditColumnCount: number;
|
|
missingRecommendedColumns: string[];
|
|
missingMinimumAuditColumns: string[];
|
|
};
|
|
|
|
const REPORT_BLUEPRINTS = ReportBlueprintCatalogSchema.parse([
|
|
{
|
|
id: "resource-month-sah-transparency",
|
|
label: "SAH transparency",
|
|
description: "Explains how monthly SAH is reduced by holidays and absences per person.",
|
|
entity: "resource_month",
|
|
templateName: "Monthly SAH transparency",
|
|
config: {
|
|
entity: "resource_month",
|
|
columns: [
|
|
"monthKey",
|
|
"displayName",
|
|
"eid",
|
|
"chapter",
|
|
"countryName",
|
|
"federalState",
|
|
"metroCityName",
|
|
"orgUnitName",
|
|
"managementLevelGroupName",
|
|
"monthlyBaseWorkingDays",
|
|
"monthlyEffectiveWorkingDays",
|
|
"monthlyBaseAvailableHours",
|
|
"monthlyPublicHolidayCount",
|
|
"monthlyPublicHolidayWorkdayCount",
|
|
"monthlyPublicHolidayHoursDeduction",
|
|
"monthlyAbsenceDayEquivalent",
|
|
"monthlyAbsenceHoursDeduction",
|
|
"monthlySahHours",
|
|
"monthlyChargeabilityTargetPct",
|
|
"monthlyTargetHours",
|
|
],
|
|
filters: [],
|
|
sortBy: "displayName",
|
|
sortDir: "asc",
|
|
},
|
|
},
|
|
{
|
|
id: "resource-month-chargeability-audit",
|
|
label: "Chargeability audit",
|
|
description: "Shows the full path from monthly SAH to booked, target and unassigned hours.",
|
|
entity: "resource_month",
|
|
templateName: "Monthly chargeability audit",
|
|
config: {
|
|
entity: "resource_month",
|
|
columns: [
|
|
"monthKey",
|
|
"displayName",
|
|
"eid",
|
|
"chapter",
|
|
"countryName",
|
|
"federalState",
|
|
"metroCityName",
|
|
"orgUnitName",
|
|
"managementLevelGroupName",
|
|
"monthlyBaseAvailableHours",
|
|
"monthlyPublicHolidayCount",
|
|
"monthlyPublicHolidayHoursDeduction",
|
|
"monthlyAbsenceDayEquivalent",
|
|
"monthlyAbsenceHoursDeduction",
|
|
"monthlySahHours",
|
|
"monthlyChargeabilityTargetPct",
|
|
"monthlyTargetHours",
|
|
"monthlyActualBookedHours",
|
|
"monthlyExpectedBookedHours",
|
|
"monthlyActualChargeabilityPct",
|
|
"monthlyExpectedChargeabilityPct",
|
|
"monthlyUnassignedHours",
|
|
"lcrCents",
|
|
"currency",
|
|
],
|
|
filters: [],
|
|
sortBy: "monthlyActualChargeabilityPct",
|
|
sortDir: "desc",
|
|
},
|
|
},
|
|
{
|
|
id: "resource-month-location-comparison",
|
|
label: "Location comparison",
|
|
description: "Compares holiday impact across country, state and city contexts for the same month.",
|
|
entity: "resource_month",
|
|
templateName: "Monthly holiday comparison by location",
|
|
config: {
|
|
entity: "resource_month",
|
|
columns: [
|
|
"monthKey",
|
|
"displayName",
|
|
"chapter",
|
|
"countryName",
|
|
"federalState",
|
|
"metroCityName",
|
|
"orgUnitName",
|
|
"monthlyBaseWorkingDays",
|
|
"monthlyBaseAvailableHours",
|
|
"monthlyPublicHolidayCount",
|
|
"monthlyPublicHolidayWorkdayCount",
|
|
"monthlyPublicHolidayHoursDeduction",
|
|
"monthlyAbsenceDayEquivalent",
|
|
"monthlyAbsenceHoursDeduction",
|
|
"monthlySahHours",
|
|
"monthlyActualChargeabilityPct",
|
|
],
|
|
filters: [],
|
|
groupBy: "federalState",
|
|
sortBy: "monthlyPublicHolidayHoursDeduction",
|
|
sortDir: "desc",
|
|
},
|
|
},
|
|
]);
|
|
|
|
export function listReportBlueprints(entity?: EntityKey): ReportBlueprintSummary[] {
|
|
return entity
|
|
? REPORT_BLUEPRINTS.filter((blueprint) => blueprint.entity === entity)
|
|
: REPORT_BLUEPRINTS;
|
|
}
|
|
|
|
export function buildResourceMonthTemplateCompleteness(
|
|
columns: Iterable<string>,
|
|
): ResourceMonthTemplateCompleteness {
|
|
const selectedColumns = new Set(columns);
|
|
const missingRecommendedColumns = RESOURCE_MONTH_RECOMMENDED_COLUMNS
|
|
.filter((column) => !selectedColumns.has(column));
|
|
const missingMinimumAuditColumns = RESOURCE_MONTH_MINIMUM_AUDIT_COLUMNS
|
|
.filter((column) => !selectedColumns.has(column));
|
|
|
|
return {
|
|
scope: "resource_month",
|
|
isAuditReady: missingMinimumAuditColumns.length === 0,
|
|
isRecommendedComplete: missingRecommendedColumns.length === 0,
|
|
recommendedColumnCount: RESOURCE_MONTH_RECOMMENDED_COLUMNS.length,
|
|
selectedRecommendedColumnCount: RESOURCE_MONTH_RECOMMENDED_COLUMNS.length - missingRecommendedColumns.length,
|
|
minimumAuditColumnCount: RESOURCE_MONTH_MINIMUM_AUDIT_COLUMNS.length,
|
|
selectedMinimumAuditColumnCount:
|
|
RESOURCE_MONTH_MINIMUM_AUDIT_COLUMNS.length - missingMinimumAuditColumns.length,
|
|
missingRecommendedColumns,
|
|
missingMinimumAuditColumns,
|
|
};
|
|
}
|