Skip to content

Commit

Permalink
Merge branch 'tech-by-design:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
alan-francis authored Jan 3, 2025
2 parents d146a69 + 9be03f0 commit a6d4d25
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 10 deletions.
2 changes: 1 addition & 1 deletion hub-prime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</parent>
<groupId>org.techbd</groupId>
<artifactId>hub-prime</artifactId>
<version>0.417.0</version>
<version>0.418.0</version>
<packaging>war</packaging>
<name>Tech by Design Hub (Prime)</name>
<description>Tech by Design Hub (Primary)</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@
const gridOptions = {
columnDefs: [
{
headerName: "QE Name",
headerName: "TechBD Tenant ID",
field: "qe_name",
filter: "agTextColumnFilter",
cellRenderer: qeNameCellRenderer,
headerTooltip: "Name of the Qualified Entity"
headerTooltip: "ID of the tenant involved in the interaction"
},
{
headerName: "QE to Tech by Design",
headerName: "TechBD Tenant ID to Tech by Design",
field: "qe_total_submissions",
// cellRenderer: cellRenderer1,
// cellStyle: function (params) {
Expand All @@ -208,7 +208,7 @@
// return null;
// },
filter: "agNumberColumnFilter",
headerTooltip: "FHIR File count from QE to Tech by Design"
headerTooltip: "FHIR File count from TechBD Tenant ID to Tech by Design"
},
{
headerName: "Tech by Design to SHIN-NY Data Lake",
Expand Down Expand Up @@ -400,7 +400,7 @@
"end_date": formattedEndDate,
};

helpers.injectDateRangeText('date-range', 'This widget compares the count of incoming synthetic files at each stage in the data processing pipeline, from the QE to Tech by Design then to the SHIN-NY Data Lake from <b>{startDate}</b> to <b>{endDate}</b>. It provides a clear view of data movement and processing consistency, highlighting discrepancies or drop-offs in the number of files between stages. This comparison helps in identifying potential issues and ensures the integrity of the data flow across the system.');
helpers.injectDateRangeText('date-range', 'This widget compares the count of incoming synthetic files at each stage in the data processing pipeline, from the TechBD Tenant ID to Tech by Design then to the SHIN-NY Data Lake from <b>{startDate}</b> to <b>{endDate}</b>. It provides a clear view of data movement and processing consistency, highlighting discrepancies or drop-offs in the number of files between stages. This comparison helps in identifying potential issues and ensures the integrity of the data flow across the system.');

const paramsJson = encodeURIComponent(JSON.stringify(storedProcparams));
const url = `/api/ux/tabular/jooq/sp/${schemaName}/${storedProcName}.json?storedProcparams=${paramsJson}`;
Expand Down Expand Up @@ -439,7 +439,7 @@
</div>
<h1 class="assemtion">Assumptions</h1>
<ul class="list-disc pl-4">
<li>The file count from QE to Tech by Design should match.</li>
<li>The file count from TechBD Tenant ID to Tech by Design should match.</li>
<li>The file count from Tech by Design to SHIN-NY Data Lake should match.</li>
<li>If any of the numbers in one column do not match the corresponding numbers in another column, it
indicates an error, and the mismatched numbers are highlighted in red.</li>
Expand Down
4 changes: 1 addition & 3 deletions support/specifications/ccda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,9 @@ This document focuses on the preparation of the XSLT file which is used for prot
- e. Observation (component/structuredBody/component)

- ### Create an XSLT file with transformation rules to exclude non-relevant tags.
- A sample XSLT file was developed to extract the specified sections (Patient, Organization, Encounter, Consent and Observation).
- A channel was configured in Mirth Connect to test the functionality of the XSLT file.

- ### Test the XSLT file with multiple CCD examples to ensure correct functionality.
- The XSLT file is tested with multiple CCD files as well as CCD files with sections other than the specified sections (Patient, Organization, Encounter, Consent and Observation)

- ### Publish the XSLT file on TechBD’s public GitHub repository.
- The XSLT file, cda-phi-filter.xslt, is saved in the GitHub repository under the folder support/specifications/ccda.

Expand Down
212 changes: 212 additions & 0 deletions support/specifications/ccda/cda-fhir-bundle.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ccda="urn:hl7-org:v3"
xmlns:fhir="http://hl7.org/fhir">

<xsl:output method="text"/>

<!-- Root template -->
<xsl:template match="/">
{
"resourceType": "Bundle",
"type": "collection",
<!-- "entry": [
<xsl:apply-templates select="//ccda:patientRole"/>
<xsl:apply-templates select="//ccda:encompassingEncounter"/>
<xsl:for-each select="//ccda:observation">
<xsl:apply-templates select="."/>
<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
] -->
"entry": [
<xsl:apply-templates select="//ccda:patientRole | //ccda:encompassingEncounter | //ccda:observation"/>
]
}
</xsl:template>

<!-- Patient Template -->
<xsl:template match="ccda:patientRole">
<xsl:if test="position() > 1">,</xsl:if>
{
"resource": {
"resourceType": "Patient",
"id": "<xsl:value-of select="ccda:id/ccda:root"/>",
"name": [
{
"use": "official",
"family": "<xsl:value-of select="ccda:patient/ccda:name/ccda:family"/>",
"given": [
"<xsl:value-of select="ccda:patient/ccda:name/ccda:given"/>"
],
"prefix": [
"<xsl:value-of select="ccda:patient/ccda:name/ccda:prefix"/>"
],
"suffix": [
"<xsl:value-of select="ccda:patient/ccda:name/ccda:suffix"/>"
]
}
],
"gender": "<xsl:choose>
<xsl:when test="ccda:patient/ccda:administrativeGenderCode/ccda:code = 'M'">male</xsl:when>
<xsl:when test="ccda:patient/ccda:administrativeGenderCode/ccda:code = 'F'">female</xsl:when>
<!-- <xsl:otherwise>unknown</xsl:otherwise> -->
<xsl:otherwise><xsl:value-of select="ccda:patient/ccda:administrativeGenderCode/ccda:code"/></xsl:otherwise>
</xsl:choose>",
<!-- "birthDate": "<xsl:value-of select="ccda:patient/ccda:birthTime/ccda:value"/>", -->
"birthDate": "<xsl:choose>
<xsl:when test='string-length(ccda:patient/ccda:birthTime/ccda:value) = 14'>
<xsl:value-of select='concat(substring(ccda:patient/ccda:birthTime/ccda:value, 1, 4), "-", substring(ccda:patient/ccda:birthTime/ccda:value, 5, 2), "-", substring(ccda:patient/ccda:birthTime/ccda:value, 7, 2), "T", substring(ccda:patient/ccda:birthTime/ccda:value, 9, 2), ":", substring(ccda:patient/ccda:birthTime/ccda:value, 11, 2), ":", substring(ccda:patient/ccda:birthTime/ccda:value, 13, 2))'/>
</xsl:when>
<xsl:when test='string-length(ccda:patient/ccda:birthTime/ccda:value) = 8'>
<xsl:value-of select='concat(substring(ccda:patient/ccda:birthTime/ccda:value, 1, 4), "-", substring(ccda:patient/ccda:birthTime/ccda:value, 5, 2), "-", substring(ccda:patient/ccda:birthTime/ccda:value, 7, 2))'/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='ccda:patient/ccda:birthTime/ccda:value'/>
</xsl:otherwise>
</xsl:choose>",
"address": [
{
"line": [
"<xsl:value-of select="ccda:addr/ccda:streetAddressLine"/>"
],
"city": "<xsl:value-of select="ccda:addr/ccda:city"/>",
"state": "<xsl:value-of select="ccda:addr/ccda:state"/>",
"postalCode": "<xsl:value-of select="ccda:addr/ccda:postalCode"/>"
}
],
"telecom": [
{
"system": "phone",
"value": "<xsl:value-of select="ccda:telecom/ccda:value"/>",
"use": "<xsl:value-of select="ccda:telecom/ccda:use"/>"
}
],
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-race",
"valueCodeableConcept": {
"coding": [
{
"system": "<xsl:value-of select="ccda:patient/ccda:raceCode/ccda:codeSystem"/>",
"code": "<xsl:value-of select="ccda:patient/ccda:raceCode/ccda:code"/>",
"display": "<xsl:value-of select="ccda:patient/ccda:raceCode/ccda:displayName"/>"
}
]
}
},
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-ethnicity",
"valueCodeableConcept": {
"coding": [
{
"system": "<xsl:value-of select="ccda:patient/ccda:ethnicGroupCode/ccda:codeSystem"/>",
"code": "<xsl:value-of select="ccda:patient/ccda:ethnicGroupCode/ccda:code"/>",
"display": "<xsl:value-of select="ccda:patient/ccda:ethnicGroupCode/ccda:displayName"/>"
}
]
}
},
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-language",
"valueCodeableConcept": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "<xsl:value-of select="ccda:patient/ccda:languageCommunication/ccda:languageCode/ccda:code"/>"
}
],
"text": "<xsl:value-of select="ccda:patient/ccda:languageCommunication/ccda:preferenceInd/ccda:value"/>"
}
}
]
}
}
</xsl:template>

<!-- Encounter Template -->
<xsl:template match="ccda:encompassingEncounter">
<xsl:if test="position() > 1">,</xsl:if>
{
"resource": {
"resourceType": "Encounter",
"id": "<xsl:value-of select="ccda:id/ccda:extension"/>",
"status": "finished",
"type": [
{
"coding": [
{
"system": "http://snomed.info/sct",
"code": "<xsl:value-of select="ccda:code/ccda:value"/>",
"display": "<xsl:value-of select="ccda:code/ccda:displayName"/>"
}
]
}
],
"period": {
"start": "<xsl:value-of select="ccda:effectiveTime/ccda:low/ccda:value"/>",
"end": "<xsl:value-of select="ccda:effectiveTime/ccda:high/ccda:value"/>"
}
}
}
</xsl:template>

<!-- Observation Template -->
<xsl:template match="ccda:observation">
<xsl:if test="position() > 1">,</xsl:if>
{
"resource": {
"resourceType": "Observation",
"id": "<xsl:value-of select='normalize-space(ccda:id)'/>",
"status": "<xsl:value-of select='ccda:statusCode/ccda:code'/>",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "<xsl:value-of select='ccda:code/ccda:code'/>",
"display": "<xsl:value-of select='ccda:code/ccda:displayName'/>"
}
]
},
"valueString": "<xsl:value-of select='ccda:value/ccda:displayName'/>",
"subject": {
"reference": "Patient/<xsl:value-of select='ancestor::ccda:ClinicalDocument/ccda:recordTarget/ccda:patientRole/ccda:id/ccda:root'/>"
},
"category": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "<xsl:value-of select='ccda:code/ccda:code'/>",
"display": "<xsl:value-of select='ccda:code/ccda:displayName'/>"
}
]
},
<!-- "effectiveDateTime": "<xsl:value-of select='ccda:effectiveTime/ccda:value'/>" -->
"effectiveDateTime": "<xsl:choose>
<xsl:when test='string-length(ccda:effectiveTime/ccda:value) > 14'>
<xsl:value-of select="
concat(
substring(ccda:effectiveTime/ccda:value, 1, 4), '-',
substring(ccda:effectiveTime/ccda:value, 5, 2), '-',
substring(ccda:effectiveTime/ccda:value, 7, 2), 'T',
substring(ccda:effectiveTime/ccda:value, 9, 2), ':',
substring(ccda:effectiveTime/ccda:value, 11, 2), ':',
substring(ccda:effectiveTime/ccda:value, 13, 2),
substring(ccda:effectiveTime/ccda:value, 15, 6)
)"/>
</xsl:when>
<xsl:when test='string-length(ccda:effectiveTime/ccda:value) = 14'>
<xsl:value-of select='concat(substring(ccda:effectiveTime/ccda:value, 1, 4), "-", substring(ccda:effectiveTime/ccda:value, 5, 2), "-", substring(ccda:effectiveTime/ccda:value, 7, 2), "T", substring(ccda:effectiveTime/ccda:value, 9, 2), ":", substring(ccda:effectiveTime/ccda:value, 11, 2), ":", substring(ccda:effectiveTime/ccda:value, 13, 2))'/>
</xsl:when>
<xsl:when test='string-length(ccda:effectiveTime/ccda:value) = 8'>
<xsl:value-of select='concat(substring(ccda:effectiveTime/ccda:value, 1, 4), "-", substring(ccda:effectiveTime/ccda:value, 5, 2), "-", substring(ccda:effectiveTime/ccda:value, 7, 2))'/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='ccda:effectiveTime/ccda:value'/>
</xsl:otherwise>
</xsl:choose>"
}
}
<!-- <xsl:if test="position() != last()">,</xsl:if> -->
</xsl:template>

</xsl:stylesheet>
3 changes: 3 additions & 0 deletions support/specifications/ccda/cda-phi-filter.xslt
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@
<codeSystem><xsl:value-of select="hl7:interpretationCode/@codeSystem"/></codeSystem>
<codeSystemName><xsl:value-of select="hl7:interpretationCode/@codeSystemName"/></codeSystemName>
</interpretationCode>
<value>
<displayName><xsl:value-of select="hl7:value/@displayName"/></displayName>
</value>

<!-- Include Subject Information only if exists -->
<xsl:if test="hl7:subject">
Expand Down

0 comments on commit a6d4d25

Please sign in to comment.