feat(api): explain chargeability derivation inputs
This commit is contained in:
@@ -132,6 +132,38 @@ describe("chargeability report router", () => {
|
||||
|
||||
expect(strictMonth).toBeDefined();
|
||||
expect(proposedMonth).toBeDefined();
|
||||
expect(strict.explainability).toEqual({
|
||||
locationFields: [
|
||||
"country",
|
||||
"federalState",
|
||||
"city",
|
||||
"orgUnit",
|
||||
"managementLevelGroup",
|
||||
"managementLevel",
|
||||
],
|
||||
monthDerivationFields: [
|
||||
"baseAvailableHours",
|
||||
"publicHolidayCount",
|
||||
"publicHolidayWorkdayCount",
|
||||
"publicHolidayHoursDeduction",
|
||||
"absenceDayEquivalent",
|
||||
"absenceHoursDeduction",
|
||||
"effectiveAvailableHours",
|
||||
],
|
||||
activeFilters: [],
|
||||
formulas: {
|
||||
sah: "baseAvailableHours - publicHolidayHoursDeduction - absenceHoursDeduction = effectiveAvailableHours",
|
||||
chargeabilityPct: "chargeabilityHours / sahHours",
|
||||
targetHours: "sahHours * targetPct",
|
||||
gapHours: "chargeabilityHours - targetHours",
|
||||
},
|
||||
notes: [
|
||||
"Location fields explain why two resources can have different SAH in the same month because country, federal state, and city holidays may differ.",
|
||||
"Holiday deductions and absence deductions are tracked separately; absence does not deduct days that are already public holidays.",
|
||||
"Include proposed work changes chargeability ratios and hours, but it does not change holiday or absence-based SAH derivation.",
|
||||
],
|
||||
});
|
||||
expect(withProposed.explainability.activeFilters).toEqual(["includeProposed"]);
|
||||
expect(strictMonth?.chg).toBeGreaterThan(0);
|
||||
expect(proposedMonth?.chg).toBeGreaterThan(strictMonth?.chg ?? 0);
|
||||
expect(proposedMonth?.chg).toBeCloseTo((strictMonth?.chg ?? 0) * 2, 5);
|
||||
@@ -352,6 +384,13 @@ describe("chargeability report router", () => {
|
||||
const augsburg = report.resources.find((resource) => resource.city === "Augsburg");
|
||||
const munich = report.resources.find((resource) => resource.city === "Munich");
|
||||
|
||||
expect(augsburg?.federalState).toBe("BY");
|
||||
expect(augsburg?.months[0]?.derivation?.publicHolidayCount).toBe(
|
||||
(munich?.months[0]?.derivation?.publicHolidayCount ?? 0) + 1,
|
||||
);
|
||||
expect(augsburg?.months[0]?.derivation?.publicHolidayHoursDeduction).toBe(
|
||||
(munich?.months[0]?.derivation?.publicHolidayHoursDeduction ?? 0) + 8,
|
||||
);
|
||||
expect(augsburg?.months[0]?.sah).toBe((munich?.months[0]?.sah ?? 0) - 8);
|
||||
});
|
||||
|
||||
@@ -513,11 +552,43 @@ describe("chargeability report router", () => {
|
||||
expect(result.resourceCount).toBe(1);
|
||||
expect(result.returnedResourceCount).toBe(1);
|
||||
expect(result.truncated).toBe(false);
|
||||
expect(result.explainability).toEqual({
|
||||
locationFields: [
|
||||
"country",
|
||||
"federalState",
|
||||
"city",
|
||||
"orgUnit",
|
||||
"managementLevelGroup",
|
||||
"managementLevel",
|
||||
],
|
||||
monthDerivationFields: [
|
||||
"baseAvailableHours",
|
||||
"publicHolidayCount",
|
||||
"publicHolidayWorkdayCount",
|
||||
"publicHolidayHoursDeduction",
|
||||
"absenceDayEquivalent",
|
||||
"absenceHoursDeduction",
|
||||
"effectiveAvailableHours",
|
||||
],
|
||||
activeFilters: ["resourceQuery"],
|
||||
formulas: {
|
||||
sah: "baseAvailableHours - publicHolidayHoursDeduction - absenceHoursDeduction = effectiveAvailableHours",
|
||||
chargeabilityPct: "chargeabilityHours / sahHours",
|
||||
targetHours: "sahHours * targetPct",
|
||||
gapHours: "chargeabilityHours - targetHours",
|
||||
},
|
||||
notes: [
|
||||
"Location fields explain why two resources can have different SAH in the same month because country, federal state, and city holidays may differ.",
|
||||
"Holiday deductions and absence deductions are tracked separately; absence does not deduct days that are already public holidays.",
|
||||
"Include proposed work changes chargeability ratios and hours, but it does not change holiday or absence-based SAH derivation.",
|
||||
],
|
||||
});
|
||||
expect(result.resources).toEqual([
|
||||
expect.objectContaining({
|
||||
displayName: "Alice",
|
||||
targetPct: 80,
|
||||
country: "ES",
|
||||
federalState: null,
|
||||
city: "Barcelona",
|
||||
managementLevelGroup: "Senior",
|
||||
managementLevel: "L7",
|
||||
@@ -527,6 +598,10 @@ describe("chargeability report router", () => {
|
||||
sah: expect.any(Number),
|
||||
chargeabilityPct: expect.any(Number),
|
||||
gapPct: expect.any(Number),
|
||||
derivation: expect.objectContaining({
|
||||
baseAvailableHours: expect.any(Number),
|
||||
effectiveAvailableHours: expect.any(Number),
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user