-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Save draft * Refactor single generalized query
- Loading branch information
Showing
4 changed files
with
271 additions
and
297 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/** | ||
* A Data Class designed to store and manipulate various code values used | ||
* to create a fully customized FHIR query. The class holds instance variables | ||
* for each of four types of input codes (lab LOINCs, SNOMED/conditions, RXNorm, | ||
* and Class/System-Type); the class uses these to automatically compile query | ||
* strings for each subtype of eCR query that can be built using those codes' | ||
* information. | ||
*/ | ||
export class CustomQuery { | ||
// Store four types of input codes | ||
labCodes: string[] = []; | ||
snomedCodes: string[] = []; | ||
rxnormCodes: string[] = []; | ||
classTypeCodes: string[] = []; | ||
|
||
// Need default initialization of query strings outstide constructor, | ||
// since the `try` means we might not find the JSON spec | ||
observationQuery: string = ""; | ||
diagnosticReportQuery: string = ""; | ||
conditionQuery: string = ""; | ||
medicationRequestQuery: string = ""; | ||
socialHistoryQuery: string = ""; | ||
encounterQuery: string = ""; | ||
encounterClassTypeQuery: string = ""; | ||
|
||
// Some queries need to be batched in waves because their encounter references | ||
// might depend on demographic information | ||
hasSecondEncounterQuery: boolean = false; | ||
|
||
/** | ||
* Creates a CustomQuery Object. The constructor accepts a JSONspec, a | ||
* DIBBs-defined JSON structure consisting of four keys corresponding to | ||
* the four types of codes this data class encompasses. These Specs are | ||
* currently located in the `customQueries` directory of the app. | ||
* @param jsonSpec A JSON Object containing four code fields to load. | ||
* @param patientId The ID of the patient to build into query strings. | ||
*/ | ||
constructor(jsonSpec: any, patientId: string) { | ||
try { | ||
this.labCodes = jsonSpec?.labCodes || []; | ||
this.snomedCodes = jsonSpec?.snomedCodes || []; | ||
this.rxnormCodes = jsonSpec?.rxnormCodes || []; | ||
this.classTypeCodes = jsonSpec?.classTypeCodes || []; | ||
this.hasSecondEncounterQuery = jsonSpec?.hasSecondEncounterQuery || false; | ||
this.compileQueries(patientId); | ||
} catch (error) { | ||
console.error("Could not create CustomQuery Object: ", error); | ||
} | ||
} | ||
|
||
/** | ||
* Compile the stored code information and given patientID into all applicable | ||
* query strings for later use. If a particular code category has no values in | ||
* the provided spec (e.g. a Newborn Screening case will have no rxnorm codes), | ||
* any query built using those codes' filter will be left as the empty string. | ||
* @param patientId The ID of the patient to query for. | ||
*/ | ||
compileQueries(patientId: string): void { | ||
const labsFilter = this.labCodes.join(","); | ||
const snomedFilter = this.snomedCodes.join(","); | ||
const rxnormFilter = this.rxnormCodes.join(","); | ||
const classTypeFilter = this.classTypeCodes.join(","); | ||
|
||
this.observationQuery = | ||
labsFilter !== "" | ||
? `/Observation?subject=Patient/${patientId}&code=${labsFilter}` | ||
: ""; | ||
this.diagnosticReportQuery = | ||
labsFilter !== "" | ||
? `/DiagnosticReport?subject=${patientId}&code=${labsFilter}` | ||
: ""; | ||
this.conditionQuery = | ||
snomedFilter !== "" | ||
? `/Condition?subject=${patientId}&code=${snomedFilter}` | ||
: ""; | ||
this.medicationRequestQuery = | ||
rxnormFilter !== "" | ||
? `/MedicationRequest?subject=${patientId}&code=${rxnormFilter}&_include=MedicationRequest:medication&_include=MedicationRequest:medication.administration` | ||
: ""; | ||
this.socialHistoryQuery = `/Observation?subject=${patientId}&category=social-history`; | ||
this.encounterQuery = | ||
snomedFilter !== "" | ||
? `/Encounter?subject=${patientId}&reason-code=${snomedFilter}` | ||
: ""; | ||
this.encounterClassTypeQuery = | ||
classTypeFilter !== "" | ||
? `/Encounter?subject=${patientId}&class=${classTypeFilter}` | ||
: ""; | ||
} | ||
|
||
/** | ||
* Yields all non-empty-string queries compiled using the stored codes. | ||
* @returns A list of queries. | ||
*/ | ||
getAllQueries(): string[] { | ||
const queryRequests: string[] = [ | ||
this.observationQuery, | ||
this.diagnosticReportQuery, | ||
this.conditionQuery, | ||
this.medicationRequestQuery, | ||
this.socialHistoryQuery, | ||
this.encounterQuery, | ||
this.encounterClassTypeQuery, | ||
]; | ||
const filteredRequests = queryRequests.filter((q) => q !== ""); | ||
return filteredRequests; | ||
} | ||
|
||
/** | ||
* Sometimes, only a single query is desired rather than a full list. In | ||
* those cases, this function returns a single specified query string. | ||
* @param desiredQuery The type of query the user wants. | ||
* @returns The compiled query string for that type. | ||
*/ | ||
getQuery(desiredQuery: string): string { | ||
switch (desiredQuery) { | ||
case "observation": | ||
return this.observationQuery; | ||
case "diagnostic": | ||
return this.diagnosticReportQuery; | ||
case "condition": | ||
return this.conditionQuery; | ||
case "medication": | ||
return this.medicationRequestQuery; | ||
case "social": | ||
return this.socialHistoryQuery; | ||
case "encounter": | ||
return this.encounterQuery; | ||
case "encounterClass": | ||
return this.encounterClassTypeQuery; | ||
default: | ||
return ""; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
export type QueryStruct = { | ||
labCodes: string[]; | ||
snomedCodes: string[]; | ||
rxnormCodes: string[]; | ||
classTypeCodes: string[]; | ||
hasSecondEncounterQuery: boolean; | ||
}; | ||
|
||
export const SOCIAL_DETERMINANTS_QUERY: QueryStruct = { | ||
labCodes: [], | ||
snomedCodes: [], | ||
rxnormCodes: [], | ||
classTypeCodes: [], | ||
hasSecondEncounterQuery: false, | ||
}; | ||
|
||
export const CANCER_QUERY: QueryStruct = { | ||
labCodes: [], | ||
snomedCodes: ["92814006"], | ||
rxnormCodes: ["828265"], | ||
classTypeCodes: [], | ||
hasSecondEncounterQuery: true, | ||
}; | ||
|
||
export const CHLAMYDIA_QUERY: QueryStruct = { | ||
labCodes: ["24111-7", "72828-7", "21613-5", "82810-3", "11350-6", "83317-8"], | ||
snomedCodes: ["2339001", "72531000052105", "102874004", "A74.9"], | ||
rxnormCodes: ["434692", "82122", "1649987", "1665005"], | ||
classTypeCodes: ["54", "441"], | ||
hasSecondEncounterQuery: true, | ||
}; | ||
|
||
export const GONORRHEA_QUERY: QueryStruct = { | ||
labCodes: ["24111-7", "11350-6", "21613-5", "82810-3", "83317-8"], | ||
snomedCodes: ["15628003", "2339001", "72531000052105", "102874004"], | ||
rxnormCodes: ["1665005", "434692"], | ||
classTypeCodes: ["54", "441"], | ||
hasSecondEncounterQuery: true, | ||
}; | ||
|
||
export const NEWBORN_SCREENING_QUERY: QueryStruct = { | ||
labCodes: [ | ||
"73700-7", | ||
"73698-3", | ||
"54108-6", | ||
"54109-4", | ||
"58232-0", | ||
"57700-7", | ||
"73739-5", | ||
"73742-9", | ||
"2708-6", | ||
"8336-0", | ||
], | ||
snomedCodes: [], | ||
rxnormCodes: [], | ||
classTypeCodes: [], | ||
hasSecondEncounterQuery: false, | ||
}; | ||
|
||
export const SYPHILIS_QUERY: QueryStruct = { | ||
labCodes: ["LP70657-9", "53605-2"], | ||
snomedCodes: ["76272004", "186847001"], | ||
rxnormCodes: ["2671695"], | ||
classTypeCodes: ["54", "441"], | ||
hasSecondEncounterQuery: true, | ||
}; |
Oops, something went wrong.