Skip to content

Commit

Permalink
add eicr author details (#2623)
Browse files Browse the repository at this point in the history
* add org to device

* Remove incorrect device author

should only be organization
https://build.fhir.org/device.html#:~:text=hours%2C%20mins%2C%20etc.)-,owner,-0..1

* Remove organization information in practitioner

* assign practitioner role as author

* update data

* update data

* add new function for evaluatePractitionerRoleReference

* Add ecr author details to ecr metadata

* add ecr author details to AccordionContent.tsx and EcrMetadata.tsx

* add eicr author details to content length

* update snapshot

* Handle multiple authors in the ecr metadata service

* Change the parameter to accept Array of data display for eicr author details

* Add eicr author details as its own section in unavailable information

* fix missing key in the eicr author details section
  • Loading branch information
BobanL authored Oct 9, 2024
1 parent 2486489 commit 565256e
Show file tree
Hide file tree
Showing 16 changed files with 1,826 additions and 84 deletions.
2 changes: 2 additions & 0 deletions containers/ecr-viewer/src/app/api/fhirPath.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ patientAlcoholUse: "Bundle.entry.resource.where(resourceType='Observation').wher
patientSexualOrientation: "Bundle.entry.resource.where(resourceType='Observation').where(code.coding.code='76690-7').valueString"
patientGenderIdentity: "Bundle.entry.resource.where(resourceType = 'Patient').extension.where(url='http: //hl7.org/fhir/us/ecr/StructureDefinition/us-ph-genderidentity-extension').extension.value.coding.display"

#eCR Metadata
eicrIdentifier: "Bundle.entry.resource.where(resourceType= 'Composition').id"
eicrReleaseVersion: "Bundle.entry.resource.where(resourceType='Composition').extension.where(url='https://www.hl7.org/implement/standards/product_brief.cfm?product_id=436').valueString"
eicrCustodianRef: "Bundle.entry.resource.where(resourceType= 'Composition').custodian.reference"
Expand All @@ -41,6 +42,7 @@ ehrSoftware: "Bundle.entry.resource.where(resourceType = 'Device').where(propert
ehrManufacturerModel: "Bundle.entry.resource.where(resourceType = 'Device').where(property[0].type.coding.code='software').manufacturer"
senderFacilityName: "Bundle.entry.resource.where(resourceType = 'Encounter')[0].location[0].location.display"
eRSDwarnings: "Bundle.entry.resource.where(resourceType= 'Composition').section.where(title = 'Reportability Response Information Section').extension.where(url = 'http://hl7.org/fhir/us/ecr/StructureDefinition/rr-eicr-processing-status-extension').valueCodeableConcept.coding.entries.eRSDwarnings"
compositionAuthorRefs: "Bundle.entry.resource.where(resourceType = 'Composition').author"

# Encounter Info
encounterEndDate: "Bundle.entry.resource.where(resourceType = 'Encounter').period.end"
Expand Down
126 changes: 123 additions & 3 deletions containers/ecr-viewer/src/app/services/ecrMetadataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import {
formatAddress,
formatContactPoint,
formatDateTime,
formatName,
} from "@/app/services/formatService";
import { PathMappings, evaluateData } from "@/app/view-data/utils/utils";
import { Bundle, Organization } from "fhir/r4";
import {
CompleteData,
evaluateData,
PathMappings,
} from "@/app/view-data/utils/utils";
import { Bundle, Organization, Reference } from "fhir/r4";
import { evaluate } from "@/app/view-data/utils/evaluate";
import { evaluatePractitionerRoleReference } from "./evaluateFhirDataService";
import { DisplayDataProps } from "@/app/view-data/components/DataDisplay";
import { evaluateReference } from "@/app/services/evaluateFhirDataService";

Expand All @@ -15,6 +21,14 @@ export interface ReportableConditions {
};
}

interface EcrMetadata {
eicrDetails: CompleteData;
ecrCustodianDetails: CompleteData;
rrDetails: ReportableConditions;
eicrAuthorDetails: CompleteData[];
eRSDWarnings: ERSDWarning[];
}

export interface ERSDWarning {
warning: string;
versionUsed: string;
Expand All @@ -31,7 +45,7 @@ export interface ERSDWarning {
export const evaluateEcrMetadata = (
fhirBundle: Bundle,
mappings: PathMappings,
) => {
): EcrMetadata => {
const rrDetails = evaluate(fhirBundle, mappings.rrDetails);

let reportableConditionsList: ReportableConditions = {};
Expand Down Expand Up @@ -159,10 +173,116 @@ export const evaluateEcrMetadata = (
},
];

const eicrAuthorDetails = evaluateEcrAuthorDetails(fhirBundle, mappings);

return {
eicrDetails: evaluateData(eicrDetails),
ecrCustodianDetails: evaluateData(ecrCustodianDetails),
rrDetails: reportableConditionsList,
eRSDWarnings: eRSDTextList,
eicrAuthorDetails: eicrAuthorDetails.map((details) =>
evaluateData(details),
),
};
};

const evaluateEcrAuthorDetails = (
fhirBundle: Bundle,
mappings: PathMappings,
): DisplayDataProps[][] => {
const authorRefs: Reference[] = evaluate(
fhirBundle,
mappings["compositionAuthorRefs"],
);

const authorDetails: DisplayDataProps[][] = [];
authorRefs.forEach((ref) => {
if (ref.reference?.includes("PractitionerRole/")) {
const practitionerRoleRef = ref?.reference;
const { practitioner, organization } = evaluatePractitionerRoleReference(
fhirBundle,
mappings,
practitionerRoleRef ?? "",
);

authorDetails.push([
{
title: "Author Name",
value: formatName(
practitioner?.name?.[0].given,
practitioner?.name?.[0].family,
practitioner?.name?.[0].prefix,
practitioner?.name?.[0].suffix,
),
},
{
title: "Author Address",
value: practitioner?.address?.map((address) =>
formatAddress(
address.line ?? [],
address.city ?? "",
address.state ?? "",
address.postalCode ?? "",
address.country ?? "",
),
),
},
{
title: "Author Contact",
value: formatContactPoint(practitioner?.telecom).join("\n"),
},
{
title: "Author Facility Name",
value: organization?.name,
},
{
title: "Author Facility Address",
value: organization?.address?.map((address) =>
formatAddress(
address.line ?? [],
address.city ?? "",
address.state ?? "",
address.postalCode ?? "",
address.country ?? "",
),
),
},
{
title: "Author Facility Contact",
value: formatContactPoint(organization?.telecom).join("\n"),
},
]);
}
});

if (authorDetails.length === 0) {
authorDetails.push([
{
title: "Author Name",
value: null,
},
{
title: "Author Address",
value: null,
},
{
title: "Author Contact",
value: null,
},
{
title: "Author Facility Name",
value: null,
},
{
title: "Author Facility Address",
value: null,
},
{
title: "Author Facility Contact",
value: null,
},
]);
}

return authorDetails;
};
42 changes: 31 additions & 11 deletions containers/ecr-viewer/src/app/services/evaluateFhirDataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,21 +415,11 @@ export const evaluateProviderData = (
encounter,
mappings["encounterIndividualRef"],
)[0];
const practitionerRole: PractitionerRole | undefined = evaluateReference(
const { practitioner, organization } = evaluatePractitionerRoleReference(
fhirBundle,
mappings,
encounterParticipantRef ?? "",
);
const practitioner: Practitioner | undefined = evaluateReference(
fhirBundle,
mappings,
practitionerRole?.practitioner?.reference ?? "",
);
const organization: Organization | undefined = evaluateReference(
fhirBundle,
mappings,
practitionerRole?.organization?.reference ?? "",
);

const providerData = [
{
Expand Down Expand Up @@ -617,3 +607,33 @@ export const evaluateFacilityId = (

return location?.identifier?.[0].value;
};

/**
* Evaluate practitioner role reference
* @param fhirBundle - The FHIR bundle containing resources.
* @param mappings - Path mappings for resolving references.
* @param practitionerRoleRef - practitioner role reference to be searched.
* @returns practitioner and organization
*/
export const evaluatePractitionerRoleReference = (
fhirBundle: Bundle,
mappings: PathMappings,
practitionerRoleRef: string,
): { practitioner?: Practitioner; organization?: Organization } => {
const practitionerRole: PractitionerRole | undefined = evaluateReference(
fhirBundle,
mappings,
practitionerRoleRef,
);
const practitioner: Practitioner | undefined = evaluateReference(
fhirBundle,
mappings,
practitionerRole?.practitioner?.reference ?? "",
);
const organization: Organization | undefined = evaluateReference(
fhirBundle,
mappings,
practitionerRole?.organization?.reference ?? "",
);
return { practitioner, organization };
};
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@
},
"author": [
{
"reference": "Practitioner/550b9626-bc9e-7d6b-c5d8-e41c2000ab85"
"reference": "PractitionerRole/b18c20c1-123b-fd12-71cf-9dd0abae8ced"
},
{
"reference": "Device/a57ef88d-1c60-d952-e7ca-5e9e16c7ef05"
Expand All @@ -467,6 +467,93 @@
"url": "Composition/1.2.840.114350.1.13.478.3.7.8.688883.230886"
}
},
{
"resource": {
"resourceType": "PractitionerRole",
"id": "b18c20c1-123b-fd12-71cf-9dd0abae8ced",
"organization": {
"reference": "Organization/d319a926-0eb3-5847-3b21-db8b778b4f07"
},
"practitioner": {
"reference": "Practitioner/550b9626-bc9e-7d6b-c5d8-e41c2000ab85"
},
"meta": {
"source": "ecr"
}
}
},
{
"fullUrl": "urn:uuid:d319a926-0eb3-5847-3b21-db8b778b4f07",
"resource": {
"resourceType": "Organization",
"id": "d319a926-0eb3-5847-3b21-db8b778b4f07",
"identifier": [
{
"system": "urn:oid:1.2.840.114350.1.13.478.2.7.5.737384.61",
"value": "1104202761"
}
],
"name": "Vanderbilt University Medical Center",
"address": [
{
"use": "work",
"line": [
"3401 West End Ave"
],
"city": "NASHVILLE",
"state": "TN",
"country": "USA",
"postalCode": "37203",
"district": "DAVIDSON"
}
],
"telecom": [
{
"system": "phone",
"value": "+1-615-322-5000",
"use": "work"
}
],
"meta": {
"source": "ecr"
}
},
"request": {
"method": "PUT",
"url": "Organization/d319a926-0eb3-5847-3b21-db8b778b4f07"
}
},
{
"fullUrl": "urn:uuid:550b9626-bc9e-7d6b-c5d8-e41c2000ab85",
"resource": {
"resourceType": "Practitioner",
"id": "550b9626-bc9e-7d6b-c5d8-e41c2000ab85",
"meta": {
"profile": [
"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner"
],
"source": "ecr"
},
"identifier": [
{
"system": "urn:oid:1.2.840.114350.1.13.478.3.7.2.697780",
"value": "EDILABIH"
}
],
"name": [
{
"family": "Interface",
"given": [
"Lab"
]
}
]
},
"request": {
"method": "PUT",
"url": "Practitioner/550b9626-bc9e-7d6b-c5d8-e41c2000ab85"
}
},
{
"fullUrl": "urn:uuid:a57ef88d-1c60-d952-e7ca-5e9e16c7ef05",
"resource": {
Expand Down
Loading

0 comments on commit 565256e

Please sign in to comment.