From 8b265789e9a5b96828ad4dbd54c9fb58cf6a5914 Mon Sep 17 00:00:00 2001 From: Lina Roth Date: Fri, 27 Sep 2024 17:29:35 -0400 Subject: [PATCH] add ersd warnings (#2632) * add ersd warnings * Complete styling of table * Fix linting issues * Update test snapshot * Add tests * Design Review update and remove log * Fix build issue * Address requested changes * Use built in whitespace control --- .../ecr-viewer/src/app/api/fhirPath.yml | 1 + .../src/app/components/EcrTable.tsx | 1 - .../src/app/services/ecrMetadataService.ts | 35 ++++++++++++ .../app/tests/assets/BundleEcrMetadata.json | 29 +++++++++- .../app/tests/components/EcrMetadata.test.tsx | 21 ++++++- .../AccordionContent.test.tsx.snap | 19 +++++++ .../__snapshots__/EcrMetadata.test.tsx.snap | 56 +++++++++++++++++++ .../tests/services/ecrMetadataService.test.ts | 18 ++++++ .../view-data/components/AccordionContent.tsx | 6 ++ .../app/view-data/components/EcrMetadata.tsx | 47 +++++++++++++++- .../ecr-viewer/src/styles/custom-styles.scss | 3 +- .../eCR/Resource/_Composition.liquid | 30 +++++++++- 12 files changed, 255 insertions(+), 11 deletions(-) diff --git a/containers/ecr-viewer/src/app/api/fhirPath.yml b/containers/ecr-viewer/src/app/api/fhirPath.yml index 251df587ca..8bd9b3c38c 100644 --- a/containers/ecr-viewer/src/app/api/fhirPath.yml +++ b/containers/ecr-viewer/src/app/api/fhirPath.yml @@ -40,6 +40,7 @@ dateTimeEcrCreated: "Bundle.entry.resource.where(resourceType = 'Composition').d ehrSoftware: "Bundle.entry.resource.where(resourceType = 'Device').where(property[0].type.coding.code='software').version.value" 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" # Encounter Info encounterEndDate: "Bundle.entry.resource.where(resourceType = 'Encounter').period.end" diff --git a/containers/ecr-viewer/src/app/components/EcrTable.tsx b/containers/ecr-viewer/src/app/components/EcrTable.tsx index 68772f6133..91144ec262 100644 --- a/containers/ecr-viewer/src/app/components/EcrTable.tsx +++ b/containers/ecr-viewer/src/app/components/EcrTable.tsx @@ -20,7 +20,6 @@ const EcrTable = async ({ }) => { const renderPage = async (pageNumber: number) => { const startIndex = (pageNumber - 1) * itemsPerPage; - const endIndex = startIndex + itemsPerPage; const pageData = await listEcrData(startIndex, itemsPerPage); return renderListEcrTableData(pageData); }; diff --git a/containers/ecr-viewer/src/app/services/ecrMetadataService.ts b/containers/ecr-viewer/src/app/services/ecrMetadataService.ts index a7f5862e10..00b00e9c1b 100644 --- a/containers/ecr-viewer/src/app/services/ecrMetadataService.ts +++ b/containers/ecr-viewer/src/app/services/ecrMetadataService.ts @@ -15,6 +15,13 @@ export interface ReportableConditions { }; } +export interface ERSDWarning { + warning: string; + versionUsed: string; + expectedVersion: string; + suggestedSolution: string; +} + /** * Evaluates eCR metadata from the FHIR bundle and formats it into structured data for display. * @param fhirBundle - The FHIR bundle containing eCR metadata. @@ -73,6 +80,33 @@ export const evaluateEcrMetadata = ( } }; + const fhirERSDWarnings = evaluate(fhirBundle, mappings.eRSDwarnings); + let eRSDTextList: ERSDWarning[] = []; + + for (const warning of fhirERSDWarnings) { + if (warning.code === "RRVS34") { + eRSDTextList.push({ + warning: + "Sending organization is using an malformed eRSD (RCTC) version", + versionUsed: "2020-06-23", + expectedVersion: + "Sending organization should be using one of the following: 2023-10-06, 1.2.2.0, 3.x.x.x.", + suggestedSolution: + "The trigger code version your organization is using could not be determined. The trigger codes may be out date. Please have your EHR administrators update the version format for complete eCR functioning.", + }); + } else if (warning.code === "RRVS29") { + eRSDTextList.push({ + warning: + "Sending organization is using an outdated eRSD (RCTC) version", + versionUsed: "2020-06-23", + expectedVersion: + "Sending organization should be using one of the following: 2023-10-06, 1.2.2.0, 3.x.x.x.", + suggestedSolution: + "The trigger code version your organization is using is out-of-date. Please have your EHR administration install the current version for complete eCR functioning.", + }); + } + } + const eicrDetails: DisplayDataProps[] = [ { title: "eICR ID", @@ -130,5 +164,6 @@ export const evaluateEcrMetadata = ( eicrDetails: evaluateData(eicrDetails), ecrCustodianDetails: evaluateData(ecrCustodianDetails), rrDetails: reportableConditionsList, + eRSDWarnings: eRSDTextList, }; }; diff --git a/containers/ecr-viewer/src/app/tests/assets/BundleEcrMetadata.json b/containers/ecr-viewer/src/app/tests/assets/BundleEcrMetadata.json index f37ee2b58b..04a4eeb5bd 100644 --- a/containers/ecr-viewer/src/app/tests/assets/BundleEcrMetadata.json +++ b/containers/ecr-viewer/src/app/tests/assets/BundleEcrMetadata.json @@ -362,9 +362,32 @@ "valueCodeableConcept": { "coding": [ { - "code": "RRVS19", - "display": "eICR processed", - "system": "urn:oid:2.16.840.1.114222.4.5.274" + "entries": [ + { + "eRSDwarnings": [ + { + "id": "e39d6ae2-8c6e-4638-9b33-412996586f42", + "code": "RRVS29", + "display": "The eICR was processed with the warning of: outdated eRSD (RCTC) version.", + "system": "urn:oid:2.16.840.1.114222.4.5.274" + }, + { + "id": "80f7b4ff-4d96-46ef-ae8f-af1f9c1f206c", + "value": "2022-11-01", + "code": "RRVS31", + "display": "Outdated eRSD (RCTC) Version Detail", + "system": "urn:oid:2.16.840.1.114222.4.5.274" + }, + { + "id": "80f7b4ff-4d96-46ef-ae8f-af1f9c1f206c", + "value": "The expected eRSD (RCTC) version should be one of the following: 2024-04-05,1.2.3.0,3.x.x", + "code": "RRVS33", + "display": "Expected eRSD (RCTC) Version Detail", + "system": "urn:oid:2.16.840.1.114222.4.5.274" + } + ] + } + ] } ] } diff --git a/containers/ecr-viewer/src/app/tests/components/EcrMetadata.test.tsx b/containers/ecr-viewer/src/app/tests/components/EcrMetadata.test.tsx index 7de63aa0b4..b26b83ab21 100644 --- a/containers/ecr-viewer/src/app/tests/components/EcrMetadata.test.tsx +++ b/containers/ecr-viewer/src/app/tests/components/EcrMetadata.test.tsx @@ -3,7 +3,10 @@ import { axe } from "jest-axe"; import EcrMetadata from "../../view-data/components/EcrMetadata"; import React from "react"; import { DisplayDataProps } from "@/app/view-data/components/DataDisplay"; -import { ReportableConditions } from "@/app/services/ecrMetadataService"; +import { + ERSDWarning, + ReportableConditions, +} from "@/app/services/ecrMetadataService"; describe("ECR Metadata", () => { let container: HTMLElement; @@ -45,6 +48,19 @@ describe("ECR Metadata", () => { }, { title: "EHR Manufacturer Model Name", value: "Epic - Version 10.1" }, ]; + + const eRSDWarnings: ERSDWarning[] = [ + { + warning: + "Sending organization is using an malformed eRSD (RCTC) version", + versionUsed: "2020-06-23", + expectedVersion: + "Sending organization should be using one of the following: 2023-10-06, 1.2.2.0, 3.x.x.x.", + suggestedSolution: + "The trigger code version your organization is using could not be determined. The trigger codes may be out date. Please have your EHR administrators update the version format for complete eCR functioning.", + }, + ]; + const ecrCustodianDetails: DisplayDataProps[] = [ { title: "Custodian ID", @@ -67,8 +83,9 @@ describe("ECR Metadata", () => { container = render( , ).container; }); diff --git a/containers/ecr-viewer/src/app/tests/components/__snapshots__/AccordionContent.test.tsx.snap b/containers/ecr-viewer/src/app/tests/components/__snapshots__/AccordionContent.test.tsx.snap index f9aa3ea5e7..5eb94a6af7 100644 --- a/containers/ecr-viewer/src/app/tests/components/__snapshots__/AccordionContent.test.tsx.snap +++ b/containers/ecr-viewer/src/app/tests/components/__snapshots__/AccordionContent.test.tsx.snap @@ -1392,6 +1392,25 @@ exports[`Snapshot test for Accordion Content Given no data, info message for emp class="section__line_gray" /> +
+
+
+ eRSD Warnings +
+
+ No data +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ eRSD Warnings +
+ Warning + + Version in Use + + Expected Version + + Suggested Solution +
+ Sending organization is using an malformed eRSD (RCTC) version + + 2020-06-23 + + Sending organization should be using one of the following: 2023-10-06, 1.2.2.0, 3.x.x.x. + + The trigger code version your organization is using could not be determined. The trigger codes may be out date. Please have your EHR administrators update the version format for complete eCR functioning. +
+
+
diff --git a/containers/ecr-viewer/src/app/tests/services/ecrMetadataService.test.ts b/containers/ecr-viewer/src/app/tests/services/ecrMetadataService.test.ts index 01465bc35e..793dd4dee0 100644 --- a/containers/ecr-viewer/src/app/tests/services/ecrMetadataService.test.ts +++ b/containers/ecr-viewer/src/app/tests/services/ecrMetadataService.test.ts @@ -84,4 +84,22 @@ describe("Evaluate Ecr Metadata", () => { }, }); }); + it("should have eRSDwarnings", () => { + const actual = evaluateEcrMetadata( + BundleWithEcrMetadata as unknown as Bundle, + mappings, + ); + + expect(actual.eRSDWarnings).toEqual([ + { + warning: + "Sending organization is using an outdated eRSD (RCTC) version", + versionUsed: "2020-06-23", + expectedVersion: + "Sending organization should be using one of the following: 2023-10-06, 1.2.2.0, 3.x.x.x.", + suggestedSolution: + "The trigger code version your organization is using is out-of-date. Please have your EHR administration install the current version for complete eCR functioning.", + }, + ]); + }); }); diff --git a/containers/ecr-viewer/src/app/view-data/components/AccordionContent.tsx b/containers/ecr-viewer/src/app/view-data/components/AccordionContent.tsx index 6fea8167c8..0fcb1804a2 100644 --- a/containers/ecr-viewer/src/app/view-data/components/AccordionContent.tsx +++ b/containers/ecr-viewer/src/app/view-data/components/AccordionContent.tsx @@ -67,6 +67,7 @@ const AccordionContent: React.FC = ({ clinicalData.clinicalNotes.unavailableData, ...ecrMetadata.eicrDetails.unavailableData, ...ecrMetadata.ecrCustodianDetails.unavailableData, + ecrMetadata.eRSDWarnings, ]; return unavailableDataArrays.some( (array) => Array.isArray(array) && array.length > 0, @@ -161,6 +162,7 @@ const AccordionContent: React.FC = ({ content: ( <> {Object.keys(ecrMetadata.rrDetails).length > 0 || + ecrMetadata.eRSDWarnings.length > 0 || ecrMetadata.eicrDetails.availableData.length > 0 || ecrMetadata.ecrCustodianDetails.availableData.length > 0 ? ( = ({ ecrMetadata.ecrCustodianDetails.availableData } rrDetails={ecrMetadata.rrDetails} + eRSDWarnings={ecrMetadata.eRSDWarnings} /> ) : (

@@ -203,6 +206,9 @@ const AccordionContent: React.FC = ({ clinicalNotesData={clinicalData.clinicalNotes.unavailableData} ecrMetadataUnavailableData={[ ...ecrMetadata.eicrDetails.unavailableData, + ...(ecrMetadata.eRSDWarnings.length === 0 + ? [{ title: "eRSD Warnings", value: "" }] + : []), ...ecrMetadata.ecrCustodianDetails.unavailableData, ]} /> diff --git a/containers/ecr-viewer/src/app/view-data/components/EcrMetadata.tsx b/containers/ecr-viewer/src/app/view-data/components/EcrMetadata.tsx index 168e136425..a16807566b 100644 --- a/containers/ecr-viewer/src/app/view-data/components/EcrMetadata.tsx +++ b/containers/ecr-viewer/src/app/view-data/components/EcrMetadata.tsx @@ -5,7 +5,10 @@ import { } from "../component-utils"; import { Table } from "@trussworks/react-uswds"; import { ToolTipElement } from "@/app/view-data/components/ToolTipElement"; -import { ReportableConditions } from "../../services/ecrMetadataService"; +import { + ERSDWarning, + ReportableConditions, +} from "../../services/ecrMetadataService"; import { DataDisplay, DisplayDataProps, @@ -15,6 +18,7 @@ import React from "react"; interface EcrMetadataProps { rrDetails: ReportableConditions; eicrDetails: DisplayDataProps[]; + eRSDWarnings: ERSDWarning[]; eCRCustodianDetails: DisplayDataProps[]; } @@ -66,12 +70,14 @@ const convertDictionaryToRows = (dictionary: ReportableConditionsList) => { * @param props - Props containing eCR metadata. * @param props.rrDetails - The reportable conditions details. * @param props.eicrDetails - The eICR details. + * @param props.eRSDWarnings - The eRSD warnings. * @param props.eCRCustodianDetails - The eCR custodian details. * @returns The JSX element representing the eCR metadata. */ const EcrMetadata = ({ rrDetails, eicrDetails, + eRSDWarnings, eCRCustodianDetails, }: EcrMetadataProps) => { return ( @@ -115,6 +121,45 @@ const EcrMetadata = ({ {convertDictionaryToRows(rrDetails)} + {eRSDWarnings?.length > 0 ? ( +

+
+ + + + + + + + + + + {Array.isArray(eRSDWarnings) && + eRSDWarnings.map((warningItem, index) => ( + + + + + + + ))} + +
WarningVersion in UseExpected VersionSuggested Solution
{warningItem.warning}{warningItem.versionUsed} + {warningItem.expectedVersion} + + {warningItem.suggestedSolution} +
+
+
+ ) : ( + "" + )}
eICR Details {eicrDetails.map((item, index) => { diff --git a/containers/ecr-viewer/src/styles/custom-styles.scss b/containers/ecr-viewer/src/styles/custom-styles.scss index 37594fff46..3d5ddab391 100644 --- a/containers/ecr-viewer/src/styles/custom-styles.scss +++ b/containers/ecr-viewer/src/styles/custom-styles.scss @@ -236,9 +236,8 @@ h4 { } } -.ecrTable { +.fixed-table { table-layout: fixed; - width: 100%; } td { diff --git a/containers/fhir-converter/Templates/eCR/Resource/_Composition.liquid b/containers/fhir-converter/Templates/eCR/Resource/_Composition.liquid index 83731fda8f..56aa08467f 100644 --- a/containers/fhir-converter/Templates/eCR/Resource/_Composition.liquid +++ b/containers/fhir-converter/Templates/eCR/Resource/_Composition.liquid @@ -244,12 +244,38 @@ {% assign rrentries = composition.section.entry | to_array -%} {% for rrentry in rrentries -%} {% if rrentry.act.templateId.root == "2.16.840.1.113883.10.20.15.2.3.29" -%} - {% include 'DataType/Coding' Coding: rrentry.act.code -%} + {% if rrentry.act.code.code == "RRVS20" %} + {% assign subrrentrys = rrentry.act.entryRelationship | to_array -%} + {% for subrrentry in subrrentrys %} + {% if subrrentry.typeCode != "SPRT" %} + "entries": [ + { + "eRSDwarnings": [ + { + "id": "{{ subrrentry.observation.id.root }}", + {% include 'DataType/Coding' Coding: subrrentry.observation.value -%} + }, + {% assign ers = subrrentry.observation.entryRelationship | to_array -%} + {% for er in ers -%} + { + "id": "{{ er.observation.id.root }}", + "value": "{{- er.observation.value._ -}}", + {% include 'DataType/Coding' Coding: er.observation.code -%}, + }, + {% endfor -%} + ], + }, + ], + {% endif -%} + {% endfor %} + {% else %} + {% include 'DataType/Coding' Coding: rrentry.act.code -%} + {% endif -%} {% endif -%} {% endfor -%} }, ], - } + }, }, ], "code": {