feat(platform): checkpoint current implementation state
This commit is contained in:
@@ -59,6 +59,67 @@ describe("report router", () => {
|
||||
]));
|
||||
});
|
||||
|
||||
it("exposes extended resource and project basis columns for report completeness", async () => {
|
||||
const caller = createControllerCaller({});
|
||||
|
||||
const resourceColumns = await caller.getAvailableColumns({ entity: "resource" });
|
||||
const projectColumns = await caller.getAvailableColumns({ entity: "project" });
|
||||
|
||||
expect(resourceColumns).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ key: "enterpriseId", label: "Enterprise ID" }),
|
||||
expect.objectContaining({ key: "valueScore", label: "Value Score" }),
|
||||
expect.objectContaining({ key: "blueprint.name", label: "Blueprint" }),
|
||||
expect.objectContaining({ key: "clientUnit.name", label: "Client Unit" }),
|
||||
]));
|
||||
expect(projectColumns).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ key: "shoringThreshold", label: "Shoring Threshold (%)" }),
|
||||
expect.objectContaining({ key: "onshoreCountryCode", label: "Onshore Country Code" }),
|
||||
expect.objectContaining({ key: "color", label: "Color" }),
|
||||
]));
|
||||
});
|
||||
|
||||
it("lists backend-managed report blueprints for resource_month", async () => {
|
||||
const caller = createControllerCaller({});
|
||||
const blueprints = await caller.listBlueprints({ entity: "resource_month" });
|
||||
|
||||
expect(blueprints).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "resource-month-sah-transparency",
|
||||
entity: "resource_month",
|
||||
templateName: "Monthly SAH transparency",
|
||||
config: expect.objectContaining({
|
||||
entity: "resource_month",
|
||||
sortBy: "displayName",
|
||||
sortDir: "asc",
|
||||
filters: [],
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "resource-month-chargeability-audit",
|
||||
entity: "resource_month",
|
||||
templateName: "Monthly chargeability audit",
|
||||
config: expect.objectContaining({
|
||||
entity: "resource_month",
|
||||
sortBy: "monthlyActualChargeabilityPct",
|
||||
sortDir: "desc",
|
||||
filters: [],
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "resource-month-location-comparison",
|
||||
entity: "resource_month",
|
||||
templateName: "Monthly holiday comparison by location",
|
||||
config: expect.objectContaining({
|
||||
entity: "resource_month",
|
||||
groupBy: "federalState",
|
||||
sortBy: "monthlyPublicHolidayHoursDeduction",
|
||||
sortDir: "desc",
|
||||
filters: [],
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("exports resource month basis and computed columns in CSV", async () => {
|
||||
const db = {
|
||||
resource: {
|
||||
@@ -114,6 +175,42 @@ describe("report router", () => {
|
||||
expect(result.rowCount).toBe(1);
|
||||
expect(result.csv).toContain("Name,Country Code,Holiday Dates,Holiday Hours Deduction,Absence Hours Deduction,SAH,Target Hours,Unassigned Hours");
|
||||
expect(result.csv).toContain("Alice,DE,1,8,4,156,124.8,156");
|
||||
expect(result.columns).toEqual([
|
||||
"id",
|
||||
"displayName",
|
||||
"countryCode",
|
||||
"monthlyPublicHolidayCount",
|
||||
"monthlyPublicHolidayHoursDeduction",
|
||||
"monthlyAbsenceHoursDeduction",
|
||||
"monthlySahHours",
|
||||
"monthlyTargetHours",
|
||||
"monthlyUnassignedHours",
|
||||
]);
|
||||
expect(result.explainability).toEqual({
|
||||
entity: "resource_month",
|
||||
periodMonth: "2026-04",
|
||||
locationContextColumns: ["countryCode"],
|
||||
holidayMetricColumns: ["monthlyPublicHolidayCount", "monthlyPublicHolidayHoursDeduction"],
|
||||
absenceMetricColumns: ["monthlyAbsenceHoursDeduction"],
|
||||
capacityMetricColumns: ["monthlySahHours", "monthlyTargetHours"],
|
||||
chargeabilityMetricColumns: ["monthlyUnassignedHours"],
|
||||
missingRecommendedColumns: [
|
||||
"countryName",
|
||||
"federalState",
|
||||
"metroCityName",
|
||||
"monthlyPublicHolidayWorkdayCount",
|
||||
"monthlyAbsenceDayEquivalent",
|
||||
"monthlyBaseWorkingDays",
|
||||
"monthlyEffectiveWorkingDays",
|
||||
"monthlyBaseAvailableHours",
|
||||
"monthlyChargeabilityTargetPct",
|
||||
],
|
||||
notes: [
|
||||
"monthlySahHours already reflects region-specific public holidays from country, federal state, and city context when those attributes exist on the resource.",
|
||||
"monthlyAbsence* metrics only deduct workdays that are not already counted as public holidays.",
|
||||
"monthlyBaseAvailableHours shows pre-deduction capacity; compare it with holiday, absence, and SAH columns to explain the final monthly availability.",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps holiday and absence deductions separate in resource_month rows", async () => {
|
||||
@@ -178,6 +275,132 @@ describe("report router", () => {
|
||||
monthlySahHours: 156,
|
||||
},
|
||||
]);
|
||||
expect(result.explainability).toEqual({
|
||||
entity: "resource_month",
|
||||
periodMonth: "2026-04",
|
||||
locationContextColumns: [],
|
||||
holidayMetricColumns: ["monthlyPublicHolidayCount", "monthlyPublicHolidayHoursDeduction"],
|
||||
absenceMetricColumns: ["monthlyAbsenceDayEquivalent", "monthlyAbsenceHoursDeduction"],
|
||||
capacityMetricColumns: ["monthlySahHours"],
|
||||
chargeabilityMetricColumns: [],
|
||||
missingRecommendedColumns: [
|
||||
"countryCode",
|
||||
"countryName",
|
||||
"federalState",
|
||||
"metroCityName",
|
||||
"monthlyPublicHolidayWorkdayCount",
|
||||
"monthlyBaseWorkingDays",
|
||||
"monthlyEffectiveWorkingDays",
|
||||
"monthlyBaseAvailableHours",
|
||||
"monthlyChargeabilityTargetPct",
|
||||
"monthlyTargetHours",
|
||||
],
|
||||
notes: [
|
||||
"monthlySahHours already reflects region-specific public holidays from country, federal state, and city context when those attributes exist on the resource.",
|
||||
"monthlyAbsence* metrics only deduct workdays that are not already counted as public holidays.",
|
||||
"monthlyBaseAvailableHours shows pre-deduction capacity; compare it with holiday, absence, and SAH columns to explain the final monthly availability.",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("flattens extended assignment resource and project context columns", async () => {
|
||||
const db = {
|
||||
assignment: {
|
||||
findMany: vi.fn().mockResolvedValue([
|
||||
{
|
||||
id: "asg_1",
|
||||
hoursPerDay: 6,
|
||||
resource: {
|
||||
displayName: "Alice",
|
||||
resourceType: "EMPLOYEE",
|
||||
chargeabilityTarget: 85,
|
||||
orgUnit: { name: "Delivery" },
|
||||
managementLevelGroup: { name: "Senior IC" },
|
||||
managementLevel: { name: "Senior Artist" },
|
||||
},
|
||||
project: {
|
||||
name: "Gelddruckmaschine",
|
||||
orderType: "TIME_AND_MATERIAL",
|
||||
allocationType: "PROJECT",
|
||||
blueprint: { name: "Consulting Blueprint" },
|
||||
utilizationCategory: { name: "Billable" },
|
||||
},
|
||||
},
|
||||
]),
|
||||
count: vi.fn().mockResolvedValue(1),
|
||||
},
|
||||
};
|
||||
|
||||
const caller = createControllerCaller(db);
|
||||
const result = await caller.getReportData({
|
||||
entity: "assignment",
|
||||
columns: [
|
||||
"resource.displayName",
|
||||
"resource.resourceType",
|
||||
"resource.chargeabilityTarget",
|
||||
"resource.orgUnit.name",
|
||||
"resource.managementLevelGroup.name",
|
||||
"resource.managementLevel.name",
|
||||
"project.name",
|
||||
"project.orderType",
|
||||
"project.allocationType",
|
||||
"project.blueprint.name",
|
||||
"project.utilizationCategory.name",
|
||||
"hoursPerDay",
|
||||
],
|
||||
filters: [],
|
||||
sortBy: "hoursPerDay",
|
||||
sortDir: "desc",
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
expect(db.assignment.findMany).toHaveBeenCalledWith({
|
||||
select: {
|
||||
id: true,
|
||||
hoursPerDay: true,
|
||||
resource: {
|
||||
select: {
|
||||
displayName: true,
|
||||
resourceType: true,
|
||||
chargeabilityTarget: true,
|
||||
orgUnit: { select: { name: true } },
|
||||
managementLevelGroup: { select: { name: true } },
|
||||
managementLevel: { select: { name: true } },
|
||||
},
|
||||
},
|
||||
project: {
|
||||
select: {
|
||||
name: true,
|
||||
orderType: true,
|
||||
allocationType: true,
|
||||
blueprint: { select: { name: true } },
|
||||
utilizationCategory: { select: { name: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {},
|
||||
orderBy: [{ hoursPerDay: "desc" }],
|
||||
take: 10,
|
||||
skip: 0,
|
||||
});
|
||||
expect(result.rows).toEqual([
|
||||
{
|
||||
id: "asg_1",
|
||||
"resource.displayName": "Alice",
|
||||
"resource.resourceType": "EMPLOYEE",
|
||||
"resource.chargeabilityTarget": 85,
|
||||
"resource.orgUnit.name": "Delivery",
|
||||
"resource.managementLevelGroup.name": "Senior IC",
|
||||
"resource.managementLevel.name": "Senior Artist",
|
||||
"project.name": "Gelddruckmaschine",
|
||||
"project.orderType": "TIME_AND_MATERIAL",
|
||||
"project.allocationType": "PROJECT",
|
||||
"project.blueprint.name": "Consulting Blueprint",
|
||||
"project.utilizationCategory.name": "Billable",
|
||||
hoursPerDay: 6,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("rejects invalid resource_month period months instead of silently normalizing them", async () => {
|
||||
|
||||
Reference in New Issue
Block a user