From ddf3b2fafc8fb93fd78778e56af9a07896f26dfa Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Wed, 18 Sep 2024 09:08:09 -0400 Subject: [PATCH 1/7] GV Refactor - validateFfsRadioButtonCompletion (#2440) --- .../2023/shared/globalValidations/index.ts | 2 +- .../2023/shared/util/validationsMock.tsx | 2 +- .../2024/shared/globalValidations/index.ts | 2 +- .../index.test.ts | 49 ------------------- .../validateFfsRadioButtonCompletion/index.ts | 37 -------------- .../2024/shared/util/validationsMock.tsx | 2 +- .../index.test.ts | 2 +- .../validateFfsRadioButtonCompletion/index.ts | 0 8 files changed, 5 insertions(+), 91 deletions(-) delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts (94%) rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts (100%) diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts index 3381a22ba8..1f94abfdbe 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts @@ -13,7 +13,7 @@ export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; export * from "./validateDualPopInformation"; export * from "./validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; -export * from "./validateFfsRadioButtonCompletion"; +export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; export * from "./validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; diff --git a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx index b96fbd0309..15017a7f65 100644 --- a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx @@ -8,7 +8,7 @@ import * as validateBothDatesInRange from "shared/globalValidations/validateBoth import * as validateDualPopInformation from "measures/2023/shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "measures/2023/shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; -import * as validateFfsRadioButtonCompletion from "measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion"; +import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; import * as validateRateNotZero from "measures/2023/shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2023/shared/globalValidations/validateRateZero"; import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts index 9ebc576fec..36cc92039c 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts @@ -14,7 +14,7 @@ export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; export * from "./validateDualPopInformation"; export * from "./validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; -export * from "./validateFfsRadioButtonCompletion"; +export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; export * from "./validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts deleted file mode 100644 index bbad461994..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { testFormData } from "../testHelpers/_testFormData"; -import * as DC from "dataConstants"; -import { validateFfsRadioButtonCompletion } from "."; - -describe("validateFfsRadioButtonCompletion", () => { - let formData: any; - let errorArray: FormError[]; - - const _check_errors = (data: any, numErrors: number) => { - errorArray = [...validateFfsRadioButtonCompletion(data)]; - expect(errorArray.length).toBe(numErrors); - }; - - beforeEach(() => { - formData = JSON.parse(JSON.stringify(testFormData)); // reset data - errorArray = []; - }); - - it("When no Delivery System nested question is checked a validation warning shows", () => { - formData[DC.DELIVERY_SYS_REPRESENTATION_DENOMINATOR] = [DC.FFS]; - formData[DC.DELIVERY_SYS_FFS] = undefined; - _check_errors(formData, 1); - }); - - it("When a Delivery System nested question is checked no validation warning shows", () => { - formData[DC.DELIVERY_SYS_REPRESENTATION_DENOMINATOR] = [DC.FFS]; - formData[DC.DELIVERY_SYS_FFS] = "yes"; - _check_errors(formData, 0); - }); - - it("Error message text should match default errorMessage", () => { - formData[DC.DELIVERY_SYS_REPRESENTATION_DENOMINATOR] = [DC.FFS]; - formData[DC.DELIVERY_SYS_FFS] = undefined; - errorArray = [...validateFfsRadioButtonCompletion(formData)]; - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - "You must indicate if the measure-eligible population is included" - ); - }); - - it("Error message text should match provided errorMessage", () => { - formData[DC.DELIVERY_SYS_REPRESENTATION_DENOMINATOR] = [DC.FFS]; - formData[DC.DELIVERY_SYS_FFS] = undefined; - const errorMessage = "Another one bites the dust."; - errorArray = [...validateFfsRadioButtonCompletion(formData, errorMessage)]; - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts deleted file mode 100644 index a656576fdb..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as Types from "shared/types"; -import * as DC from "dataConstants"; - -export const validateFfsRadioButtonCompletion = ( - data: Types.DefinitionOfPopulation, - errorMessage?: string -) => { - const errorArray: FormError[] = []; - - // map the delivery systems to their respective nested selections - const deliverySystemsMap = { - [DC.FFS]: DC.DELIVERY_SYS_FFS, - [DC.ICM]: DC.DELIVERY_SYS_ICM, - [DC.PCCM]: DC.DELIVERY_SYS_PCCM, - [DC.MCO_PIHP]: DC.DELIVERY_SYS_MCO_PIHP, - [DC.OTHER]: DC.DELIVERY_SYS_OTHER, - }; - - const selectedDeliverySystems = data.DeliverySysRepresentationDenominator; - if (selectedDeliverySystems) { - selectedDeliverySystems.forEach((system) => { - Object.entries(data).forEach((selection) => { - // check if user has actually checked the nested radio button selection - if (selection[0] === deliverySystemsMap[system] && !selection[1]) { - errorArray.push({ - errorLocation: "Delivery Systems", - errorMessage: - errorMessage ?? - "You must indicate if the measure-eligible population is included", - }); - } - }); - }); - } - - return errorArray; -}; diff --git a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx index eb4ebce901..1fee268f9c 100644 --- a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx @@ -8,7 +8,7 @@ import * as validateBothDatesInRange from "shared/globalValidations/validateBoth import * as validateDualPopInformation from "measures/2024/shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "measures/2024/shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; -import * as validateFfsRadioButtonCompletion from "measures/2024/shared/globalValidations/validateFfsRadioButtonCompletion"; +import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; import * as validateRateNotZero from "measures/2024/shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2024/shared/globalValidations/validateRateZero"; import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts b/services/ui-src/src/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts similarity index 94% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts rename to services/ui-src/src/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts index bbad461994..8c763860f3 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts +++ b/services/ui-src/src/shared/globalValidations/validateFfsRadioButtonCompletion/index.test.ts @@ -1,4 +1,4 @@ -import { testFormData } from "../testHelpers/_testFormData"; +import { testFormData } from "measures/2024/shared/globalValidations/testHelpers/_testFormData"; import * as DC from "dataConstants"; import { validateFfsRadioButtonCompletion } from "."; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts b/services/ui-src/src/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts similarity index 100% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts rename to services/ui-src/src/shared/globalValidations/validateFfsRadioButtonCompletion/index.ts From bd7aebe30af7e43a071ceccf7f5ae8f44d1a1662 Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Wed, 18 Sep 2024 09:08:36 -0400 Subject: [PATCH 2/7] GV Refactor - validateEqualCategoryDenominators (#2439) --- .../measures/2021/globalValidations/index.ts | 2 +- .../index.test.ts | 185 ------------------ .../index.ts | 78 -------- .../2022/shared/globalValidations/index.ts | 2 +- .../index.test.ts | 185 ------------------ .../index.ts | 78 -------- .../2022/shared/util/validationsMock.tsx | 2 +- .../2023/shared/globalValidations/index.ts | 2 +- .../2023/shared/util/validationsMock.tsx | 2 +- .../2024/shared/globalValidations/index.ts | 2 +- .../index.test.ts | 184 ----------------- .../index.ts | 80 -------- .../2024/shared/util/validationsMock.tsx | 2 +- .../index.test.ts | 0 .../index.ts | 2 +- 15 files changed, 8 insertions(+), 798 deletions(-) delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.test.ts delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.ts rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts (100%) rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateEqualCategoryDenominators/index.ts (98%) diff --git a/services/ui-src/src/measures/2021/globalValidations/index.ts b/services/ui-src/src/measures/2021/globalValidations/index.ts index da16c2bb40..8600b83908 100644 --- a/services/ui-src/src/measures/2021/globalValidations/index.ts +++ b/services/ui-src/src/measures/2021/globalValidations/index.ts @@ -7,7 +7,7 @@ export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "./validateDualPopInformation"; -export * from "./validateEqualCategoryDenominators"; +export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "./validateRateNotZero"; export * from "./validateRateZero"; diff --git a/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.test.ts b/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.test.ts deleted file mode 100644 index 77711f948a..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { LabelData } from "utils"; -import { - validateEqualCategoryDenominatorsOMS, - validateEqualCategoryDenominatorsPM, -} from "."; - -import { - generateOmsCategoryRateData, - locationDictionary, - doubleRate, - simpleRate, - partialRate, - generatePmQualifierRateData, -} from "utils/testUtils/validationHelpers"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Equal Denominators For All Qualifiers Validation", () => { - const noCat: LabelData[] = []; - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - const pmd = { categories, qualifiers }; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, simpleRate]), - categories - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, doubleRate]), - categories - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - }); - - it("should have error, with qualifiers listed", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(qualifiers[0].label); - expect(errors[0].errorList).toContain(qualifiers[1].label); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [partialRate, partialRate]), - categories - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errorArray = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers, - errorMessage - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return NO errors", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return no errors if OPM", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - isOPM: true, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have errors, list qualifiers", () => { - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - expect(locationDictionaryJestFunc).toHaveBeenCalledWith(["TestLabel"]); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS(errorMessage)({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.ts b/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.ts deleted file mode 100644 index 9441c1d2c8..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateEqualCategoryDenominators/index.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as Types from "shared/types"; -import { - OmsValidationCallback, - UnifiedValidationFunction as UVF, -} from "../types"; -import { - convertOmsDataToRateArray, - getPerfMeasureRateArray, -} from "../dataDrivenTools"; -import { SINGLE_CATEGORY } from "dataConstants"; -import { LabelData } from "utils"; - -const _validation: UVF = ({ - rateData, - qualifiers, - categories, - location, - errorMessage, -}) => { - const errorArray: FormError[] = []; - const locationArray: string[] = []; - const denominatorArray: string[] = []; - - for (const [i, rateSet] of rateData.entries()) { - for (const [j, rate] of rateSet.entries()) { - if (rate && rate.denominator) { - denominatorArray.push(rate.denominator); - locationArray.push( - !!categories?.length && categories[0].label !== SINGLE_CATEGORY - ? categories![i].label - : qualifiers![j].label - ); - } - } - } - - if (!denominatorArray.every((v) => denominatorArray[0] === v)) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - `The following categories must have the same denominator:`, - errorList: locationArray.filter((v, i, a) => a.indexOf(v) === i), - }); - } - - return errorArray; -}; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only use qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsOMS = - (errorMessage?: string): OmsValidationCallback => - ({ rateData, categories, qualifiers, label, locationDictionary, isOPM }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - errorMessage, - }); - }; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only pass qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsPM = ( - data: Types.PerformanceMeasure, - categories: LabelData[], - qualifiers?: LabelData[], - errorMessage?: string -) => { - return _validation({ - categories, - qualifiers, - location: "Performance Measure", - rateData: getPerfMeasureRateArray(data, { categories, qualifiers }), - errorMessage, - }); -}; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts index da16c2bb40..8600b83908 100644 --- a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts @@ -7,7 +7,7 @@ export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "./validateDualPopInformation"; -export * from "./validateEqualCategoryDenominators"; +export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "./validateRateNotZero"; export * from "./validateRateZero"; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts deleted file mode 100644 index 77711f948a..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { LabelData } from "utils"; -import { - validateEqualCategoryDenominatorsOMS, - validateEqualCategoryDenominatorsPM, -} from "."; - -import { - generateOmsCategoryRateData, - locationDictionary, - doubleRate, - simpleRate, - partialRate, - generatePmQualifierRateData, -} from "utils/testUtils/validationHelpers"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Equal Denominators For All Qualifiers Validation", () => { - const noCat: LabelData[] = []; - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - const pmd = { categories, qualifiers }; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, simpleRate]), - categories - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, doubleRate]), - categories - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - }); - - it("should have error, with qualifiers listed", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(qualifiers[0].label); - expect(errors[0].errorList).toContain(qualifiers[1].label); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [partialRate, partialRate]), - categories - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errorArray = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers, - errorMessage - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return NO errors", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return no errors if OPM", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - isOPM: true, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have errors, list qualifiers", () => { - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - expect(locationDictionaryJestFunc).toHaveBeenCalledWith(["TestLabel"]); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS(errorMessage)({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.ts deleted file mode 100644 index 9441c1d2c8..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateEqualCategoryDenominators/index.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as Types from "shared/types"; -import { - OmsValidationCallback, - UnifiedValidationFunction as UVF, -} from "../types"; -import { - convertOmsDataToRateArray, - getPerfMeasureRateArray, -} from "../dataDrivenTools"; -import { SINGLE_CATEGORY } from "dataConstants"; -import { LabelData } from "utils"; - -const _validation: UVF = ({ - rateData, - qualifiers, - categories, - location, - errorMessage, -}) => { - const errorArray: FormError[] = []; - const locationArray: string[] = []; - const denominatorArray: string[] = []; - - for (const [i, rateSet] of rateData.entries()) { - for (const [j, rate] of rateSet.entries()) { - if (rate && rate.denominator) { - denominatorArray.push(rate.denominator); - locationArray.push( - !!categories?.length && categories[0].label !== SINGLE_CATEGORY - ? categories![i].label - : qualifiers![j].label - ); - } - } - } - - if (!denominatorArray.every((v) => denominatorArray[0] === v)) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - `The following categories must have the same denominator:`, - errorList: locationArray.filter((v, i, a) => a.indexOf(v) === i), - }); - } - - return errorArray; -}; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only use qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsOMS = - (errorMessage?: string): OmsValidationCallback => - ({ rateData, categories, qualifiers, label, locationDictionary, isOPM }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - errorMessage, - }); - }; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only pass qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsPM = ( - data: Types.PerformanceMeasure, - categories: LabelData[], - qualifiers?: LabelData[], - errorMessage?: string -) => { - return _validation({ - categories, - qualifiers, - location: "Performance Measure", - rateData: getPerfMeasureRateArray(data, { categories, qualifiers }), - errorMessage, - }); -}; diff --git a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx index ce6b071d9f..3069f378d3 100644 --- a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx @@ -3,7 +3,7 @@ import * as validateAtLeastOneDeviationFieldFilled from "measures/2022/shared/gl import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; import * as validateDualPopInformation from "measures/2022/shared/globalValidations/validateDualPopInformation"; -import * as validateEqualCategoryDenominators from "measures/2022/shared/globalValidations/validateEqualCategoryDenominators"; +import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateRateNotZero from "measures/2022/shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2022/shared/globalValidations/validateRateZero"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts index 1f94abfdbe..5c8eba40dd 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts @@ -11,7 +11,7 @@ export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; export * from "./validateDualPopInformation"; -export * from "./validateEqualCategoryDenominators"; +export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; export * from "./validateRateNotZero"; diff --git a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx index 15017a7f65..b28e7c2294 100644 --- a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx @@ -6,7 +6,7 @@ import * as validateAtLeastOneDeviationFieldFilled from "measures/2023/shared/gl import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; import * as validateDualPopInformation from "measures/2023/shared/globalValidations/validateDualPopInformation"; -import * as validateEqualCategoryDenominators from "measures/2023/shared/globalValidations/validateEqualCategoryDenominators"; +import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; import * as validateRateNotZero from "measures/2023/shared/globalValidations/validateRateNotZero"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts index 36cc92039c..0a19895558 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts @@ -12,7 +12,7 @@ export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; export * from "./validateDualPopInformation"; -export * from "./validateEqualCategoryDenominators"; +export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; export * from "./validateRateNotZero"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts deleted file mode 100644 index 870c5cbf59..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { LabelData } from "utils"; -import { - validateEqualCategoryDenominatorsOMS, - validateEqualCategoryDenominatorsPM, -} from "."; - -import { - generateOmsCategoryRateData, - locationDictionary, - doubleRate, - simpleRate, - partialRate, - generatePmQualifierRateData, -} from "utils/testUtils/validationHelpers"; - -describe("Testing Equal Denominators For All Qualifiers Validation", () => { - const noCat: LabelData[] = []; - const categories = [ - { label: "TestCat1", text: "TestCat1", id: "TestCat1" }, - { label: "TestCat2", text: "TestCat2", id: "TestCat2" }, - ]; - const qualifiers = [ - { label: "TestQual1", text: "TestQual1", id: "TestQual1" }, - { label: "TestQual2", text: "TestQual2", id: "TestQual2" }, - ]; - const pmd = { categories, qualifiers }; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, simpleRate]), - categories, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [simpleRate, doubleRate]), - categories, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - }); - - it("should have error, with qualifiers listed", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorList).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(qualifiers[0].label); - expect(errors[0].errorList).toContain(qualifiers[1].label); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData(pmd, [partialRate, partialRate]), - categories, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errorArray = validateEqualCategoryDenominatorsPM( - generatePmQualifierRateData({ qualifiers, categories: noCat }, [ - simpleRate, - doubleRate, - ]), - noCat, - qualifiers, - errorMessage - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return NO errors", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return no errors if OPM", () => { - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - simpleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - rateData: data, - isOPM: true, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have errors, list qualifiers", () => { - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS()({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe( - `The following categories must have the same denominator:` - ); - expect(errors[0].errorList).toContain(categories[0].label); - expect(errors[0].errorList).toContain(categories[1].label); - expect(locationDictionaryJestFunc).toHaveBeenCalledWith(["TestLabel"]); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const locationDictionaryJestFunc = jest.fn(); - const data = generateOmsCategoryRateData(categories, qualifiers, [ - simpleRate, - doubleRate, - ]); - const errors = validateEqualCategoryDenominatorsOMS(errorMessage)({ - ...baseOMSInfo, - locationDictionary: locationDictionaryJestFunc, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification:" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.ts deleted file mode 100644 index 33aa86814d..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateEqualCategoryDenominators/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as Types from "shared/types"; -import { - OmsValidationCallback, - UnifiedValidationFunction as UVF, -} from "../types"; -import { - convertOmsDataToRateArray, - getPerfMeasureRateArray, -} from "../dataDrivenTools"; -import { SINGLE_CATEGORY } from "dataConstants"; -import { LabelData } from "utils"; - -const _validation: UVF = ({ - rateData, - qualifiers, - categories, - location, - errorMessage, -}) => { - const errorArray: FormError[] = []; - const locationArray: string[] = []; - const denominatorArray: string[] = []; - - for (const [i, rateSet] of rateData.entries()) { - for (const [j, rate] of rateSet.entries()) { - if (rate && rate.denominator) { - denominatorArray.push(rate.denominator); - locationArray.push( - !!categories?.length && - categories[0].label !== SINGLE_CATEGORY && - categories.some((item) => item.label) - ? categories![i].label - : qualifiers![j].label - ); - } - } - } - - if (!denominatorArray.every((v) => denominatorArray[0] === v)) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - `The following categories must have the same denominator:`, - errorList: locationArray.filter((v, i, a) => a.indexOf(v) === i), - }); - } - - return errorArray; -}; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only use qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsOMS = - (errorMessage?: string): OmsValidationCallback => - ({ rateData, categories, qualifiers, label, locationDictionary, isOPM }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - errorMessage, - }); - }; - -/** Checks all rates have the same denominator for both categories and qualifiers. NOTE: only pass qualifiers if category is empty */ -export const validateEqualCategoryDenominatorsPM = ( - data: Types.PerformanceMeasure, - categories: LabelData[], - qualifiers?: LabelData[], - errorMessage?: string -) => { - return _validation({ - categories, - qualifiers, - location: "Performance Measure", - rateData: getPerfMeasureRateArray(data, { categories, qualifiers }), - errorMessage, - }); -}; diff --git a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx index 1fee268f9c..0c798bdbaf 100644 --- a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx @@ -6,7 +6,7 @@ import * as validateAtLeastOneDeviationFieldFilled from "measures/2024/shared/gl import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; import * as validateDualPopInformation from "measures/2024/shared/globalValidations/validateDualPopInformation"; -import * as validateEqualCategoryDenominators from "measures/2024/shared/globalValidations/validateEqualCategoryDenominators"; +import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; import * as validateRateNotZero from "measures/2024/shared/globalValidations/validateRateNotZero"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts b/services/ui-src/src/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts similarity index 100% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts rename to services/ui-src/src/shared/globalValidations/validateEqualCategoryDenominators/index.test.ts diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateEqualCategoryDenominators/index.ts b/services/ui-src/src/shared/globalValidations/validateEqualCategoryDenominators/index.ts similarity index 98% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateEqualCategoryDenominators/index.ts rename to services/ui-src/src/shared/globalValidations/validateEqualCategoryDenominators/index.ts index 33aa86814d..1e3d8b51b9 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateEqualCategoryDenominators/index.ts +++ b/services/ui-src/src/shared/globalValidations/validateEqualCategoryDenominators/index.ts @@ -2,7 +2,7 @@ import * as Types from "shared/types"; import { OmsValidationCallback, UnifiedValidationFunction as UVF, -} from "../types"; +} from "shared/types/TypeValidations"; import { convertOmsDataToRateArray, getPerfMeasureRateArray, From 9db503ebbf8e1c81585553da757ea751339e650c Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:45:21 -0400 Subject: [PATCH 3/7] GV Refactor - validateDualPopInformation (#2438) --- .../measures/2021/globalValidations/index.ts | 2 +- .../validateDualPopInformation/index.test.ts | 137 ------------------ .../validateDualPopInformation/index.ts | 62 -------- .../2022/shared/globalValidations/index.ts | 2 +- .../validateDualPopInformation/index.test.ts | 137 ------------------ .../validateDualPopInformation/index.ts | 62 -------- .../2022/shared/util/validationsMock.tsx | 2 +- .../2023/shared/globalValidations/index.ts | 2 +- .../validateDualPopInformation/index.test.ts | 137 ------------------ .../validateDualPopInformation/index.ts | 62 -------- .../2023/shared/util/validationsMock.tsx | 2 +- .../2024/shared/globalValidations/index.ts | 2 +- .../validateDualPopInformation/index.ts | 43 ------ .../2024/shared/util/validationsMock.tsx | 2 +- .../validateDualPopInformation/index.test.ts | 0 .../validateDualPopInformation/index.ts | 70 +++++++++ 16 files changed, 77 insertions(+), 647 deletions(-) delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.test.ts delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.test.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.ts delete mode 100644 services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.test.ts delete mode 100644 services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.ts rename services/ui-src/src/{measures/2024 => }/shared/globalValidations/validateDualPopInformation/index.test.ts (100%) create mode 100644 services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.ts diff --git a/services/ui-src/src/measures/2021/globalValidations/index.ts b/services/ui-src/src/measures/2021/globalValidations/index.ts index 8600b83908..6b97e90379 100644 --- a/services/ui-src/src/measures/2021/globalValidations/index.ts +++ b/services/ui-src/src/measures/2021/globalValidations/index.ts @@ -6,7 +6,7 @@ export * from "shared/globalValidations/validateAtLeastOneDataSource"; export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; -export * from "./validateDualPopInformation"; +export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "./validateRateNotZero"; diff --git a/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.test.ts b/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.test.ts deleted file mode 100644 index a7a289a2c9..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as DC from "dataConstants"; -import { simpleRate, partialRate } from "utils/testUtils/validationHelpers"; -import { validateDualPopInformationPM } from "."; - -describe("Testing Dual Population Selection Validation", () => { - it("should be no errors", () => { - const errors = validateDualPopInformationPM([], undefined, 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - partial data", () => { - const errors = validateDualPopInformationPM( - [[partialRate, partialRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - OPM", () => { - const errors = validateDualPopInformationPM([], [], 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be errors for no checkbox selections", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection - specified string", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the TestLabel Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no data", () => { - const errors = validateDualPopInformationPM([], undefined, 0, [ - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE, - ]); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for Age 65 and Older` - ); - }); - - it("should be errors for no data - specified string", () => { - const errors = validateDualPopInformationPM( - [], - undefined, - 0, - [DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for TestLabel` - ); - }); - - it("Error message text should match default errorMessage", () => { - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - "Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing" - ); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessageFunc = ( - _dualEligible: boolean, - errorReplacementText: string - ) => { - return `Another ${errorReplacementText} bites the dust`; - }; - - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined, - undefined, - errorMessageFunc - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - errorMessageFunc(true, "Age 65 and Older") - ); - }); -}); diff --git a/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.ts b/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.ts deleted file mode 100644 index 18a57160e9..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateDualPopInformation/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as DC from "dataConstants"; -import { FormRateField } from "../types"; - -const validateDualPopInformationPMErrorMessage = ( - dualEligible: boolean, - errorReplacementText: string -) => { - if (!dualEligible) { - return `Information has been included in the ${errorReplacementText} Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing`; - } else { - return `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for ${errorReplacementText}`; - } -}; - -export const validateDualPopInformationPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - age65PlusIndex: number, - DefinitionOfDenominator: string[] | undefined, - errorReplacementText: string = "Age 65 and Older", - errorMessageFunc = validateDualPopInformationPMErrorMessage -) => { - if (OPM) { - return []; - } - - const dualEligible = DefinitionOfDenominator - ? DefinitionOfDenominator.indexOf( - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE - ) !== -1 - : false; - - const errorArray: FormError[] = []; - const filledInData: FormRateField[] = []; - performanceMeasureArray?.forEach((performanceMeasure) => { - if ( - performanceMeasure && - performanceMeasure[age65PlusIndex] && - performanceMeasure[age65PlusIndex].denominator && - performanceMeasure[age65PlusIndex].numerator && - performanceMeasure[age65PlusIndex].rate - ) { - filledInData.push(performanceMeasure[age65PlusIndex]); - } - }); - - if (!dualEligible && filledInData.length > 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - if (dualEligible && filledInData.length === 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - return errorArray; -}; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts index 8600b83908..6b97e90379 100644 --- a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts @@ -6,7 +6,7 @@ export * from "shared/globalValidations/validateAtLeastOneDataSource"; export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; -export * from "./validateDualPopInformation"; +export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "./validateRateNotZero"; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.test.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.test.ts deleted file mode 100644 index a7a289a2c9..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as DC from "dataConstants"; -import { simpleRate, partialRate } from "utils/testUtils/validationHelpers"; -import { validateDualPopInformationPM } from "."; - -describe("Testing Dual Population Selection Validation", () => { - it("should be no errors", () => { - const errors = validateDualPopInformationPM([], undefined, 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - partial data", () => { - const errors = validateDualPopInformationPM( - [[partialRate, partialRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - OPM", () => { - const errors = validateDualPopInformationPM([], [], 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be errors for no checkbox selections", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection - specified string", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the TestLabel Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no data", () => { - const errors = validateDualPopInformationPM([], undefined, 0, [ - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE, - ]); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for Age 65 and Older` - ); - }); - - it("should be errors for no data - specified string", () => { - const errors = validateDualPopInformationPM( - [], - undefined, - 0, - [DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for TestLabel` - ); - }); - - it("Error message text should match default errorMessage", () => { - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - "Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing" - ); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessageFunc = ( - _dualEligible: boolean, - errorReplacementText: string - ) => { - return `Another ${errorReplacementText} bites the dust`; - }; - - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined, - undefined, - errorMessageFunc - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - errorMessageFunc(true, "Age 65 and Older") - ); - }); -}); diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.ts deleted file mode 100644 index 18a57160e9..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateDualPopInformation/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as DC from "dataConstants"; -import { FormRateField } from "../types"; - -const validateDualPopInformationPMErrorMessage = ( - dualEligible: boolean, - errorReplacementText: string -) => { - if (!dualEligible) { - return `Information has been included in the ${errorReplacementText} Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing`; - } else { - return `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for ${errorReplacementText}`; - } -}; - -export const validateDualPopInformationPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - age65PlusIndex: number, - DefinitionOfDenominator: string[] | undefined, - errorReplacementText: string = "Age 65 and Older", - errorMessageFunc = validateDualPopInformationPMErrorMessage -) => { - if (OPM) { - return []; - } - - const dualEligible = DefinitionOfDenominator - ? DefinitionOfDenominator.indexOf( - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE - ) !== -1 - : false; - - const errorArray: FormError[] = []; - const filledInData: FormRateField[] = []; - performanceMeasureArray?.forEach((performanceMeasure) => { - if ( - performanceMeasure && - performanceMeasure[age65PlusIndex] && - performanceMeasure[age65PlusIndex].denominator && - performanceMeasure[age65PlusIndex].numerator && - performanceMeasure[age65PlusIndex].rate - ) { - filledInData.push(performanceMeasure[age65PlusIndex]); - } - }); - - if (!dualEligible && filledInData.length > 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - if (dualEligible && filledInData.length === 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - return errorArray; -}; diff --git a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx index 3069f378d3..528f1d25cb 100644 --- a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx @@ -2,7 +2,7 @@ import * as validateAtLeastOneDataSource from "shared/globalValidations/validate import * as validateAtLeastOneDeviationFieldFilled from "measures/2022/shared/globalValidations/validateAtLeastOneDeviationFieldFilled"; import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; -import * as validateDualPopInformation from "measures/2022/shared/globalValidations/validateDualPopInformation"; +import * as validateDualPopInformation from "shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateRateNotZero from "measures/2022/shared/globalValidations/validateRateNotZero"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts index 5c8eba40dd..2d750c10ed 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts @@ -10,7 +10,7 @@ export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; -export * from "./validateDualPopInformation"; +export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.test.ts b/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.test.ts deleted file mode 100644 index a7a289a2c9..0000000000 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as DC from "dataConstants"; -import { simpleRate, partialRate } from "utils/testUtils/validationHelpers"; -import { validateDualPopInformationPM } from "."; - -describe("Testing Dual Population Selection Validation", () => { - it("should be no errors", () => { - const errors = validateDualPopInformationPM([], undefined, 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - partial data", () => { - const errors = validateDualPopInformationPM( - [[partialRate, partialRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(0); - }); - - it("should be no errors - OPM", () => { - const errors = validateDualPopInformationPM([], [], 0, []); - - expect(errors.length).toBe(0); - }); - - it("should be errors for no checkbox selections", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [] - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no matching checkbox selection - specified string", () => { - const errors = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - [], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `Information has been included in the TestLabel Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing` - ); - }); - - it("should be errors for no data", () => { - const errors = validateDualPopInformationPM([], undefined, 0, [ - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE, - ]); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for Age 65 and Older` - ); - }); - - it("should be errors for no data - specified string", () => { - const errors = validateDualPopInformationPM( - [], - undefined, - 0, - [DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE], - "TestLabel" - ); - - expect(errors.length).toBe(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for TestLabel` - ); - }); - - it("Error message text should match default errorMessage", () => { - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - "Information has been included in the Age 65 and Older Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing" - ); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessageFunc = ( - _dualEligible: boolean, - errorReplacementText: string - ) => { - return `Another ${errorReplacementText} bites the dust`; - }; - - const errorArray = validateDualPopInformationPM( - [[simpleRate, simpleRate]], - undefined, - 0, - undefined, - undefined, - errorMessageFunc - ); - expect(errorArray.length).toBe(1); - expect(errorArray[0].errorMessage).toBe( - errorMessageFunc(true, "Age 65 and Older") - ); - }); -}); diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.ts deleted file mode 100644 index 18a57160e9..0000000000 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateDualPopInformation/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as DC from "dataConstants"; -import { FormRateField } from "../types"; - -const validateDualPopInformationPMErrorMessage = ( - dualEligible: boolean, - errorReplacementText: string -) => { - if (!dualEligible) { - return `Information has been included in the ${errorReplacementText} Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing`; - } else { - return `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for ${errorReplacementText}`; - } -}; - -export const validateDualPopInformationPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - age65PlusIndex: number, - DefinitionOfDenominator: string[] | undefined, - errorReplacementText: string = "Age 65 and Older", - errorMessageFunc = validateDualPopInformationPMErrorMessage -) => { - if (OPM) { - return []; - } - - const dualEligible = DefinitionOfDenominator - ? DefinitionOfDenominator.indexOf( - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE - ) !== -1 - : false; - - const errorArray: FormError[] = []; - const filledInData: FormRateField[] = []; - performanceMeasureArray?.forEach((performanceMeasure) => { - if ( - performanceMeasure && - performanceMeasure[age65PlusIndex] && - performanceMeasure[age65PlusIndex].denominator && - performanceMeasure[age65PlusIndex].numerator && - performanceMeasure[age65PlusIndex].rate - ) { - filledInData.push(performanceMeasure[age65PlusIndex]); - } - }); - - if (!dualEligible && filledInData.length > 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - if (dualEligible && filledInData.length === 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: errorMessageFunc(dualEligible, errorReplacementText), - errorType: "Warning", - }); - } - return errorArray; -}; diff --git a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx index b28e7c2294..08af6c0d91 100644 --- a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx @@ -5,7 +5,7 @@ import * as validateAtLeastOneDeliverySystem from "shared/globalValidations/vali import * as validateAtLeastOneDeviationFieldFilled from "measures/2023/shared/globalValidations/validateAtLeastOneDeviationFieldFilled"; import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; -import * as validateDualPopInformation from "measures/2023/shared/globalValidations/validateDualPopInformation"; +import * as validateDualPopInformation from "shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts index 0a19895558..8f04e494b3 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts @@ -11,7 +11,7 @@ export * from "./validateAtLeastOneDeviationFieldFilled"; export * from "shared/globalValidations/validateAtLeastOneRateComplete"; export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDateRangeRadioButtonCompletion"; -export * from "./validateDualPopInformation"; +export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.ts deleted file mode 100644 index 8696045a50..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as DC from "dataConstants"; -import { FormRateField } from "../types"; - -export const validateDualPopInformationPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - age65PlusIndex: number, - DefinitionOfDenominator: string[] | undefined, - errorReplacementText: string = "Age 65 and Older" -) => { - if (OPM) { - return []; - } - - const dualEligible = DefinitionOfDenominator - ? DefinitionOfDenominator.indexOf( - DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE - ) !== -1 - : false; - - const errorArray: FormError[] = []; - const filledInData: FormRateField[] = []; - performanceMeasureArray?.forEach((performanceMeasure) => { - if ( - performanceMeasure && - performanceMeasure[age65PlusIndex] && - performanceMeasure[age65PlusIndex].denominator && - performanceMeasure[age65PlusIndex].numerator && - performanceMeasure[age65PlusIndex].rate - ) { - filledInData.push(performanceMeasure[age65PlusIndex]); - } - }); - - if (dualEligible && filledInData.length === 0) { - errorArray.push({ - errorLocation: "Performance Measure", - errorMessage: `"Individuals Dually Eligible for Medicare and Medicaid" is selected in the "Definition of Denominator" question but you are missing performance measure data for ${errorReplacementText}`, - errorType: "Warning", - }); - } - return errorArray; -}; diff --git a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx index 0c798bdbaf..25f2d3f615 100644 --- a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx @@ -5,7 +5,7 @@ import * as validateAtLeastOneDeliverySystem from "shared/globalValidations/vali import * as validateAtLeastOneDeviationFieldFilled from "measures/2024/shared/globalValidations/validateAtLeastOneDeviationFieldFilled"; import * as validateAtLeastOneRateComplete from "shared/globalValidations/validateAtLeastOneRateComplete"; import * as validateBothDatesInRange from "shared/globalValidations/validateBothDatesInRange"; -import * as validateDualPopInformation from "measures/2024/shared/globalValidations/validateDualPopInformation"; +import * as validateDualPopInformation from "shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.test.ts b/services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.test.ts similarity index 100% rename from services/ui-src/src/measures/2024/shared/globalValidations/validateDualPopInformation/index.test.ts rename to services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.test.ts diff --git a/services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.ts b/services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.ts new file mode 100644 index 0000000000..30e2d0c56f --- /dev/null +++ b/services/ui-src/src/shared/globalValidations/validateDualPopInformation/index.ts @@ -0,0 +1,70 @@ +import * as DC from "dataConstants"; +import { FormRateField } from "shared/types/TypeValidations"; +import { getMeasureYear } from "utils/getMeasureYear"; + +export const getLabels = (year: number, errorReplacementText: string) => { + switch (year) { + case 2021: + case 2022: + case 2023: + return { + checkmarkWarning: `Information has been included in the ${errorReplacementText} Performance Measure but the checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is missing`, + missingDataWarning: `The checkmark for (Denominator Includes Medicare and Medicaid Dually-Eligible population) is checked but you are missing performance measure data for ${errorReplacementText}`, + }; + default: + return { + missingDataWarning: `"Individuals Dually Eligible for Medicare and Medicaid" is selected in the "Definition of Denominator" question but you are missing performance measure data for ${errorReplacementText}`, + }; + } +}; + +export const validateDualPopInformationPM = ( + performanceMeasureArray: FormRateField[][], + OPM: any, + age65PlusIndex: number, + DefinitionOfDenominator: string[] | undefined, + errorReplacementText: string = "Age 65 and Older" +) => { + if (OPM) { + return []; + } + + const year = getMeasureYear(); + const labels = getLabels(year, errorReplacementText); + + const dualEligible = DefinitionOfDenominator + ? DefinitionOfDenominator.indexOf( + DC.DENOMINATOR_INC_MEDICAID_DUAL_ELIGIBLE + ) !== -1 + : false; + + const errorArray: FormError[] = []; + const filledInData: FormRateField[] = []; + performanceMeasureArray?.forEach((performanceMeasure) => { + if ( + performanceMeasure && + performanceMeasure[age65PlusIndex] && + performanceMeasure[age65PlusIndex].denominator && + performanceMeasure[age65PlusIndex].numerator && + performanceMeasure[age65PlusIndex].rate + ) { + filledInData.push(performanceMeasure[age65PlusIndex]); + } + }); + + if (!dualEligible && filledInData.length > 0 && labels.checkmarkWarning) { + errorArray.push({ + errorLocation: "Performance Measure", + errorMessage: labels.checkmarkWarning, + errorType: "Warning", + }); + } + if (dualEligible && filledInData.length === 0 && labels.missingDataWarning) { + errorArray.push({ + errorLocation: "Performance Measure", + errorMessage: labels.missingDataWarning, + errorType: "Warning", + }); + } + return errorArray; +}; From bc43b73fc6f9c095f32e97c3a16c66d756a53c9a Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:59:31 -0400 Subject: [PATCH 4/7] GV Refactor - validateRateNotZero (#2444) --- .../ComplexAtLeastOneRateComplete/index.tsx | 66 ------- .../measures/2021/globalValidations/index.ts | 2 +- .../validateRateNotZero/index.test.ts | 171 ----------------- .../validateRateNotZero/index.ts | 80 -------- .../2022/shared/globalValidations/index.ts | 2 +- .../validateRateNotZero/index.test.ts | 172 ------------------ .../validateRateNotZero/index.ts | 79 -------- .../2022/shared/util/validationsMock.tsx | 2 +- .../2023/shared/globalValidations/index.ts | 2 +- .../validateRateNotZero/index.ts | 79 -------- .../2023/shared/util/validationsMock.tsx | 2 +- .../2024/shared/globalValidations/index.ts | 2 +- .../validateRateNotZero/index.test.ts | 167 ----------------- .../2024/shared/util/validationsMock.tsx | 2 +- .../validateRateNotZero/index.test.ts | 0 .../validateRateNotZero/index.ts | 2 +- 16 files changed, 8 insertions(+), 822 deletions(-) delete mode 100644 services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexAtLeastOneRateComplete/index.tsx delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.test.ts delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.test.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.ts delete mode 100644 services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.test.ts rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateRateNotZero/index.test.ts (100%) rename services/ui-src/src/{measures/2024 => }/shared/globalValidations/validateRateNotZero/index.ts (98%) diff --git a/services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexAtLeastOneRateComplete/index.tsx b/services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexAtLeastOneRateComplete/index.tsx deleted file mode 100644 index ab62cab4aa..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexAtLeastOneRateComplete/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { validatePartialRateCompletionPM } from "shared/globalValidations/validatePartialRateCompletion"; - -/* At least one NDR set must be complete (OPM or PM) */ -export const ComplexAtLeastOneRateComplete = ( - performanceMeasureArray: any, - OPM: any, - errorLocation: string = "Performance Measure/Other Performance Measure" -) => { - let error = true; - let partialError = false; - let errorArray: FormError[] = []; - - // Check OPM first - OPM && - OPM.forEach((measure: any) => { - if (measure?.rate && measure?.rate?.[0]?.rate) { - error = false; - } - }); - - // Check regular Performance Measures if cannot validate OPM - // For each Performance Measure - // Check that the performance measure has a field representation for each age groups - // Check that each field has a "value" and it is not an empty string - // For a complete measure the sum of the booleans will equal the length of the age groups - for (const category of performanceMeasureArray) { - for (const qualifier of category) { - const qualComplete = qualifier.fields.every( - (field: { value: string; label: string }) => { - return field.value !== undefined && field.value !== ""; - } - ); - if ( - !qualComplete && - qualifier.fields.some((field: { value?: string; label?: string }) => { - return !!(field?.value !== undefined && field?.value !== ""); - }) - ) { - partialError = true; - } - if (qualComplete) { - error = false; - } - } - } - - if (partialError) { - errorArray.push({ - errorLocation: errorLocation, - errorMessage: `Should not have partially filled data sets.`, - }); - } - - if (error) { - errorArray.push({ - errorLocation: errorLocation, - errorMessage: "At least one set of fields must be complete.", - }); - } - - if (OPM) { - errorArray.push(...validatePartialRateCompletionPM([], OPM, [])); - } - - return errorArray; -}; diff --git a/services/ui-src/src/measures/2021/globalValidations/index.ts b/services/ui-src/src/measures/2021/globalValidations/index.ts index 6b97e90379..45bff15fb1 100644 --- a/services/ui-src/src/measures/2021/globalValidations/index.ts +++ b/services/ui-src/src/measures/2021/globalValidations/index.ts @@ -9,7 +9,7 @@ export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; -export * from "./validateRateNotZero"; +export * from "shared/globalValidations/validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.test.ts b/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.test.ts deleted file mode 100644 index df76b4dfa5..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { LabelData } from "utils"; -import { validateRateNotZeroOMS, validateRateNotZeroPM } from "."; -import { - generateOmsQualifierRateData, - locationDictionary, - manualZeroRate, - manualNonZeroRate, - simpleRate, - partialRate, - generateOtherPerformanceMeasureData, -} from "utils/testUtils/validationHelpers"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Non-Zero/No Zero Numerator/Rate Validation", () => { - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateRateNotZeroPM( - [[simpleRate, simpleRate]], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have NO error for zero numerator but rate non-zero - Hybrid", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualNonZeroRate, - manualNonZeroRate, - manualNonZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error for zero rate but numerator non-zero", () => { - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should have error for zero rate but numerator non-zero - OPM", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualZeroRate, - manualZeroRate, - manualZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateRateNotZeroPM( - [ - [partialRate, partialRate], - [partialRate, partialRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers, - errorMessage - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should have error for zero numerator but rate non-zero", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS(errorMessage)({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.ts b/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.ts deleted file mode 100644 index 97903aa3c0..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateRateNotZero/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { - OmsValidationCallback, - FormRateField, - UnifiedValFuncProps as UVFP, -} from "../types"; -import { - convertOmsDataToRateArray, - getOtherPerformanceMeasureRateArray, -} from "../dataDrivenTools"; -import { LabelData } from "utils"; - -export const validationRateNotZero = ({ - location, - rateData, - errorMessage, -}: UVFP) => { - const errorArray: FormError[] = []; - - for (const ratefields of rateData) { - for (const rate of ratefields) { - if (rate && rate.denominator && rate.numerator && rate.rate) { - if ( - parseFloat(rate.numerator) > 0 && - parseFloat(rate.denominator) > 0 && - parseFloat(rate.rate) === 0 - ) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation.", - }); - } - } - } - } - - return errorArray; -}; - -export const validateRateNotZeroOMS = - (errorMessage?: string): OmsValidationCallback => - ({ categories, qualifiers, rateData, label, locationDictionary }) => { - return validationRateNotZero({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessage, - }).filter((v, i, a) => i === 0 || a[0].errorLocation !== v.errorLocation); - }; - -// If a user manually over-rides a rate it must not violate two rules: -// It Must be greater than zero if the Num and Denom are greater than zero -export const validateRateNotZeroPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - _qualifiers: LabelData[], - errorMessage?: string -) => { - const errorArray: FormError[] = []; - const location = `Performance Measure/Other Performance Measure`; - const rateDataOPM = getOtherPerformanceMeasureRateArray(OPM); - - const errors = [ - ...validationRateNotZero({ - location, - rateData: performanceMeasureArray, - errorMessage, - }), - ...validationRateNotZero({ - location, - rateData: rateDataOPM, - errorMessage, - }), - ]; - - if (!!errors.length) errorArray.push(errors[0]); - return errorArray; -}; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts index 6b97e90379..45bff15fb1 100644 --- a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts @@ -9,7 +9,7 @@ export * from "shared/globalValidations/validateBothDatesInRange"; export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; -export * from "./validateRateNotZero"; +export * from "shared/globalValidations/validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.test.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.test.ts deleted file mode 100644 index 90d2af0604..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { LabelData } from "utils"; -import { validateRateNotZeroOMS, validateRateNotZeroPM } from "."; -import { - generateOmsQualifierRateData, - locationDictionary, - manualZeroRate, - manualNonZeroRate, - simpleRate, - partialRate, - generateOtherPerformanceMeasureData, -} from "utils/testUtils/validationHelpers"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Non-Zero/No Zero Numerator/Rate Validation", () => { - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateRateNotZeroPM( - [[simpleRate, simpleRate]], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have NO error for zero numerator but rate non-zero - Hybrid", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualNonZeroRate, - manualNonZeroRate, - manualNonZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error for zero rate but numerator non-zero", () => { - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should have error for zero rate but numerator non-zero - OPM", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualZeroRate, - manualZeroRate, - manualZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateRateNotZeroPM( - [ - [partialRate, partialRate], - [partialRate, partialRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers, - errorMessage - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should have error for zero numerator but rate non-zero", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS(errorMessage)({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.ts deleted file mode 100644 index 0e6d6515b9..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateRateNotZero/index.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { - OmsValidationCallback, - FormRateField, - UnifiedValFuncProps as UVFP, -} from "../types"; -import { - convertOmsDataToRateArray, - getOtherPerformanceMeasureRateArray, -} from "../dataDrivenTools"; -import { LabelData } from "utils"; - -export const validationRateNotZero = ({ - location, - rateData, - errorMessage, -}: UVFP) => { - const errorArray: FormError[] = []; - - for (const ratefields of rateData) { - for (const rate of ratefields) { - if (rate && rate.denominator && rate.numerator && rate.rate) { - if ( - parseFloat(rate.numerator) > 0 && - parseFloat(rate.denominator) > 0 && - parseFloat(rate.rate) === 0 - ) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation.", - }); - } - } - } - } - - return errorArray; -}; - -export const validateRateNotZeroOMS = - (errorMessage?: string): OmsValidationCallback => - ({ categories, qualifiers, rateData, label, locationDictionary }) => { - return validationRateNotZero({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessage, - }).filter((v, i, a) => i === 0 || a[0].errorLocation !== v.errorLocation); - }; - -// If a user manually over-rides a rate it must not violate two rules: -// It must be zero if the numerator is zero -export const validateRateNotZeroPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - _qualifiers: LabelData[], - errorMessage?: string -) => { - const errorArray: FormError[] = []; - const location = `Performance Measure/Other Performance Measure`; - const rateDataOPM = getOtherPerformanceMeasureRateArray(OPM); - - const errors = [ - ...validationRateNotZero({ - location, - rateData: performanceMeasureArray, - errorMessage, - }), - ...validationRateNotZero({ - location, - rateData: rateDataOPM, - errorMessage, - }), - ]; - if (!!errors.length) errorArray.push(errors[0]); - return errorArray; -}; diff --git a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx index 528f1d25cb..4e8a79f46c 100644 --- a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx @@ -5,7 +5,7 @@ import * as validateBothDatesInRange from "shared/globalValidations/validateBoth import * as validateDualPopInformation from "shared/globalValidations/validateDualPopInformation"; import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; -import * as validateRateNotZero from "measures/2022/shared/globalValidations/validateRateNotZero"; +import * as validateRateNotZero from "shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2022/shared/globalValidations/validateRateZero"; import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts index 2d750c10ed..540968148a 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts @@ -14,7 +14,7 @@ export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; -export * from "./validateRateNotZero"; +export * from "shared/globalValidations/validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.ts deleted file mode 100644 index 0e6d6515b9..0000000000 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { - OmsValidationCallback, - FormRateField, - UnifiedValFuncProps as UVFP, -} from "../types"; -import { - convertOmsDataToRateArray, - getOtherPerformanceMeasureRateArray, -} from "../dataDrivenTools"; -import { LabelData } from "utils"; - -export const validationRateNotZero = ({ - location, - rateData, - errorMessage, -}: UVFP) => { - const errorArray: FormError[] = []; - - for (const ratefields of rateData) { - for (const rate of ratefields) { - if (rate && rate.denominator && rate.numerator && rate.rate) { - if ( - parseFloat(rate.numerator) > 0 && - parseFloat(rate.denominator) > 0 && - parseFloat(rate.rate) === 0 - ) { - errorArray.push({ - errorLocation: location, - errorMessage: - errorMessage ?? - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation.", - }); - } - } - } - } - - return errorArray; -}; - -export const validateRateNotZeroOMS = - (errorMessage?: string): OmsValidationCallback => - ({ categories, qualifiers, rateData, label, locationDictionary }) => { - return validationRateNotZero({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessage, - }).filter((v, i, a) => i === 0 || a[0].errorLocation !== v.errorLocation); - }; - -// If a user manually over-rides a rate it must not violate two rules: -// It must be zero if the numerator is zero -export const validateRateNotZeroPM = ( - performanceMeasureArray: FormRateField[][], - OPM: any, - _qualifiers: LabelData[], - errorMessage?: string -) => { - const errorArray: FormError[] = []; - const location = `Performance Measure/Other Performance Measure`; - const rateDataOPM = getOtherPerformanceMeasureRateArray(OPM); - - const errors = [ - ...validationRateNotZero({ - location, - rateData: performanceMeasureArray, - errorMessage, - }), - ...validationRateNotZero({ - location, - rateData: rateDataOPM, - errorMessage, - }), - ]; - if (!!errors.length) errorArray.push(errors[0]); - return errorArray; -}; diff --git a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx index 08af6c0d91..245a8a6e1e 100644 --- a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx @@ -9,7 +9,7 @@ import * as validateDualPopInformation from "shared/globalValidations/validateDu import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; -import * as validateRateNotZero from "measures/2023/shared/globalValidations/validateRateNotZero"; +import * as validateRateNotZero from "shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2023/shared/globalValidations/validateRateZero"; import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts index 8f04e494b3..132098e8ac 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts @@ -15,7 +15,7 @@ export * from "shared/globalValidations/validateDualPopInformation"; export * from "shared/globalValidations/validateEqualCategoryDenominators"; export * from "shared/globalValidations/validateEqualQualifierDenominators"; export * from "shared/globalValidations/validateFfsRadioButtonCompletion"; -export * from "./validateRateNotZero"; +export * from "shared/globalValidations/validateRateNotZero"; export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.test.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.test.ts deleted file mode 100644 index 50878bfeef..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.test.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { validateRateNotZeroOMS, validateRateNotZeroPM } from "."; -import { - generateOmsQualifierRateData, - locationDictionary, - manualZeroRate, - manualNonZeroRate, - simpleRate, - partialRate, - generateOtherPerformanceMeasureData, -} from "utils/testUtils/validationHelpers"; - -describe("Testing Non-Zero/No Zero Numerator/Rate Validation", () => { - const categories = [ - { label: "TestCat1", text: "TestCat1", id: "TestCat1" }, - { label: "TestCat2", text: "TestCat2", id: "TestCat2" }, - ]; - const qualifiers = [ - { label: "TestQual1", text: "TestQual1", id: "TestQual1" }, - { label: "TestQual2", text: "TestQual2", id: "TestQual2" }, - ]; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM/OPM Validation", () => { - it("should return NO errors", () => { - const errors = validateRateNotZeroPM( - [[simpleRate, simpleRate]], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have NO error for zero numerator but rate non-zero - Hybrid", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualNonZeroRate, - manualNonZeroRate, - manualNonZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("should have error for zero rate but numerator non-zero", () => { - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should have error for zero rate but numerator non-zero - OPM", () => { - const errors = validateRateNotZeroPM( - [], - generateOtherPerformanceMeasureData([ - manualZeroRate, - manualZeroRate, - manualZeroRate, - ]), - qualifiers - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - - it("should NOT have error from empty rate value", () => { - const errors = validateRateNotZeroPM( - [ - [partialRate, partialRate], - [partialRate, partialRate], - ], - undefined, - qualifiers - ); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const errors = validateRateNotZeroPM( - [ - [manualZeroRate, manualZeroRate], - [manualZeroRate, manualZeroRate], - ], - undefined, - qualifiers, - errorMessage - ); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe( - `Performance Measure/Other Performance Measure` - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should have error for zero numerator but rate non-zero", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe( - "Rate should not be 0 if numerator and denominator are not 0. If the calculated rate is less than 0.5, disregard this validation." - ); - }); - }); - - it("Error message text should match provided errorMessage", () => { - const errorMessage = "Another one bites the dust."; - const data = generateOmsQualifierRateData(categories, qualifiers, [ - manualZeroRate, - manualZeroRate, - ]); - const errors = validateRateNotZeroOMS(errorMessage)({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toContain( - "Optional Measure Stratification: TestLabel" - ); - expect(errors[0].errorMessage).toBe(errorMessage); - }); -}); diff --git a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx index 25f2d3f615..2621815aac 100644 --- a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx @@ -9,7 +9,7 @@ import * as validateDualPopInformation from "shared/globalValidations/validateDu import * as validateEqualCategoryDenominators from "shared/globalValidations/validateEqualCategoryDenominators"; import * as validateEqualQualifierDenominators from "shared/globalValidations/validateEqualQualifierDenominators"; import * as validateFfsRadioButtonCompletion from "shared/globalValidations/validateFfsRadioButtonCompletion"; -import * as validateRateNotZero from "measures/2024/shared/globalValidations/validateRateNotZero"; +import * as validateRateNotZero from "shared/globalValidations/validateRateNotZero"; import * as validateRateZero from "measures/2024/shared/globalValidations/validateRateZero"; import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.test.ts b/services/ui-src/src/shared/globalValidations/validateRateNotZero/index.test.ts similarity index 100% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateRateNotZero/index.test.ts rename to services/ui-src/src/shared/globalValidations/validateRateNotZero/index.test.ts diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.ts b/services/ui-src/src/shared/globalValidations/validateRateNotZero/index.ts similarity index 98% rename from services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.ts rename to services/ui-src/src/shared/globalValidations/validateRateNotZero/index.ts index 0e6d6515b9..b8c09fc4e7 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateRateNotZero/index.ts +++ b/services/ui-src/src/shared/globalValidations/validateRateNotZero/index.ts @@ -2,7 +2,7 @@ import { OmsValidationCallback, FormRateField, UnifiedValFuncProps as UVFP, -} from "../types"; +} from "../../types/TypeValidations"; import { convertOmsDataToRateArray, getOtherPerformanceMeasureRateArray, From 94aa4dea0e261c634118714104955a0d914a5226 Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:00:06 -0400 Subject: [PATCH 5/7] GV Refactor - validateOneQualRateHigherThanOtherQual (#2441) --- .../measures/2021/globalValidations/index.ts | 2 +- .../index.test.ts | 223 ------------------ .../index.ts | 127 ---------- .../2022/shared/globalValidations/index.ts | 2 +- .../index.test.ts | 223 ------------------ .../index.ts | 127 ---------- .../2022/shared/util/validationsMock.tsx | 2 +- .../2023/shared/globalValidations/index.ts | 2 +- .../2023/shared/util/validationsMock.tsx | 2 +- .../2024/shared/globalValidations/index.ts | 2 +- .../index.test.ts | 215 ----------------- .../index.ts | 129 ---------- .../2024/shared/util/validationsMock.tsx | 2 +- .../index.test.ts | 0 .../index.ts | 5 +- 15 files changed, 11 insertions(+), 1052 deletions(-) delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts delete mode 100644 services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts delete mode 100644 services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts (100%) rename services/ui-src/src/{measures/2023 => }/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts (97%) diff --git a/services/ui-src/src/measures/2021/globalValidations/index.ts b/services/ui-src/src/measures/2021/globalValidations/index.ts index 45bff15fb1..afd1a9fed1 100644 --- a/services/ui-src/src/measures/2021/globalValidations/index.ts +++ b/services/ui-src/src/measures/2021/globalValidations/index.ts @@ -14,7 +14,7 @@ export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; export * from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -export * from "./validateOneQualRateHigherThanOtherQual"; +export * from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; export * from "shared/globalValidations/validateReasonForNotReporting"; export * from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; export * from "./validateTotals"; diff --git a/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts b/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts deleted file mode 100644 index 1ba3438ec5..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { SINGLE_CATEGORY } from "dataConstants"; -import { - validateOneQualRateHigherThanOtherQualOMS, - validateOneQualRateHigherThanOtherQualPM, -} from "."; - -import { - generatePmQualifierRateData, - generateOmsQualifierRateData, - locationDictionary, - higherRate, - lowerRate, - partialRate, -} from "utils/testUtils/validationHelpers"; -import { LabelData } from "utils"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Qualifier Rate Higher Than Other Validation", () => { - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - const singleCat: LabelData[] = [ - { - label: SINGLE_CATEGORY, - text: SINGLE_CATEGORY, - id: SINGLE_CATEGORY, - }, - ]; - const noCat: LabelData[] = []; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM Validation", () => { - it("should return no errors", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate within ${categories[0].label}.` - ); - }); - - it("should have error - single category", () => { - const data = generatePmQualifierRateData( - { categories: noCat, qualifiers }, - [lowerRate, higherRate] - ); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories: noCat, - qualifiers, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate.` - ); - }); - - it("should NOT have error from empty rate value ", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - partialRate, - partialRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM( - data, - { - categories, - qualifiers, - }, - undefined, - undefined, - errorMessageFunc - ); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - categories[0].label - ) - ); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return no errors", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return with no error - isOPM", () => { - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: {}, - isOPM: true, - }); - expect(errors).toHaveLength(0); - }); - - it("should not show last string portion when OMS has no categories", () => { - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - `${qualifiers?.[1].label} rate must be less than or equal to ${qualifiers?.[0].label} rate.` - ); - }); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS( - undefined, - undefined, - errorMessageFunc - )({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - singleCat[0].label - ) - ); - }); -}); diff --git a/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts b/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts deleted file mode 100644 index 7f4da0d18c..0000000000 --- a/services/ui-src/src/measures/2021/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts +++ /dev/null @@ -1,127 +0,0 @@ -import * as Types from "shared/types"; -import * as DC from "dataConstants"; -import { OmsValidationCallback, UnifiedValFuncProps as UVFP } from "../types"; -import { - getPerfMeasureRateArray, - convertOmsDataToRateArray, -} from "../dataDrivenTools"; - -type ErrorMessageFunc = ( - lowQual: string, - highQual: string, - singleCategoryCheck: boolean, - category: string -) => string; - -interface ValProps extends UVFP { - lowerIndex: number; - higherIndex: number; - errorMessageFunc?: ErrorMessageFunc; -} - -const validateOneQualRateHigherThanOtherQualErrorMessage: ErrorMessageFunc = ( - lowQual: string, - highQual: string, - notSingleCategory: boolean, - category: string -) => { - return `${lowQual} rate must be less than or equal to ${highQual} rate${ - notSingleCategory ? ` within ${category}` : "" - }.`; -}; - -const _validation = ({ - categories, - location, - qualifiers, - rateData, - higherIndex, - lowerIndex, - errorMessageFunc = validateOneQualRateHigherThanOtherQualErrorMessage, -}: ValProps) => { - const errorArray: FormError[] = []; - - for (const [i, ratefields] of rateData.entries()) { - if ( - ratefields?.length >= 2 && - parseFloat(ratefields[lowerIndex]?.rate ?? "") > - parseFloat(ratefields[higherIndex]?.rate ?? "") - ) { - const notSingleCategory: boolean = - categories?.length && categories[0].label !== DC.SINGLE_CATEGORY - ? true - : false; - errorArray.push({ - errorLocation: location, - errorMessage: errorMessageFunc( - qualifiers?.[lowerIndex]?.label!, - qualifiers?.[higherIndex]?.label!, - notSingleCategory, - categories?.[i]?.label! - ), - }); - } - } - return errorArray; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * @note this function returns the oms validation function - * - * - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualOMS = ( - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -): OmsValidationCallback => { - return ({ - rateData, - categories, - qualifiers, - label, - locationDictionary, - isOPM, - }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - higherIndex, - lowerIndex, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessageFunc, - }); - }; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * - * @param data form data - * @param performanceMeasureData data driven information - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualPM = ( - data: Types.PerformanceMeasure, - performanceMeasureData: Types.DataDrivenTypes.PerformanceMeasure, - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -) => { - const perfMeasure = getPerfMeasureRateArray(data, performanceMeasureData); - return _validation({ - categories: performanceMeasureData.categories, - qualifiers: performanceMeasureData.qualifiers, - higherIndex, - lowerIndex, - rateData: perfMeasure, - location: "Performance Measure", - errorMessageFunc, - }); -}; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts index 45bff15fb1..afd1a9fed1 100644 --- a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts @@ -14,7 +14,7 @@ export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; export * from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -export * from "./validateOneQualRateHigherThanOtherQual"; +export * from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; export * from "shared/globalValidations/validateReasonForNotReporting"; export * from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; export * from "./validateTotals"; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts deleted file mode 100644 index 1ba3438ec5..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts +++ /dev/null @@ -1,223 +0,0 @@ -import { SINGLE_CATEGORY } from "dataConstants"; -import { - validateOneQualRateHigherThanOtherQualOMS, - validateOneQualRateHigherThanOtherQualPM, -} from "."; - -import { - generatePmQualifierRateData, - generateOmsQualifierRateData, - locationDictionary, - higherRate, - lowerRate, - partialRate, -} from "utils/testUtils/validationHelpers"; -import { LabelData } from "utils"; - -jest.mock("utils/getLabelText", () => ({ - isLegacyLabel: () => true, -})); - -describe("Testing Qualifier Rate Higher Than Other Validation", () => { - const categories: LabelData[] = [ - { id: "Test Cat 1", label: "Test Cat 1", text: "Test Cat 1" }, - { id: "Test Cat 2", label: "Test Cat 2", text: "Test Cat 2" }, - ]; - const qualifiers: LabelData[] = [ - { id: "Test Qual 1", label: "Test Qual 1", text: "Test Qual 1" }, - { id: "Test Qual 2", label: "Test Qual 2", text: "Test Qual 2" }, - ]; - const singleCat: LabelData[] = [ - { - label: SINGLE_CATEGORY, - text: SINGLE_CATEGORY, - id: SINGLE_CATEGORY, - }, - ]; - const noCat: LabelData[] = []; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM Validation", () => { - it("should return no errors", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate within ${categories[0].label}.` - ); - }); - - it("should have error - single category", () => { - const data = generatePmQualifierRateData( - { categories: noCat, qualifiers }, - [lowerRate, higherRate] - ); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories: noCat, - qualifiers, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate.` - ); - }); - - it("should NOT have error from empty rate value ", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - partialRate, - partialRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM( - data, - { - categories, - qualifiers, - }, - undefined, - undefined, - errorMessageFunc - ); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - categories[0].label - ) - ); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return no errors", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return with no error - isOPM", () => { - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: {}, - isOPM: true, - }); - expect(errors).toHaveLength(0); - }); - - it("should not show last string portion when OMS has no categories", () => { - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - `${qualifiers?.[1].label} rate must be less than or equal to ${qualifiers?.[0].label} rate.` - ); - }); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS( - undefined, - undefined, - errorMessageFunc - )({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - singleCat[0].label - ) - ); - }); -}); diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts deleted file mode 100644 index 7f4da0d18c..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts +++ /dev/null @@ -1,127 +0,0 @@ -import * as Types from "shared/types"; -import * as DC from "dataConstants"; -import { OmsValidationCallback, UnifiedValFuncProps as UVFP } from "../types"; -import { - getPerfMeasureRateArray, - convertOmsDataToRateArray, -} from "../dataDrivenTools"; - -type ErrorMessageFunc = ( - lowQual: string, - highQual: string, - singleCategoryCheck: boolean, - category: string -) => string; - -interface ValProps extends UVFP { - lowerIndex: number; - higherIndex: number; - errorMessageFunc?: ErrorMessageFunc; -} - -const validateOneQualRateHigherThanOtherQualErrorMessage: ErrorMessageFunc = ( - lowQual: string, - highQual: string, - notSingleCategory: boolean, - category: string -) => { - return `${lowQual} rate must be less than or equal to ${highQual} rate${ - notSingleCategory ? ` within ${category}` : "" - }.`; -}; - -const _validation = ({ - categories, - location, - qualifiers, - rateData, - higherIndex, - lowerIndex, - errorMessageFunc = validateOneQualRateHigherThanOtherQualErrorMessage, -}: ValProps) => { - const errorArray: FormError[] = []; - - for (const [i, ratefields] of rateData.entries()) { - if ( - ratefields?.length >= 2 && - parseFloat(ratefields[lowerIndex]?.rate ?? "") > - parseFloat(ratefields[higherIndex]?.rate ?? "") - ) { - const notSingleCategory: boolean = - categories?.length && categories[0].label !== DC.SINGLE_CATEGORY - ? true - : false; - errorArray.push({ - errorLocation: location, - errorMessage: errorMessageFunc( - qualifiers?.[lowerIndex]?.label!, - qualifiers?.[higherIndex]?.label!, - notSingleCategory, - categories?.[i]?.label! - ), - }); - } - } - return errorArray; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * @note this function returns the oms validation function - * - * - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualOMS = ( - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -): OmsValidationCallback => { - return ({ - rateData, - categories, - qualifiers, - label, - locationDictionary, - isOPM, - }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - higherIndex, - lowerIndex, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessageFunc, - }); - }; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * - * @param data form data - * @param performanceMeasureData data driven information - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualPM = ( - data: Types.PerformanceMeasure, - performanceMeasureData: Types.DataDrivenTypes.PerformanceMeasure, - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -) => { - const perfMeasure = getPerfMeasureRateArray(data, performanceMeasureData); - return _validation({ - categories: performanceMeasureData.categories, - qualifiers: performanceMeasureData.qualifiers, - higherIndex, - lowerIndex, - rateData: perfMeasure, - location: "Performance Measure", - errorMessageFunc, - }); -}; diff --git a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx index 4e8a79f46c..edc32a57e4 100644 --- a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx @@ -10,7 +10,7 @@ import * as validateRateZero from "measures/2022/shared/globalValidations/valida import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; import * as validateOneQualDenomHigherThanOtherDenomOMS from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -import * as validateOneQualRateHigherThanOtherQual from "measures/2022/shared/globalValidations/validateOneQualRateHigherThanOtherQual"; +import * as validateOneQualRateHigherThanOtherQual from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; import * as validateReasonForNotReporting from "shared/globalValidations/validateReasonForNotReporting"; import * as validateRequiredRadioButtonForCombinedRates from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; import * as validateTotals from "measures/2022/shared/globalValidations/validateTotals"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts index 540968148a..265833d4b3 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2023/shared/globalValidations/index.ts @@ -19,7 +19,7 @@ export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; export * from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -export * from "./validateOneQualRateHigherThanOtherQual"; +export * from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; export * from "shared/globalValidations/validateReasonForNotReporting"; export * from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; export * from "./validateTotals"; diff --git a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx index 245a8a6e1e..5fea6d58e6 100644 --- a/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2023/shared/util/validationsMock.tsx @@ -14,7 +14,7 @@ import * as validateRateZero from "measures/2023/shared/globalValidations/valida import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; import * as validateOneQualDenomHigherThanOtherDenomOMS from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -import * as validateOneQualRateHigherThanOtherQual from "measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual"; +import * as validateOneQualRateHigherThanOtherQual from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; import * as validateReasonForNotReporting from "shared/globalValidations/validateReasonForNotReporting"; import * as validateRequiredRadioButtonForCombinedRates from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; import * as validateTotals from "measures/2023/shared/globalValidations/validateTotals"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts index 132098e8ac..ee3f16292d 100644 --- a/services/ui-src/src/measures/2024/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2024/shared/globalValidations/index.ts @@ -20,7 +20,7 @@ export * from "./validateRateZero"; export * from "shared/globalValidations/validateNumeratorsLessThanDenominators"; export * from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; export * from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -export * from "./validateOneQualRateHigherThanOtherQual"; +export * from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; export * from "shared/globalValidations/validateReasonForNotReporting"; export * from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; export * from "./validateTotals"; diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts deleted file mode 100644 index 3bfd7d9cee..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { SINGLE_CATEGORY } from "dataConstants"; -import { - validateOneQualRateHigherThanOtherQualOMS, - validateOneQualRateHigherThanOtherQualPM, -} from "."; - -import { - generatePmQualifierRateData, - generateOmsQualifierRateData, - locationDictionary, - higherRate, - lowerRate, - partialRate, -} from "utils/testUtils/validationHelpers"; -import { LabelData } from "utils"; - -describe("Testing Qualifier Rate Higher Than Other Validation", () => { - const categories = [ - { label: "Test Cat 1", text: "Test Cat 1", id: "Test Cat 1" }, - { label: "Test Cat 2", text: "Test Cat 2", id: "Test Cat 2" }, - ]; - const qualifiers = [ - { label: "Test Qual 1", text: "Test Qual 1", id: "Test Qual 1" }, - { label: "Test Qual 2", text: "Test Qual 2", id: "Test Qual 2" }, - ]; - const singleCat = [ - { label: SINGLE_CATEGORY, text: SINGLE_CATEGORY, id: SINGLE_CATEGORY }, - ]; - const noCat: LabelData[] = []; - - const baseOMSInfo = { - categories, - qualifiers, - locationDictionary, - isOPM: false, - label: ["TestLabel"], - }; - - // PM - describe("PM Validation", () => { - it("should return no errors", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("should have error", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate within ${categories[0].label}.` - ); - }); - - it("should have error - single category", () => { - const data = generatePmQualifierRateData( - { categories: noCat, qualifiers }, - [lowerRate, higherRate] - ); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories: noCat, - qualifiers, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - `${qualifiers[1].label} rate must be less than or equal to ${qualifiers[0].label} rate.` - ); - }); - - it("should NOT have error from empty rate value ", () => { - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - partialRate, - partialRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM(data, { - categories, - qualifiers, - }); - - expect(errors).toHaveLength(0); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generatePmQualifierRateData({ categories, qualifiers }, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualPM( - data, - { - categories, - qualifiers, - }, - undefined, - undefined, - errorMessageFunc - ); - - expect(errors).toHaveLength(2); - expect(errors[0].errorLocation).toBe("Performance Measure"); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - categories[0].label - ) - ); - }); - }); - - // OMS - describe("OMS Validation", () => { - it("should return no errors", () => { - const data = generateOmsQualifierRateData(categories, qualifiers, [ - higherRate, - lowerRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: data, - }); - - expect(errors).toHaveLength(0); - }); - - it("should return with no error - isOPM", () => { - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - rateData: {}, - isOPM: true, - }); - expect(errors).toHaveLength(0); - }); - - it("should not show last string portion when OMS has no categories", () => { - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS()({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - `${qualifiers?.[1].label} rate must be less than or equal to ${qualifiers?.[0].label} rate.` - ); - }); - }); - - it("Error message text should match provided errorMessageFunc", () => { - const errorMessageFunc = ( - lowQual: string, - highQual: string, - _notSingleCategory: boolean, - category: string - ) => { - return `Another ${lowQual} bites the ${highQual} and the ${category}.`; - }; - - const data = generateOmsQualifierRateData(singleCat, qualifiers, [ - lowerRate, - higherRate, - ]); - const errors = validateOneQualRateHigherThanOtherQualOMS( - undefined, - undefined, - errorMessageFunc - )({ - ...baseOMSInfo, - categories: singleCat, - rateData: data, - }); - - expect(errors).toHaveLength(1); - expect(errors[0].errorMessage).toBe( - errorMessageFunc( - qualifiers[1].label, - qualifiers[0].label, - false, - singleCat[0].label - ) - ); - }); -}); diff --git a/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts b/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts deleted file mode 100644 index 9d689172cc..0000000000 --- a/services/ui-src/src/measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts +++ /dev/null @@ -1,129 +0,0 @@ -import * as Types from "shared/types"; -import * as DC from "dataConstants"; -import { OmsValidationCallback, UnifiedValFuncProps as UVFP } from "../types"; -import { - getPerfMeasureRateArray, - convertOmsDataToRateArray, -} from "../dataDrivenTools"; - -type ErrorMessageFunc = ( - lowQual: string, - highQual: string, - singleCategoryCheck: boolean, - category: string -) => string; - -interface ValProps extends UVFP { - lowerIndex: number; - higherIndex: number; - errorMessageFunc?: ErrorMessageFunc; -} - -const validateOneQualRateHigherThanOtherQualErrorMessage: ErrorMessageFunc = ( - lowQual: string, - highQual: string, - notSingleCategory: boolean, - category: string -) => { - return `${lowQual} rate must be less than or equal to ${highQual} rate${ - notSingleCategory ? ` within ${category}` : "" - }.`; -}; - -const _validation = ({ - categories, - location, - qualifiers, - rateData, - higherIndex, - lowerIndex, - errorMessageFunc = validateOneQualRateHigherThanOtherQualErrorMessage, -}: ValProps) => { - const errorArray: FormError[] = []; - - for (const [i, ratefields] of rateData.entries()) { - if ( - ratefields?.length >= 2 && - parseFloat(ratefields[lowerIndex]?.rate ?? "") > - parseFloat(ratefields[higherIndex]?.rate ?? "") - ) { - const notSingleCategory: boolean = - categories?.length && - categories[0].label !== DC.SINGLE_CATEGORY && - categories[0].label - ? true - : false; - errorArray.push({ - errorLocation: location, - errorMessage: errorMessageFunc( - qualifiers?.[lowerIndex]?.label!, - qualifiers?.[higherIndex]?.label!, - notSingleCategory, - categories?.[i]?.label! - ), - }); - } - } - return errorArray; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * @note this function returns the oms validation function - * - * - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualOMS = ( - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -): OmsValidationCallback => { - return ({ - rateData, - categories, - qualifiers, - label, - locationDictionary, - isOPM, - }) => { - if (isOPM) return []; - return _validation({ - categories, - qualifiers, - location: `Optional Measure Stratification: ${locationDictionary(label)}`, - higherIndex, - lowerIndex, - rateData: convertOmsDataToRateArray(categories, qualifiers, rateData), - errorMessageFunc, - }); - }; -}; - -/** - * Validates that one qualifier's rate is higher than the other specified qualifier's rate - * - * @param data form data - * @param performanceMeasureData data driven information - * @param higherIndex which qualifier index should have the higher rate - * @param lowerIndex which qualifier index should have the lower rate - */ -export const validateOneQualRateHigherThanOtherQualPM = ( - data: Types.PerformanceMeasure, - performanceMeasureData: Types.DataDrivenTypes.PerformanceMeasure, - higherIndex = 0, - lowerIndex = 1, - errorMessageFunc?: ErrorMessageFunc -) => { - const perfMeasure = getPerfMeasureRateArray(data, performanceMeasureData); - return _validation({ - categories: performanceMeasureData.categories, - qualifiers: performanceMeasureData.qualifiers, - higherIndex, - lowerIndex, - rateData: perfMeasure, - location: "Performance Measure", - errorMessageFunc, - }); -}; diff --git a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx index 2621815aac..01f745bfba 100644 --- a/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2024/shared/util/validationsMock.tsx @@ -14,7 +14,7 @@ import * as validateRateZero from "measures/2024/shared/globalValidations/valida import * as validateNumeratorsLessThanDenominators from "shared/globalValidations/validateNumeratorsLessThanDenominators"; import * as validateOneCatRateHigherThanOtherCat from "shared/globalValidations/validateOneCatRateHigherThanOtherCat"; import * as validateOneQualDenomHigherThanOtherDenomOMS from "shared/globalValidations/validateOneQualDenomHigherThanOtherDenomOMS"; -import * as validateOneQualRateHigherThanOtherQual from "measures/2024/shared/globalValidations/validateOneQualRateHigherThanOtherQual"; +import * as validateOneQualRateHigherThanOtherQual from "shared/globalValidations/validateOneQualRateHigherThanOtherQual"; import * as validateReasonForNotReporting from "shared/globalValidations/validateReasonForNotReporting"; import * as validateRequiredRadioButtonForCombinedRates from "shared/globalValidations/validateRequiredRadioButtonForCombinedRates"; import * as validateTotals from "measures/2024/shared/globalValidations/validateTotals"; diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts b/services/ui-src/src/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts similarity index 100% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts rename to services/ui-src/src/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.test.ts diff --git a/services/ui-src/src/measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts b/services/ui-src/src/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts similarity index 97% rename from services/ui-src/src/measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts rename to services/ui-src/src/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts index 9d689172cc..0b044e3f0c 100644 --- a/services/ui-src/src/measures/2023/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts +++ b/services/ui-src/src/shared/globalValidations/validateOneQualRateHigherThanOtherQual/index.ts @@ -1,6 +1,9 @@ import * as Types from "shared/types"; import * as DC from "dataConstants"; -import { OmsValidationCallback, UnifiedValFuncProps as UVFP } from "../types"; +import { + OmsValidationCallback, + UnifiedValFuncProps as UVFP, +} from "../../types/TypeValidations"; import { getPerfMeasureRateArray, convertOmsDataToRateArray, From d6b75fab91f7332d6ac684e2f5f334bccb528c2b Mon Sep 17 00:00:00 2001 From: ailZhou <127151429+ailZhou@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:34:02 -0400 Subject: [PATCH 6/7] GV Refactor - ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec (#2432) --- .../measures/2021/globalValidations/index.ts | 2 +- .../index.tsx | 60 ------------------- .../2022/shared/globalValidations/index.ts | 2 +- .../2022/shared/util/validationsMock.tsx | 2 +- .../index.tsx | 0 5 files changed, 3 insertions(+), 63 deletions(-) delete mode 100644 services/ui-src/src/measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx rename services/ui-src/src/{measures/2021 => shared}/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx (100%) diff --git a/services/ui-src/src/measures/2021/globalValidations/index.ts b/services/ui-src/src/measures/2021/globalValidations/index.ts index afd1a9fed1..7c50edca4a 100644 --- a/services/ui-src/src/measures/2021/globalValidations/index.ts +++ b/services/ui-src/src/measures/2021/globalValidations/index.ts @@ -31,7 +31,7 @@ export { ComplexNoNonZeroNumOrDenom, ComplexNoNonZeroNumOrDenomOMS, } from "./ComplexValidations/ComplexNoNonZeroNumOrDenom"; -export { ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec } from "./ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; +export { ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec } from "shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; //pragma: allowlist secret export { ComplexValidateNDRTotals, ComplexValidateNDRTotalsOMS, diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx b/services/ui-src/src/measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx deleted file mode 100644 index 1c59925b0c..0000000000 --- a/services/ui-src/src/measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as Types from "shared/types"; - -interface NDRforumla { - numerator: number; - denominator: number; - rateIndex: number; -} - -/* - * If the user indicates that there is a deviation from the measure spec, they must - * indicate where the deviation is. - */ -export const ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec = ( - performanceMeasureArray: any, - ndrFormulas: NDRforumla[], - deviationArray: Types.DeviationFields[] | any, - didCalculationsDeviate: boolean -) => { - let errorArray: FormError[] = []; - let oneRateComplete = false; - - if (didCalculationsDeviate) { - for (const category of performanceMeasureArray) { - if (oneRateComplete) break; - for (const qualifier of category) { - if (oneRateComplete) break; - for (const formula of ndrFormulas) { - const numerator = qualifier.fields[formula.numerator]?.value; - const denominator = qualifier.fields[formula.denominator]?.value; - const rate = qualifier.fields[formula.rateIndex]?.value; - - if (![numerator, denominator, rate].includes("")) { - oneRateComplete = true; - break; - } - } - } - } - - if (oneRateComplete) { - const atLeastOneDevNDR = deviationArray?.some((deviationNDR: any) => { - return ( - deviationNDR?.denominator || - deviationNDR?.numerator || - deviationNDR?.other - ); - }); - - if (!atLeastOneDevNDR) { - errorArray.push({ - errorLocation: "Deviations from Measure Specifications", - errorMessage: - "At least one item must be selected and completed (Numerator, Denominator, or Other)", - }); - } - } - } - - return errorArray; -}; diff --git a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts index afd1a9fed1..7c50edca4a 100644 --- a/services/ui-src/src/measures/2022/shared/globalValidations/index.ts +++ b/services/ui-src/src/measures/2022/shared/globalValidations/index.ts @@ -31,7 +31,7 @@ export { ComplexNoNonZeroNumOrDenom, ComplexNoNonZeroNumOrDenomOMS, } from "./ComplexValidations/ComplexNoNonZeroNumOrDenom"; -export { ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec } from "./ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; +export { ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec } from "shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; //pragma: allowlist secret export { ComplexValidateNDRTotals, ComplexValidateNDRTotalsOMS, diff --git a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx index edc32a57e4..dd4ad98a1b 100644 --- a/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx +++ b/services/ui-src/src/measures/2022/shared/util/validationsMock.tsx @@ -19,7 +19,7 @@ import * as PCRnoNonZeroNumOrDenom from "shared/globalValidations/PCRValidations import * as PCRvalidateAtLeastOneNDRInDeviationOfMeasureSpec from "shared/globalValidations/PCRValidations/PCRvalidateAtLeastOneNDRInDeviationOfMeasureSpec"; //pragma: allowlist secret import * as ComplexAtLeastOneRateComplete from "shared/globalValidations/ComplexValidations/ComplexAtLeastOneRateComplete"; import * as ComplexNoNonZeroNumOrDenom from "measures/2022/shared/globalValidations/ComplexValidations/ComplexNoNonZeroNumOrDenom"; -import * as ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec from "measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; //pragma: allowlist secret +import * as ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec from "shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec"; //pragma: allowlist secret import * as ComplexValidateNDRTotals from "measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateNDRTotals"; import * as ComplexValidateDualPopInformation from "measures/2022/shared/globalValidations/ComplexValidations/ComplexValidateDualPopInformation"; import * as ComplexValueSameCrossCategory from "measures/2022/shared/globalValidations/ComplexValidations/ComplexValueSameCrossCategory"; diff --git a/services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx b/services/ui-src/src/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx similarity index 100% rename from services/ui-src/src/measures/2021/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx rename to services/ui-src/src/shared/globalValidations/ComplexValidations/ComplexValidateAtLeastOneNDRInDeviationOfMeasureSpec/index.tsx From 7024b16aadcf210d1fa2430d3b3552f26c2fad5f Mon Sep 17 00:00:00 2001 From: Garrett Rabian <57802560+gmrabian@users.noreply.github.com> Date: Fri, 20 Sep 2024 09:24:42 -0400 Subject: [PATCH 7/7] update macfc security hub github action (#2447) --- .github/workflows/scan_security-hub-jira-integration.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scan_security-hub-jira-integration.yml b/.github/workflows/scan_security-hub-jira-integration.yml index 5f8001001c..e7ede6ba41 100644 --- a/.github/workflows/scan_security-hub-jira-integration.yml +++ b/.github/workflows/scan_security-hub-jira-integration.yml @@ -21,13 +21,12 @@ jobs: aws-region: ${{ secrets.AWS_DEFAULT_REGION }} role-to-assume: ${{ secrets.PRODUCTION_SYNC_OIDC_ROLE }} - name: Sync Security Hub and Jira - uses: Enterprise-CMCS/mac-fc-security-hub-visibility@v1.0.5 + uses: Enterprise-CMCS/mac-fc-security-hub-visibility@v2.0.9 with: jira-username: "mdct_github_service_account" jira-token: ${{ secrets.JIRA_ENT_USER_TOKEN }} - jira-host: jiraent.cms.gov jira-project-key: CMDCT jira-ignore-statuses: Done, Closed, Canceled jira-custom-fields: '{ "customfield_10100": "CMDCT-2280", "customfield_26700" : [{"id": "40103", "value": "QMR"}] }' aws-severities: CRITICAL, HIGH, MEDIUM - assign-jira-ticket-to: "MWTW" + jira-assignee: "MWTW"