Files
CapaKraken/apps/web/src/components/reports/reportBuilderExplainability.ts
T

92 lines
3.1 KiB
TypeScript

type WorkbookCellValue = boolean | Date | number | string | null | undefined;
export type ResourceMonthReportExplainability = {
entity: "resource_month";
periodMonth: string | null;
locationContextColumns: string[];
holidayMetricColumns: string[];
absenceMetricColumns: string[];
capacityMetricColumns: string[];
chargeabilityMetricColumns: string[];
missingRecommendedColumns: string[];
notes: string[];
};
export type ReportExplainability = ResourceMonthReportExplainability;
export type ReportExportSheet = {
name: string;
rows: WorkbookCellValue[][];
};
type BuildReportWorkbookSheetsInput = {
columns: string[];
rows: Record<string, unknown>[];
groups: Array<{ key: string; label: string; rowCount: number; startIndex: number }>;
groupBy?: string;
explainability?: ReportExplainability;
resolveColumnLabel: (column: string) => string;
};
export function buildResourceMonthExplainabilitySheetRows(
explainability: ReportExplainability,
resolveColumnLabel: (column: string) => string,
): WorkbookCellValue[][] {
const mapLabels = (columns: string[]) => (
columns.length > 0 ? columns.map(resolveColumnLabel) : ["none"]
);
return [
["Resource Month Explainability"],
["Period Month", explainability.periodMonth ?? "current month"],
["Location Context Columns", ...mapLabels(explainability.locationContextColumns)],
["Holiday Metric Columns", ...mapLabels(explainability.holidayMetricColumns)],
["Absence Metric Columns", ...mapLabels(explainability.absenceMetricColumns)],
["Capacity Metric Columns", ...mapLabels(explainability.capacityMetricColumns)],
["Chargeability Metric Columns", ...mapLabels(explainability.chargeabilityMetricColumns)],
["Missing Recommended Columns", ...mapLabels(explainability.missingRecommendedColumns)],
[],
["Notes"],
...explainability.notes.map((note) => [note]),
];
}
export function buildReportWorkbookSheets(
input: BuildReportWorkbookSheetsInput,
): ReportExportSheet[] {
const headerRow = input.columns.map(input.resolveColumnLabel);
const groupStartByIndex = new Map(
input.groups.map((group) => [group.startIndex, group] as const),
);
const groupByLabel = input.groupBy ? input.resolveColumnLabel(input.groupBy) : null;
const reportRows: WorkbookCellValue[][] = [headerRow];
input.rows.forEach((row, index) => {
const group = groupStartByIndex.get(index);
if (group && groupByLabel) {
reportRows.push([
`${groupByLabel}: ${group.label} (${group.rowCount})`,
...Array.from({ length: Math.max(0, input.columns.length - 1) }, () => ""),
]);
}
reportRows.push(input.columns.map((column) => {
const value = row[column];
if (value === undefined) {
return "";
}
return value as WorkbookCellValue;
}));
});
const sheets: ReportExportSheet[] = [{ name: "Report", rows: reportRows }];
if (input.explainability?.entity === "resource_month") {
sheets.push({
name: "Explainability",
rows: buildResourceMonthExplainabilitySheetRows(input.explainability, input.resolveColumnLabel),
});
}
return sheets;
}