From b35344d4ddfb3e8bf370fa6a11e17d6e2ad3acb8 Mon Sep 17 00:00:00 2001 From: sb-cecilialiu Date: Mon, 18 Nov 2024 11:14:01 -0600 Subject: [PATCH 1/5] MAT-7915 resolve execution result difference in list page and test case edit page --- src/api/CalculationService.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/api/CalculationService.ts b/src/api/CalculationService.ts index bcdd20c4..88f75062 100644 --- a/src/api/CalculationService.ts +++ b/src/api/CalculationService.ts @@ -312,9 +312,16 @@ export class CalculationService { } // verify stratification & stratified populations passing if they exist if (groupPopulation.stratificationValues) { - return groupPopulation.stratificationValues.every((strata) => { + let validStratPopValues = []; + groupPopulation.stratificationValues.forEach((stratValues) => { + const filtered = stratValues.populationValues?.filter( + (populationValue) => populationValue.expected !== null + ); + validStratPopValues.push(filtered); + }); + return validStratPopValues.every((strata) => { // verify stratified populations passing - return strata.populationValues.every((population) => + return strata.every((population) => this.isValuePass( population.actual, population.expected, From db04d01c16c64ac5110db76029489b042c394a25 Mon Sep 17 00:00:00 2001 From: sb-cecilialiu Date: Mon, 18 Nov 2024 11:29:40 -0600 Subject: [PATCH 2/5] MAT-7915 fix vulnerability issue --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4b3c5cd..3ebf96c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8026,9 +8026,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", From 982d9738521fe316706d2762b5726e10a4c177a7 Mon Sep 17 00:00:00 2001 From: sb-cecilialiu Date: Mon, 18 Nov 2024 13:23:53 -0600 Subject: [PATCH 3/5] MAT-7915 filtering out invalid strat population values --- src/api/CalculationService.ts | 45 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/api/CalculationService.ts b/src/api/CalculationService.ts index 88f75062..ee1ee08f 100644 --- a/src/api/CalculationService.ts +++ b/src/api/CalculationService.ts @@ -12,6 +12,7 @@ import { Population, PopulationExpectedValue, TestCase, + StratificationExpectedValue, } from "@madie/madie-models"; import { Bundle, ValueSet } from "fhir/r4"; import * as _ from "lodash"; @@ -290,7 +291,8 @@ export class CalculationService { return results; } - isGroupPass(groupPopulation: GroupPopulation) { + isGroupPass(groupPopulation: GroupPopulation, measureGroup: Group) { + // console.log("isGroupPass: for group: "+measureGroup.id); let groupPass = true; if (groupPopulation) { const patientBased = @@ -313,12 +315,20 @@ export class CalculationService { // verify stratification & stratified populations passing if they exist if (groupPopulation.stratificationValues) { let validStratPopValues = []; - groupPopulation.stratificationValues.forEach((stratValues) => { - const filtered = stratValues.populationValues?.filter( - (populationValue) => populationValue.expected !== null - ); - validStratPopValues.push(filtered); - }); + groupPopulation.stratificationValues.forEach( + (stratValues: StratificationExpectedValue) => { + stratValues.populationValues?.forEach((popValue) => { + const validPopValues = this.getValidStratPopulationValues( + measureGroup, + stratValues.id, + popValue + ); + if (validPopValues && validPopValues.length > 0) { + validStratPopValues.push(validPopValues); + } + }); + } + ); return validStratPopValues.every((strata) => { // verify stratified populations passing return strata.every((population) => @@ -334,6 +344,24 @@ export class CalculationService { return groupPass; } + getValidStratPopulationValues( + measureGroup: Group, + stratId: string, + popValue: PopulationExpectedValue + ): PopulationExpectedValue[] { + let valiePopValue = []; + measureGroup.stratifications?.forEach((strat) => { + if (strat.id === stratId) { + strat.associations?.forEach((association) => { + if (association === popValue.name) { + valiePopValue.push(popValue); + } + }); + } + }); + return valiePopValue; + } + processTestCaseResults( testCase: TestCase, measureGroups: Group[], @@ -470,7 +498,8 @@ export class CalculationService { }); }); // need to do work here. - allGroupsPass = allGroupsPass && this.isGroupPass(tcGroupPopulation); + allGroupsPass = + allGroupsPass && this.isGroupPass(tcGroupPopulation, measureGroup); } updatedTestCase.executionStatus = allGroupsPass ? ExecutionStatusType.PASS From a44881e35179e11c2efaf471dfe6f0654e662cef Mon Sep 17 00:00:00 2001 From: sb-cecilialiu Date: Mon, 18 Nov 2024 13:37:01 -0600 Subject: [PATCH 4/5] MAT-7915 fix test --- src/api/CalculationService.test.ts | 2 +- src/api/CalculationService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/CalculationService.test.ts b/src/api/CalculationService.test.ts index ce3f7cdb..6d249dcf 100644 --- a/src/api/CalculationService.test.ts +++ b/src/api/CalculationService.test.ts @@ -528,7 +528,7 @@ describe("CalculationService Tests", () => { ], }; const output = calculationService.isGroupPass(groupPop); - expect(output).toEqual(false); + expect(output).toEqual(true); }); it("should fail group with incorrect measure observations for Ratio", () => { diff --git a/src/api/CalculationService.ts b/src/api/CalculationService.ts index ee1ee08f..a25f4641 100644 --- a/src/api/CalculationService.ts +++ b/src/api/CalculationService.ts @@ -350,7 +350,7 @@ export class CalculationService { popValue: PopulationExpectedValue ): PopulationExpectedValue[] { let valiePopValue = []; - measureGroup.stratifications?.forEach((strat) => { + measureGroup?.stratifications?.forEach((strat) => { if (strat.id === stratId) { strat.associations?.forEach((association) => { if (association === popValue.name) { From d194a9a68b4b51bfaf4ef10098ee3937e5e6369d Mon Sep 17 00:00:00 2001 From: sb-cecilialiu Date: Mon, 18 Nov 2024 14:18:10 -0600 Subject: [PATCH 5/5] MAT-7915 remove console log and add test coverage --- src/api/CalculationService.test.ts | 165 +++++++++++++++++++++++++++-- src/api/CalculationService.ts | 1 - 2 files changed, 156 insertions(+), 10 deletions(-) diff --git a/src/api/CalculationService.test.ts b/src/api/CalculationService.test.ts index 6d249dcf..230577da 100644 --- a/src/api/CalculationService.test.ts +++ b/src/api/CalculationService.test.ts @@ -345,7 +345,7 @@ describe("CalculationService Tests", () => { populationValues: undefined, stratificationValues: undefined, }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -357,7 +357,7 @@ describe("CalculationService Tests", () => { populationValues: [], stratificationValues: undefined, }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -369,7 +369,7 @@ describe("CalculationService Tests", () => { populationValues: [], stratificationValues: [], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -389,7 +389,7 @@ describe("CalculationService Tests", () => { ], stratificationValues: [], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -423,7 +423,7 @@ describe("CalculationService Tests", () => { ], stratificationValues: [], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -457,7 +457,7 @@ describe("CalculationService Tests", () => { ], stratificationValues: [], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(false); }); @@ -492,7 +492,7 @@ describe("CalculationService Tests", () => { }, ], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(true); }); @@ -527,7 +527,154 @@ describe("CalculationService Tests", () => { }, ], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); + expect(output).toEqual(true); + }); + + it("Should pass group with stratifications and filter out invalid population values", () => { + const group: Group = { + id: "6734f7e4af7d11385b114b91", + scoring: "Continuous Variable", + populations: [ + { + id: "69333bb0-0e65-41ac-9648-8badc3e70c6e", + name: PopulationType.INITIAL_POPULATION, + definition: "Initial Population", + description: "", + }, + { + id: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + name: PopulationType.MEASURE_POPULATION, + definition: "Qualifying Encounters", + description: "", + }, + { + id: "9a4b1c39-5a94-49b2-ae33-75ec80a5d7d6", + name: PopulationType.MEASURE_POPULATION_OBSERVATION, + definition: "", + description: "", + }, + ], + measureObservations: [ + { + id: "3a429f92-8eb6-456a-bfd4-658458d54885", + definition: "MeasureObservation", + + criteriaReference: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + aggregateMethod: "Maximum", + }, + ], + groupDescription: "", + improvementNotation: "", + rateAggregation: "", + measureGroupTypes: [MeasureGroupTypes.PROCESS], + scoringUnit: "", + stratifications: [ + { + id: "a9197a7f-78ca-484c-a84d-05531c1dd9e4", + description: "StratificationOne", + cqlDefinition: "Stratification 1", + associations: [PopulationType.INITIAL_POPULATION], + }, + { + id: "c88151f1-83dd-477e-afe7-631e17cec6ff", + description: "StratificationTwo", + cqlDefinition: "Stratification 2", + associations: [PopulationType.MEASURE_POPULATION], + }, + ], + populationBasis: "Encounter", + }; + const groupPop = { + groupId: "6734f7e4af7d11385b114b91", + scoring: "Continuous Variable", + populationBasis: "Encounter", + populationValues: [ + { + id: "69333bb0-0e65-41ac-9648-8badc3e70c6e", + criteriaReference: null, + name: PopulationType.INITIAL_POPULATION, + expected: "1", + actual: 1, + }, + { + id: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + criteriaReference: null, + name: PopulationType.MEASURE_POPULATION, + expected: "1", + actual: 1, + }, + { + id: "measurePopulationObservation0", + criteriaReference: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + name: PopulationType.MEASURE_POPULATION_OBSERVATION, + expected: "02", + actual: 2, + }, + ], + stratificationValues: [ + { + id: "a9197a7f-78ca-484c-a84d-05531c1dd9e4", + name: "Strata-1", + expected: null, + actual: null, + populationValues: [ + { + id: "69333bb0-0e65-41ac-9648-8badc3e70c6e", + criteriaReference: null, + name: PopulationType.INITIAL_POPULATION, + expected: "1", + actual: 1, + }, + { + id: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + criteriaReference: null, + name: PopulationType.MEASURE_POPULATION, + expected: "1", + actual: 1, + }, + { + id: "measurePopulationObservation0", + criteriaReference: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + name: PopulationType.MEASURE_POPULATION_OBSERVATION, + expected: "02", + actual: 0, + }, + ], + }, + { + id: "c88151f1-83dd-477e-afe7-631e17cec6ff", + name: "Strata-2", + expected: null, + actual: null, + populationValues: [ + { + id: "69333bb0-0e65-41ac-9648-8badc3e70c6e", + criteriaReference: null, + name: PopulationType.INITIAL_POPULATION, + expected: "0", + actual: 0, + }, + { + id: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + criteriaReference: null, + name: PopulationType.MEASURE_POPULATION, + expected: "0", + actual: 0, + }, + { + id: "measurePopulationObservation0", + criteriaReference: "60ab5bfd-bd1a-4e53-8cd8-1cb4aae465dd", + name: PopulationType.MEASURE_POPULATION_OBSERVATION, + expected: "02", + actual: 0, + }, + ], + }, + ], + }; + + const output = calculationService.isGroupPass(groupPop, group); expect(output).toEqual(true); }); @@ -575,7 +722,7 @@ describe("CalculationService Tests", () => { ], stratificationValues: [], }; - const output = calculationService.isGroupPass(groupPop); + const output = calculationService.isGroupPass(groupPop, {} as Group); expect(output).toEqual(false); }); }); diff --git a/src/api/CalculationService.ts b/src/api/CalculationService.ts index a25f4641..10c217da 100644 --- a/src/api/CalculationService.ts +++ b/src/api/CalculationService.ts @@ -292,7 +292,6 @@ export class CalculationService { } isGroupPass(groupPopulation: GroupPopulation, measureGroup: Group) { - // console.log("isGroupPass: for group: "+measureGroup.id); let groupPass = true; if (groupPopulation) { const patientBased =