Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
Merge branch 'develop' into MAT-6475
Browse files Browse the repository at this point in the history
  • Loading branch information
ethankaplan authored Dec 11, 2023
2 parents ecd7127 + a339621 commit 00b854d
Show file tree
Hide file tree
Showing 25 changed files with 1,921 additions and 131 deletions.
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm exec pretty-quick --staged && npm exec concurrently npm:test npm:lint
npm exec pretty-quick --staged && npm exec concurrently "npm:lint" "npm:test -- --silent"
4 changes: 4 additions & 0 deletions src/api/CqmModelConversionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
PopulationSet,
MeasurePeriod,
ValueSet,
CodeSystem,
} from "cqm-models";
import { ServiceConfig } from "./ServiceContext";
import useServiceConfig from "./useServiceConfig";
Expand Down Expand Up @@ -282,6 +283,9 @@ export class CqmConversionService {
elmJson.library?.valueSets?.def.forEach((valueSet: ValueSet) => {
valueSet.id = valueSet.id.replace("urn:oid:", "");
});
elmJson.library?.codeSystems?.def.forEach((codeSystem: CodeSystem) => {
codeSystem.id = codeSystem.id.replace("urn:oid:", "");
});
const cqlLibrary = new CQLLibrary();
cqlLibrary.library_name = elmJson.library?.identifier.id;
cqlLibrary.library_version = elmJson.library?.identifier.version;
Expand Down
29 changes: 17 additions & 12 deletions src/api/TerminologyServiceApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { officeVisitValueSet } from "./__mocks__/OfficeVisitValueSet";
import { officeVisitMeasureBundle } from "./__mocks__/OfficeVisitMeasureBundle";
import { cqm_measure_basic } from "../mockdata/qdm/CMS108/cqm_measure_basic";
import { cqm_measure_basic_valueset } from "../mockdata/qdm/CMS108/cqm_measure_basic_valueset";
import { Measure as CqmMeasure } from "cqm-models";
import { Measure as CqmMeasure, ValueSet } from "cqm-models";
import * as _ from "lodash";

jest.mock("axios");
Expand Down Expand Up @@ -81,7 +81,7 @@ describe("TerminologyServiceApi Tests", () => {

terminologyService
.getQdmValueSetsExpansion(cqm_measure_basic)
.then((data) => {
.then((data: ValueSet[]) => {
expect(data.length).toEqual(2);
expect(data[0].display_name).toEqual("Encounter Inpatient");
expect(data[0].oid).toEqual("2.16.840.1.113883.3.666.5.307");
Expand Down Expand Up @@ -136,15 +136,18 @@ describe("TerminologyServiceApi Tests", () => {
const result = terminologyService.getCqlCodesForDRCs(cqm_measure_basic);
expect(result.length).toBe(3);

expect(result[0].code).toBe("drc-bdb8b89536181a411ad034378b7ceef6");
expect(result[0].system).toBe("LOINC");
expect(result[0].display).toBe("Housing status");
expect(result[1].code).toBe("160734000");
expect(result[1].system).toBe("SNOMEDCT");
expect(result[1].display).toBe("Lives in a nursing home (finding)");
expect(result[2].code).toBe("98181-1");
expect(result[2].system).toBe("LOINC");
expect(result[2].display).toBe("Medical equipment used");
expect(result[0].cqlCode.code).toBe("drc-bdb8b89536181a411ad034378b7ceef6");
expect(result[0].cqlCode.system).toBe("LOINC");
expect(result[0].cqlCode.display).toBe("Housing status");
expect(result[0].codeSystemOid).toBe("2.16.840.1.113883.6.1");
expect(result[1].cqlCode.code).toBe("160734000");
expect(result[1].cqlCode.system).toBe("SNOMEDCT");
expect(result[1].cqlCode.display).toBe("Lives in a nursing home (finding)");
expect(result[1].codeSystemOid).toBe("2.16.840.1.113883.6.96");
expect(result[2].cqlCode.code).toBe("98181-1");
expect(result[2].cqlCode.system).toBe("LOINC");
expect(result[2].cqlCode.display).toBe("Medical equipment used");
expect(result[2].codeSystemOid).toBe("2.16.840.1.113883.6.1");
});

it("test getCqlCodesForDRCs no codes", () => {
Expand All @@ -161,7 +164,8 @@ describe("TerminologyServiceApi Tests", () => {
});

it("test getValueSetsForDRCs", () => {
const result = terminologyService.getValueSetsForDRCs(cqm_measure_basic);
const result: ValueSet[] =
terminologyService.getValueSetsForDRCs(cqm_measure_basic);

expect(result.length).toBe(1);

Expand All @@ -171,6 +175,7 @@ describe("TerminologyServiceApi Tests", () => {
);
expect(result[0].concepts[0].code_system_name).toBe("LOINC");
expect(result[0].concepts[0].display_name).toBe("Housing status");
expect(result[0].concepts[0].code_system_oid).toBe("2.16.840.1.113883.6.1");
});

it("test getValueSetsForDRCs no value sets", () => {
Expand Down
61 changes: 61 additions & 0 deletions src/api/useCqlParsingService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import axios from "axios";
import useServiceConfig from "./useServiceConfig";
import { ServiceConfig } from "./ServiceContext";
import { useOktaTokens } from "@madie/madie-util";
import { CqlDefinitionExpression } from "../util/GroupCoverageHelpers";
import { CqlDefinitionCallstack } from "../components/editTestCase/groupCoverage/QiCoreGroupCoverage";

export class CqlParsingService {
constructor(private baseUrl: string, private getAccessToken: () => string) {}

async getDefinitionCallstacks(cql: string): Promise<CqlDefinitionCallstack> {
try {
const response = await axios.put<string>(
`${this.baseUrl}/cql/callstacks`,
cql,
{
headers: {
Authorization: `Bearer ${this.getAccessToken()}`,
"Content-Type": "text/plain",
},
}
);
return response.data as unknown as CqlDefinitionCallstack;
} catch (err) {
const message = `Unable to retrieve used definition references`;
throw new Error(message);
}
}

async getAllDefinitionsAndFunctions(
cql: string
): Promise<CqlDefinitionExpression[]> {
try {
const response = await axios.put<string>(
`${this.baseUrl}/cql/definitions`,
cql,
{
headers: {
Authorization: `Bearer ${this.getAccessToken()}`,
"Content-Type": "text/plain",
},
}
);
return response.data as unknown as CqlDefinitionExpression[];
} catch (err) {
const message = `Unable to retrieve definition and function references`;
throw new Error(message);
}
}
}

const useCqlParsingService = (): CqlParsingService => {
const serviceConfig: ServiceConfig = useServiceConfig();
const { getAccessToken } = useOktaTokens();
return new CqlParsingService(
serviceConfig?.elmTranslationService.baseUrl,
getAccessToken
);
};

export default useCqlParsingService;
30 changes: 22 additions & 8 deletions src/api/useTerminologyServiceApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ type ValueSetsSearchCriteria = {
valueSetParams: ValueSetSearchParams[];
};

type CQLCodeWithCodeSystemOid = {
cqlCode: CQL.CQLCode;
codeSystemOid: string;
};

export class TerminologyServiceApi {
constructor(private baseUrl: string, private getAccessToken: () => string) {}

Expand Down Expand Up @@ -173,9 +178,10 @@ export class TerminologyServiceApi {

getValueSetsForDRCs(cqmMeasure: CqmMeasure): ValueSet[] {
const drcValueSets = [];
const cqlCodes: CQL.CQLCode[] = this.getCqlCodesForDRCs(cqmMeasure);
if (cqlCodes) {
cqlCodes.forEach((cqlCode) => {
const cqlCodeWithCodeSystemOid: CQLCodeWithCodeSystemOid[] =
this.getCqlCodesForDRCs(cqmMeasure);
if (cqlCodeWithCodeSystemOid) {
cqlCodeWithCodeSystemOid.forEach(({ cqlCode, codeSystemOid }) => {
const drcOid = this.getDrcOid(cqmMeasure, cqlCode.code);
if (drcOid) {
const valueSet = {
Expand All @@ -184,7 +190,7 @@ export class TerminologyServiceApi {
concepts: [
{
code: cqlCode.code,
code_system_oid: cqlCode.system,
code_system_oid: codeSystemOid,
code_system_name: cqlCode.system,
code_system_version: cqlCode.version,
display_name: cqlCode.display,
Expand All @@ -199,23 +205,31 @@ export class TerminologyServiceApi {
return drcValueSets;
}

getCqlCodesForDRCs(cqmMeasure: CqmMeasure): CQL.CQLCode[] {
const cqlCodes: CQL.CQLCode[] = [];
getCqlCodesForDRCs(cqmMeasure: CqmMeasure): CQLCodeWithCodeSystemOid[] {
const cqlCodeWithCodeSystemOid: CQLCodeWithCodeSystemOid[] = [];
cqmMeasure?.cql_libraries?.forEach((library) => {
const codeDefs = library?.elm?.library?.codes?.def;
const codeSystemDefs = library?.elm?.library?.codeSystems?.def;
if (!_.isEmpty(codeDefs)) {
codeDefs.forEach((def) => {
// find associated CodeSystem for this code, so that we can get codeSystem oid
const codeSystem = codeSystemDefs.find(
(cs) => cs.name === def.codeSystem.name
);
const cqlCode = new CQL.Code(
def?.id, //code
def.codeSystem.name, //system
"N/A", //version,
def.display //display
);
cqlCodes.push(cqlCode);
cqlCodeWithCodeSystemOid.push({
cqlCode: cqlCode,
codeSystemOid: codeSystem.id,
});
});
}
});
return cqlCodes;
return cqlCodeWithCodeSystemOid;
}

getDrcOid(cqmMeasure: CqmMeasure, code: string): string {
Expand Down
Loading

0 comments on commit 00b854d

Please sign in to comment.