Skip to content

Commit

Permalink
Add date of death, age at death, detailed ethnicity, and detailed race (
Browse files Browse the repository at this point in the history
  • Loading branch information
lina-roth authored Oct 18, 2024
1 parent c03760a commit a35c892
Show file tree
Hide file tree
Showing 9 changed files with 1,776 additions and 20 deletions.

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions containers/ecr-viewer/src/app/api/fhirPath.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ patientCounty: "Bundle.entry.resource.where(resourceType = 'Patient').address.fi
patientIds: "Bundle.entry.resource.where(resourceType = 'Patient').identifier"
patientDOB: "Bundle.entry.resource.where(resourceType = 'Patient').birthDate"
patientVitalStatus: "Bundle.entry.resource.where(resourceType = 'Patient').deceasedBoolean"
patientDOD: "Bundle.entry.resource.where(resourceType = 'Patient').deceasedDate"
patientGender: "Bundle.entry.resource.where(resourceType = 'Patient').gender"
patientRace: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race').extension.where(url = 'ombCategory').valueCoding.display"
patinetRaceExtension: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race').extension.where(url = 'detailed').valueCoding.display"
patientEthnicity: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity').extension.first().valueCoding.display"
patientRaceDetailed: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race').extension.where(url = 'detailed').valueCoding.display"
patientEthnicity: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity').extension.where(url = 'ombCategory').valueCoding.display"
patientEthnicityDetailed: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url = 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity').extension.where(url = 'detailed').valueCoding.display"
patientLanguage: "Bundle.entry.resource.where(resourceType = 'Patient').communication.first().language.coding.first().display"
patientTribalAffiliation: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url='http: //hl7.org/fhir/us/ecr/StructureDefinition/us-ph-tribal-affiliation-extension').extension.where(url='TribeName').value.display"
patientEmergencyContact: "Bundle.entry.resource.where(resourceType = 'Patient').contact.first()"
Expand Down
83 changes: 70 additions & 13 deletions containers/ecr-viewer/src/app/services/evaluateFhirDataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,37 @@ export const evaluatePatientRace = (
mappings: PathMappings,
) => {
const raceCat = evaluate(fhirBundle, mappings.patientRace)[0];
const raceDetailedExt =
evaluate(fhirBundle, mappings.patinetRaceExtension)[0] ?? "";
const raceDetailed =
evaluate(fhirBundle, mappings.patientRaceDetailed)[0] ?? "";

if (raceDetailedExt) {
return `${raceCat}, ${raceDetailedExt}`;
if (raceDetailed) {
return raceCat + "\n" + raceDetailed;
} else {
return raceCat;
}
};

/**
* Evaluates the patients ethnicity from the FHIR bundle and formats for display.
* @param fhirBundle - The FHIR bundle containing patient contact info.
* @param mappings - The object containing the fhir paths.
* @returns - The patient's ethnicity information, including additional ethnicity extension (if available).
*/
export const evaluatePatientEthnicity = (
fhirBundle: Bundle,
mappings: PathMappings,
) => {
const ethnicity = evaluate(fhirBundle, mappings.patientEthnicity)[0] ?? "";
const ethnicityDetailed =
evaluate(fhirBundle, mappings.patientEthnicityDetailed)[0] ?? "";

if (ethnicityDetailed) {
return ethnicity + "\n" + ethnicityDetailed;
} else {
return ethnicity;
}
};

/**
* Evaluates patient address from the FHIR bundle and formats it into structured data for display.
* @param fhirBundle - The FHIR bundle containing patient contact info.
Expand Down Expand Up @@ -157,22 +178,49 @@ const evaluateTravelHistory = (
};

/**
* Calculates the age of a patient to a given date or today.
* Calculates the age of a patient to a given date or today, unless DOD exists.
* @param fhirBundle - The FHIR bundle containing patient information.
* @param fhirPathMappings - The mappings for retrieving patient date of birth.
* @param [givenDate] - Optional. The target date to calculate the age. Defaults to the current date if not provided.
* @returns - The age of the patient in years, or undefined if date of birth is not available.
* @returns - The age of the patient in years, or undefined if date of birth is not available or if date of death exists.
*/
export const calculatePatientAge = (
fhirBundle: Bundle,
fhirPathMappings: PathMappings,
givenDate?: string,
) => {
const patientDOBString = evaluate(fhirBundle, fhirPathMappings.patientDOB)[0];
if (patientDOBString) {
const patientDODString = evaluate(fhirBundle, fhirPathMappings.patientDOD)[0];
if (patientDOBString && !patientDODString && !givenDate) {
const patientDOB = new Date(patientDOBString);
const targetDate = givenDate ? new Date(givenDate) : new Date();
return dateFns.differenceInYears(targetDate, patientDOB);
return dateFns.differenceInYears(new Date(), patientDOB);
} else if (patientDOBString && givenDate) {
const patientDOB = new Date(patientDOBString);
return dateFns.differenceInYears(new Date(givenDate), patientDOB);
} else {
return undefined;
}
};

/**
* Calculates Patient Age at Death if DOB and DOD exist, otherwise returns undefined
* @param fhirBundle - The FHIR bundle containing patient information.
* @param fhirPathMappings - The mappings for retrieving patient date of birth and date of death.
* @returns - The age of the patient at death in years, or undefined if date of birth or date of death is not available.
*/
export const calculatePatientAgeAtDeath = (
fhirBundle: Bundle,
fhirPathMappings: PathMappings,
) => {
const patientDOBString = evaluate(fhirBundle, fhirPathMappings.patientDOB)[0];
const patientDODString = evaluate(fhirBundle, fhirPathMappings.patientDOD)[0];

if (patientDOBString && patientDODString) {
const patientDOB = new Date(patientDOBString);
const patientDOD = new Date(patientDODString);
return dateFns.differenceInYears(patientDOD, patientDOB);
} else {
return undefined;
}
};

Expand Down Expand Up @@ -247,11 +295,20 @@ export const evaluateDemographicsData = (
title: "Current Age",
value: calculatePatientAge(fhirBundle, mappings)?.toString(),
},
{
title: "Age at Death",
value: calculatePatientAgeAtDeath(fhirBundle, mappings),
},
{
title: "Vital Status",
value: evaluate(fhirBundle, mappings.patientVitalStatus)[0]
? "Deceased"
: "Alive",
value:
evaluate(fhirBundle, mappings.patientVitalStatus)[0] === false
? "Alive"
: "Deceased",
},
{
title: "Date of Death",
value: evaluate(fhirBundle, mappings.patientDOD)[0],
},
{ title: "Sex", value: evaluate(fhirBundle, mappings.patientGender)[0] },
{
Expand All @@ -260,7 +317,7 @@ export const evaluateDemographicsData = (
},
{
title: "Ethnicity",
value: evaluate(fhirBundle, mappings.patientEthnicity)[0],
value: evaluatePatientEthnicity(fhirBundle, mappings),
},
{
title: "Tribal Affiliation",
Expand Down
7 changes: 7 additions & 0 deletions containers/ecr-viewer/src/app/tests/assets/BundlePatient.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@
"display": "Hispanic or Latino"
}
},
{
"url": "detailed",
"valueCoding": {
"code": "2106-3",
"display": "White"
}
},
{
"url": "text",
"valueString": "Hispanic or Latino"
Expand Down
143 changes: 143 additions & 0 deletions containers/ecr-viewer/src/app/tests/assets/BundlePatientDeceased.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
{
"resourceType": "Bundle",
"type": "batch",
"entry": [
{
"fullUrl": "urn:uuid:6b6b3c4c-4884-4a96-b6ab-c46406839cea",
"resource": {
"resourceType": "Patient",
"id": "6b6b3c4c-4884-4a96-b6ab-c46406839cea",
"meta": {
"profile": [
"http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"
],
"source": [
"ecr"
]
},
"identifier": [
{
"system": "urn:oid:2.16.840.1.113883.3.3316.100",
"value": "10308625"
}
],
"name": [
{
"family": "CASTILLO",
"given": [
"ABEL"
]
}
],
"birthDate": "2015-04-15",
"deceasedBoolean": true,
"deceasedDate": "2020-02-27",
"gender": "male",
"extension": [
{
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race",
"extension": [
{
"url": "ombCategory",
"valueCoding": {
"code": "2054-5",
"display": "Black or African American"
}
},
{
"url": "detailed",
"valueCoding": {
"code": "2076-8",
"display": "African"
}
},
{
"url": "text",
"valueString": "Black or African American"
}
]
},
{
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity",
"extension": [
{
"url": "ombCategory",
"valueCoding": {
"code": "2135-2",
"display": "Hispanic or Latino"
}
},
{
"url": "detailed",
"valueCoding": {
"code": "2106-3",
"display": "White"
}
},
{
"url": "text",
"valueString": "Hispanic or Latino"
}
]
},
{
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex",
"extension": [
{
"url": "value",
"valueCodeableConcept": {
"coding": [
{
"code": "M",
"display": "Male",
"system": "urn:oid:2.16.840.1.113883.5.1"
}
]
}
}
]
}
],
"address": [
{
"line": [
"1050 CARPENTER ST"
],
"city": "EDWARDS",
"state": "CA",
"country": "US",
"postalCode": "93523-2800"
}
],
"telecom": [
{
"system": "phone",
"value": "+18184195968",
"use": "home"
},
{
"system": "email",
"value": "MELLY.C.A.16@GMAIL.COM"
}
],
"communication": [
{
"language": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "en",
"display": "English"
}
]
}
}
]
},
"request": {
"method": "PUT",
"url": "Patient/6b6b3c4c-4884-4a96-b6ab-c46406839cea"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ exports[`Snapshot test for Accordion Content Given no data, info message for emp
<div
class="grid-col maxw7 text-pre-line"
>
Alive
Deceased
</div>
</div>
<div
Expand Down Expand Up @@ -284,6 +284,44 @@ exports[`Snapshot test for Accordion Content Given no data, info message for emp
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
>
<div
class="data-title padding-right-1"
>
Age at Death
</div>
<div
class="grid-col maxw7 text-pre-line text-italic text-base"
>
No data
</div>
</div>
<div
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
>
<div
class="data-title padding-right-1"
>
Date of Death
</div>
<div
class="grid-col maxw7 text-pre-line text-italic text-base"
>
No data
</div>
</div>
<div
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
evaluateFacilityId,
evaluateIdentifiers,
evaluatePatientRace,
evaluatePatientEthnicity,
evaluatePractitionerRoleReference,
evaluateReference,
evaluateValue,
Expand Down Expand Up @@ -107,7 +108,17 @@ describe("Evaluate Patient Race", () => {
BundleWithPatient as unknown as Bundle,
mappings,
);
expect(actual).toEqual("Black or African American, African");
expect(actual).toEqual("Black or African American\nAfrican");
});
});

describe("Evaluate Patient Ethnicity", () => {
it("should return ethnicity category and extension if available", () => {
const actual = evaluatePatientEthnicity(
BundleWithPatient as unknown as Bundle,
mappings,
);
expect(actual).toEqual("Hispanic or Latino\nWhite");
});
});

Expand Down
Loading

0 comments on commit a35c892

Please sign in to comment.