Skip to content

Commit

Permalink
Update BW laboratory workflows for #34 (#35)
Browse files Browse the repository at this point in the history
* Updated laboratory workflows support

* Yarn update

* TS fixes

* Token update

* Test fixes and updates
  • Loading branch information
pmanko authored Feb 5, 2022
1 parent 2f9cad8 commit 9dbf315
Show file tree
Hide file tree
Showing 19 changed files with 1,375 additions and 1,258 deletions.
25 changes: 0 additions & 25 deletions app.docker-compose.yml

This file was deleted.

11 changes: 10 additions & 1 deletion ci.docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '2.4'
version: '3.9'

# Docker Compose for Github CI setup
services:
Expand Down Expand Up @@ -101,6 +101,15 @@ services:
- zookeeper
networks:
- test
# HL7 Converter
fhir-converter:
container_name: fhir-converter
hostname: fhir-converter
restart: unless-stopped
image: ghcr.io/b-techbw/openhim-mediator-fhir-converter:v3.1.0
volumes:
- ./config/fhir-converter/config.json:/app/config.json

# Not necessary
openhim-console:
image: jembi/openhim-console:latest
Expand Down
124 changes: 124 additions & 0 deletions config/fhir-converter/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"auth": {
"secret": "23221o43-71bc-4247-86e4-ea21aaf89c28",
"tokenDuration": 5400
},
"logLevel": "info",
"app": {
"port": 2019
},
"mediator": {
"api": {
"username": "[email protected]",
"password": "openhim",
"apiURL": "https://openhim-core:8080",
"trustSelfSigned": true,
"urn": "urn:mediator:hl7v2tofhir_translator"
}
},
"mediatorConfig": {
"urn": "urn:mediator:hl7v2tofhir_translator",
"version": "2.3.4",
"name": "HL7v2 to FHIR Translator",
"description": "HL7v2 to FHIR Translator",
"defaultChannelConfig": [
{
"methods": [
"GET",
"POST",
"PUT",
"PATCH"
],
"type": "http",
"whitelist": [],
"authType": "private",
"matchContentTypes": [],
"properties": [],
"txViewAcl": [],
"txViewFullAcl": [],
"txRerunAcl": [],
"status": "enabled",
"rewriteUrls": false,
"addAutoRewriteRules": true,
"autoRetryEnabled": false,
"autoRetryPeriodMinutes": 60,
"requestBody": true,
"responseBody": true,
"name": "HL7v2 Translator API Passthrough",
"description": "HL7v2 Translator API Passthrough",
"urlPattern": "^/72f/.*$",
"routes": [
{
"type": "http",
"status": "enabled",
"forwardAuthHeader": false,
"name": "Send to Translator ",
"secured": false,
"host": "fhir-converter",
"port": 2019,
"path": "",
"pathTransform": "s/72f/api/g",
"primary": true,
"username": "",
"password": ""
}
],
"alerts": [],
"rewriteUrlsConfig": [],
"priority": 4
},
{
"methods": [
"POST"
],
"type": "http",
"whitelist": [],
"authType": "private",
"matchContentTypes": [],
"properties": [],
"txViewAcl": [],
"txViewFullAcl": [],
"txRerunAcl": [],
"status": "enabled",
"rewriteUrls": false,
"addAutoRewriteRules": true,
"autoRetryEnabled": false,
"autoRetryPeriodMinutes": 60,
"requestBody": true,
"responseBody": true,
"name": "FHIR --> HL7v2 API",
"description": "FHIR to HL7v2 Translation",
"urlPattern": "^/f27/.*$",
"routes": [
{
"type": "http",
"status": "enabled",
"forwardAuthHeader": false,
"name": "Send to Translator ",
"secured": false,
"host": "fhir-converter",
"port": 2019,
"path": "",
"pathTransform": "s/f27/api\/convert\/fhir/g",
"primary": true,
"username": "",
"password": ""
}
],
"priority": 5
}
],
"endpoints": [
{
"name": "HL7v2 to FHIR Translator",
"host": "fhir-converter",
"port": 2019,
"type": "http",
"primary": true,
"forwardAuthHeader": false,
"status": "enabled",
"path": "api"
}
]
}
}
52 changes: 38 additions & 14 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
version: '2.4'

## Port Assignments:
## See .env file
version: '3.9'

## Container debugging:
# 1. append the following lines to desired container
Expand All @@ -12,29 +9,56 @@ version: '2.4'
# stdin_open: true
# entrypoint: bash

## Utility for booting up placeholder page:
# `docker run --hostname openhim-placeholder --network shared-health-record_sedish --name openhim-placeholder -e MESSAGE=OPENHIM-PLACEHOLDER -e PORT=3000 -d docker.io/sroze/landing-page:latest`

services:
# shr: Run natively using yarn, or see docker-compose.yml
shr:
hostname: shr
container_name: shr
build: ./
hostname: shr
build: .
ports:
- "3000:3000"
restart: on-failure
- 3000:3000
environment:
- NODE_ENV=docker
volumes:
- ./config/config_development.json:/app/config/config_docker.json
- ./config/mediator_development.json:/app/config/mediator_docker.json
networks:
- hie
- hie
profiles: ["shr"]

shr-fhir:
image: "hapiproject/hapi:latest"
container_name: shr-fhir
hostname: shr-fhir
image: hapiproject/hapi:latest
restart: unless-stopped
volumes:
- hapi-data:/data/hapi
networks:
- hie
profiles: ["dev"]
ports:
- "8080:8080"
- 8090:8080

# Kafka Task Runners
zookeeper:
image: 'bitnami/zookeeper:latest'
hostname: zookeeper
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: 'bitnami/kafka:latest'
hostname: kafka
ports:
- '9092:9092'
environment:
- KAFKA_BROKER_ID=1
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
volumes:
- /bitnami/kafka
networks:
hie:
external: true
Expand Down
102 changes: 3 additions & 99 deletions src/workflows/lab-bw.ts → src/lib/ipmsDataGen.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,8 @@
"use strict"

import { R4 } from "@ahryman40k/ts-fhir-types";
import got from "got";
import logger from "../lib/winston";
import { LaboratoryWorkflows } from "./lab";
import { v4 as uuidv4 } from 'uuid';
import { sendPayload } from "../lib/kafka"

export class LaboratoryWorkflowsBw extends LaboratoryWorkflows {
static async handleBwLabOrder(orderBundle: R4.IBundle, resultBundle: R4.IBundle) {
try {
sendPayload({bundle: orderBundle, response: resultBundle}, "map-concepts")
} catch (e) {
logger.error(e)
}
}

// Add coding mappings info to bundle
static async addBwCodings(bundle: R4.IBundle): Promise<R4.IBundle> {
try {
for (const e of bundle.entry!) {
if (e.resource && e.resource.resourceType == "ServiceRequest" && e.resource.basedOn) {
e.resource = await this.translatePimsCoding(e.resource)
}
}
} catch (e) {
logger.error(e)
}

return bundle
}

// Add location info to bundle
static async addBwLocations(bundle: R4.IBundle): Promise<R4.IBundle> {
try {
for (const e of bundle.entry!) {
if (e.resource && e.resource.resourceType == "ServiceRequest" && e.resource.basedOn) {
e.resource = await this.translateLocations(e.resource)
}
}
} catch (e) {
logger.error(e)
}

return bundle
}


static async translatePimsCoding(sr: R4.IServiceRequest): Promise<R4.IServiceRequest> {
try {
let pimsCoding: R4.ICoding = <R4.ICoding>sr.code!.coding!.find(e => e.system &&
e.system == "https://api.openconceptlab.org/orgs/B-TECHBW/sources/PIMS-LAB-TEST-DICT/")
let pimsCode: string = pimsCoding.code!

let ipmsMapping: any = await got.get(`https://api.openconceptlab.org/orgs/B-TECHBW/sources/IPMS-LAB-TEST/mappings?toConcept=${pimsCode}&toConceptSource=PIMS-LAB-TEST-DICT`).json()
let ipmsCode: string = ipmsMapping[0].from_concept_code
if (ipmsMapping.length > 0) {
sr.code!.coding!.push({
system: "https://api.openconceptlab.org/orgs/B-TECHBW/sources/IPMS-LAB-TEST/",
code: ipmsCode,
display: ipmsMapping[0].from_concept_name_resolved
})
}

let cielMapping: any = await got.get(`https://api.openconceptlab.org/orgs/B-TECHBW/sources/IPMS-LAB-TEST/mappings/?toConceptSource=CIEL&fromConcept=${ipmsCode}`).json()
let cielCode: string = cielMapping[0].to_concept_code
if (cielMapping.length > 0) {
sr.code!.coding!.push({
system: "https://api.openconceptlab.org/orgs/CIEL/sources/CIEL/",
code: cielCode,
display: cielMapping[0].to_concept_name_resolved
})
}

let loincMapping = got.get(`https://api.openconceptlab.org/sources/CIEL/mappings/?toConceptSource=LOINC&fromConcept=${cielCode}&mapType=SAME-AS`).json()
loincMapping.catch(logger.error).then((lm: any) => {
if (lm.length > 0) {
let loinCode: string = lm[0].to_concept_code
sr.code!.coding!.push({
system: "https://api.openconceptlab.org/orgs/Regenstrief/sources/LOINC/",
code: loinCode
})
}
})

} catch (e) {
logger.error(`Could not translate ServiceRequest codings: \n ${e}`)
}
return sr
}

static async translateLocations(sr: R4.IServiceRequest): Promise<R4.IServiceRequest> {
logger.info("Not Implemented yet!")

return sr
}

static generateIpmsResults(entries: R4.IBundle_Entry[]): R4.IBundle_Entry[] {
export class IpmsDataGen {
static generateIpmsResults(entries: R4.IBundle_Entry[]): R4.IBundle_Entry[] {
let generatedResults: R4.IBundle_Entry[] = []

for (let entry of entries) {
Expand Down Expand Up @@ -219,6 +125,4 @@ export class LaboratoryWorkflowsBw extends LaboratoryWorkflows {
result: [{ reference: "Observation/" + obsId }]
}
}
}


}
4 changes: 2 additions & 2 deletions src/routes/hl7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import got from "got/dist/source";
import URI from "urijs";
import config from "../lib/config";
import logger from "../lib/winston";
import Hl7Workflows from '../workflows/hl7';
import Hl7WorkflowsBw from '../workflows/hl7WorkflowsBw';

const querystring = require('querystring');

Expand All @@ -18,7 +18,7 @@ router.post('/oru', async (req: Request, res: Response) => {
try {
let hl7Msg = req.body.trim()

let resultBundle: R4.IBundle = await Hl7Workflows.saveOruMessage(hl7Msg)
let resultBundle: R4.IBundle = await Hl7WorkflowsBw.saveOruMessage(hl7Msg)

return res.status(200).json(resultBundle)

Expand Down
4 changes: 2 additions & 2 deletions src/routes/lab-bw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { R4 } from '@ahryman40k/ts-fhir-types'
import config from '../lib/config'
import { invalidBundleMessage, invalidBundle } from "../lib/helpers"
import { saveLabBundle } from '../hapi/lab';
import { LaboratoryWorkflowsBw } from "../workflows/lab-bw"
import { LabWorkflowsBw } from "../workflows/labWorkflowsBw"
import { or } from "ip"

export const router = express.Router()
Expand All @@ -26,7 +26,7 @@ router.all('/', async (req: Request, res: Response) => {
let resultBundle: R4.IBundle = (await saveLabBundle(orderBundle))

// Trigger Background Tasks
LaboratoryWorkflowsBw.handleBwLabOrder(orderBundle, resultBundle)
LabWorkflowsBw.handleBwLabOrder(orderBundle, resultBundle)

return res.status(200).json(resultBundle)
} catch (e) {
Expand Down
Loading

0 comments on commit 9dbf315

Please sign in to comment.