Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add proficiency and mode to patient language #3083

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion containers/ecr-viewer/src/app/api/fhirPath.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ patientRace: "Bundle.entry.resource.where(resourceType = 'Patient').extension.wh
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"
patientPreferredCommunication: "Bundle.entry.resource.where(resourceType = 'Patient').communication.where(preferred = true)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is preferred always set? or would we want the first as a fallback?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preferred isn't always set, but the field is called preferred language.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if preferred isn't set, we will show no language info at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - as it is we won't display any languages if there are none that are preferred.

@ashton-skylight - Should we display any language if there are no "preferred" languages?

Copy link
Collaborator

@ashton-skylight ashton-skylight Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BobanL if there is a language specified (that isn't preferred), we should probably still display it

Would this be possible?

  • If there is a preferred language specified, only display the preferred language
  • If there is not a preferred language specified, display any other languages

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"
patientEmergencyContact: "Bundle.entry.resource.where(resourceType = 'Patient').contact"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
Coding,
Condition,
Encounter,
Extension,
HumanName,
Location,
Organization,
PatientCommunication,
PatientContact,
Practitioner,
PractitionerRole,
Expand Down Expand Up @@ -337,7 +339,7 @@ export const evaluateDemographicsData = (
},
{
title: "Preferred Language",
value: evaluate(fhirBundle, mappings.patientLanguage)[0],
value: evaluatePatientLanguage(fhirBundle, mappings),
},
{
title: "Patient Address",
Expand Down Expand Up @@ -630,7 +632,10 @@ export const evaluateReference = (
* @param path - The path within the resource to extract the value from.
* @returns - The evaluated value as a string.
*/
export const evaluateValue = (entry: Element, path: string | Path): string => {
export const evaluateValue = (
entry: Element | Element[],
path: string | Path,
): string => {
let originalValue = evaluate(entry, path, undefined, fhirpath_r4_model)[0];

let value = "";
Expand Down Expand Up @@ -737,3 +742,40 @@ export const evaluateEncounterDiagnosis = (
.map((condition) => condition.code?.coding?.[0].display)
.join(", ");
};

/**
* Evaluate patient's prefered language
* @param fhirBundle - The FHIR bundle containing resources.
* @param mappings - Path mappings for resolving references.
* @returns String containing language, proficiency, and mode
*/
export const evaluatePatientLanguage = (
fhirBundle: Bundle,
mappings: PathMappings,
) => {
const patientCommunication: PatientCommunication[] = evaluate(
fhirBundle,
mappings.patientPreferredCommunication,
);

const patientProficiencyExtension: Extension[] = evaluate(
patientCommunication,
"extension.where(url = 'http://hl7.org/fhir/StructureDefinition/patient-proficiency')",
);
const patientLanguage: string | undefined = evaluateValue(
patientCommunication,
"language.coding",
);
const languageProficency: string | undefined = evaluateValue(
patientProficiencyExtension,
"extension.where(url = 'level').value",
);
const languageMode: string | undefined = evaluateValue(
patientProficiencyExtension,
"extension.where(url = 'type').value",
);

return [patientLanguage, languageProficency, languageMode]
.filter(Boolean)
.join("\n");
};
37 changes: 36 additions & 1 deletion containers/ecr-viewer/src/app/tests/assets/BundlePatient.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@
}
],
"communication": [
{
"language": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "es",
"display": "Spanish"
}
]
}
},
{
"language": {
"coding": [
Expand All @@ -169,7 +180,31 @@
"display": "English"
}
]
}
},
"preferred": true,
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-proficiency",
"extension": [
{
"url": "type",
"valueCoding": {
"system": "http://terminology.hl7.org/CodeSystem/v3-LanguageAbilityMode",
"code": "ESP",
"display": "Expressed spoken"
}
},
{
"url": "level",
"valueCoding": {
"system": "http://terminology.hl7.org/CodeSystem/v3-LanguageAbilityProficiency",
"code": "G",
"display": "Good"
}
}
]
}
]
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
evaluateDemographicsData,
evaluateEncounterCareTeamTable,
evaluateAlcoholUse,
evaluatePatientLanguage,
} from "@/app/services/evaluateFhirDataService";
import { Bundle, Patient } from "fhir/r4";
import BundleWithMiscNotes from "@/app/tests/assets/BundleMiscNotes.json";
Expand Down Expand Up @@ -538,3 +539,47 @@ describe("Evaluate Alcohol Use", () => {
expect(actual).toEqual("");
});
});

describe("Evaluate Patient language", () => {
it("Should display language, proficiency, and mode", () => {
const actual = evaluatePatientLanguage(
BundleWithPatient as unknown as Bundle,
mappings,
);

expect(actual).toEqual("English\nGood\nExpressed spoken");
});

it("Should not display non-preferred language", () => {
const patient = {
resourceType: "Bundle",
entry: [
{
resource: {
resourceType: "Patient",
communication: [
{
language: {
coding: [
{
system: "urn:ietf:bcp:47",
code: "es",
display: "Spanish",
},
],
},
},
],
},
},
],
};

const actual = evaluatePatientLanguage(
patient as unknown as Bundle,
mappings,
);

expect(actual).toEqual("");
});
});
2 changes: 1 addition & 1 deletion containers/fhir-converter/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build

# Download FHIR-Converter
RUN git clone https://github.com/skylight-hq/FHIR-Converter.git --branch v7.0-skylight-18 --single-branch /build/FHIR-Converter
RUN git clone https://github.com/skylight-hq/FHIR-Converter.git --branch boban/patient-proficency --single-branch /build/FHIR-Converter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: update to released before merging


WORKDIR /build/FHIR-Converter

Expand Down
1 change: 1 addition & 0 deletions containers/fhir-converter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ Both repos should be checked out and set up per the instructions above. We use r
#### Tips & Tricks

* To run the service tests, use the command `python -m pytest` (make sure the correct environment is activated).
* To update snapshots run `python -m pytest --snapshot-update`
* Make sure your docker image has pulled in the latest changes by building with no cache `make build-image-no-cache`.
* To run the tool tests, run the commands found in the github actions workflow.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,21 @@
'birthDate': '2005-05-01',
'communication': list([
dict({
'extension': list([
dict({
'extension': list([
dict({
'url': str,
'valueCoding': dict({
'code': 'ESP',
'display': 'Expressed spoken',
'system': 'http://terminology.hl7.org/CodeSystem/v3-LanguageAbilityMode',
}),
}),
]),
'url': str,
}),
]),
'language': dict({
'coding': list([
dict({
Expand Down Expand Up @@ -2494,6 +2509,21 @@
'birthDate': '1977-03-25',
'communication': list([
dict({
'extension': list([
dict({
'extension': list([
dict({
'url': str,
'valueCoding': dict({
'code': 'EWR',
'display': 'Expressed written',
'system': 'http://terminology.hl7.org/CodeSystem/v3-LanguageAbilityMode',
}),
}),
]),
'url': str,
}),
]),
'language': dict({
'coding': list([
dict({
Expand Down
Loading