Skip to content

Commit

Permalink
Pilot testing updates (#3)
Browse files Browse the repository at this point in the history
* Fixes

* ORM messaging updates and fixes

* fix

* OCL path fix

* Location mapping updates

* IPMS pilot updates

* Resulting testing updates

* Pilot testing updates

* Fix
  • Loading branch information
pmanko authored May 8, 2024
1 parent 73d9757 commit 65f310c
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 21 deletions.
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"mediator": {
"api": {
"username": "[email protected]",
"password": "openhim",
"password": "instant101",
"apiURL": "https://openhim-core:8080",
"trustSelfSigned": true,
"urn": "urn:mediator:hl7v2tofhir_translator"
Expand Down
7 changes: 7 additions & 0 deletions data/templates/fhir/ADT_A04_TO_IPMS copy.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{#with msg.fhir}}
MSH|^~\&|DM||||{{date}}||ADT^A04|{{controlId}}|D|2.4|||AL|NE|
EVN||{{date}}|||ZZHGGMMO^Healthpost^Mmopane|{{date}}|
PID|1||NEW||{{patientFamilyName}}^{{patientFirstName.[0]}}^^^^^F||{{patientDob}}|{{patientSex}}||CT|{{patientStreetAddress}}^^{{patientCity}}^{{patientProvince}}^{{patientPostalCode}}||{{patientHomePhoneNumber}}^^^{{patientEmail}}|{{patientBusinessPhoneNumber}}||{{patientMaritalStatus}}|AC||{{patientOmang}}|
PV1|1|O|{{targetFacility.ipmsXlocation}}||||{{targetFacility.provider}}^^^^^^^^^^^^XX|||||||||||{{targetFacility.patientType}}||U|||||||||||||||||||{{targetFacility.name}}||{{targetFacility.patientStatus}}|||{{date}}|
ROL|1|AD|AT|{{providerId}}^{{providerLastName}}^{{providerFirstName.[0]}}|
{{/with}}
2 changes: 1 addition & 1 deletion data/templates/fhir/ADT_A04_TO_IPMS.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
MSH|^~\&|DM||||{{date}}||ADT^A04|{{controlId}}|D|2.4|||AL|NE|
EVN||{{date}}|||ZZHGGMMO^Healthpost^Mmopane|{{date}}|
PID|1||NEW||{{patientFamilyName}}^{{patientFirstName.[0]}}^^^^^F||{{patientDob}}|{{patientSex}}||CT|{{patientStreetAddress}}^^{{patientCity}}^{{patientProvince}}^{{patientPostalCode}}||{{patientHomePhoneNumber}}^^^{{patientEmail}}|{{patientBusinessPhoneNumber}}||{{patientMaritalStatus}}|AC||{{patientOmang}}|
PV1|1|O|HGGMMO||||ZZHGGMMO^Healthpost^Mmopane^^^^^^^^^^XX|||||||||||POV||U|||||||||||||||||||GGC||REG|||{{date}}|
PV1|1|O|{{targetFacility.ipmsXlocation}}||||{{targetFacility.provider}}^^^^^^^^^^^^XX|||||||||||{{targetFacility.patientType}}||U|||||||||||||||||||{{targetFacility.name}}||{{targetFacility.patientStatus}}|||{{date}}|
ROL|1|AD|AT|{{providerId}}^{{providerLastName}}^{{providerFirstName.[0]}}|
{{/with}}
6 changes: 3 additions & 3 deletions data/templates/fhir/ORM_O01_TO_IPMS.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{#with msg.fhir}}
MSH|^~\&|LAB||LAB||{{date}}||ORM^O01|{{controlId}}|D|2.4|||AL|NE|
MSH|^~\&|{{orderTypeFlag}}||{{orderTypeFlag}}||{{date}}||ORM^O01|{{controlId}}|D|2.4|||AL|NE|
PID|1||{{medicalRecordNumber}}^^^^MR^GGC~{{patientOmang}}^^^^SS^GGC~{{patientIdentifier}}^^^^PI^GGC~{{unknownIdentifier}}^^^^HUB^GGC||{{patientFamilyName}}^{{patientFirstName.[0]}}^^^^^L||{{patientDoB}}|{{sex}}||CT|{{patientStreetAddress}}^^{{patientCity}}^{{patientProvince}}^{{patientPostalCode}}||{{patientBusinessPhoneNumber}}|||{{maritalStatus}}||{{patientAccountNumber}}|
ORC|NW|{{labOrderId}}^LAB|{{medicalRecordNumber}}||FINAL||^^^^^R^||{{labOrderDatetime}}|||
OBR|1|{{labOrderId}}^LAB||{{labOrderMnemonic}}^{{labOrderName}}|R|{{labOrderDatetime}}|{{labOrderDatetime}}|||||||^^|{{providerId}}^{{providerLastName}}^{{providerFirstName.[0]}}^^^^^||
ORC|NW|{{labOrderId}}^{{orderTypeFlag}}|{{medicalRecordNumber}}||FINAL||^^^^^R^||{{labOrderDatetime}}|||
OBR|1|{{labOrderId}}^{{orderTypeFlag}}||{{labOrderMnemonic}}^{{labOrderName}}|R|{{labOrderDatetime}}|{{labOrderDatetime}}||||||||SPUTUM^^^SPUTUM|{{providerId}}^{{providerLastName}}^{{providerFirstName.[0]}}^^^^^||
{{/with}}
4 changes: 4 additions & 0 deletions data/templates/hl7v2/CodeSystem/IDType.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@
"code" : "IND",
"display" : "Indigenous/Aboriginal",
"system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
{{else if (eq inCode 'LAB')}},
"code" : "LAB",
"display" : "Laboratory Order ID",
"system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
{{else if (eq inCode 'LACSN')}},
"code" : "LACSN",
"display" : "Laboratory Accession ID",
Expand Down
49 changes: 49 additions & 0 deletions data/templates/hl7v2/DataType/CWECodeableConceptIpms.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"coding":
[
{
{{#if mapping}}
{{#with (evaluate mapping inCode=CWE-1)}}
"code":"{{code}}",
"display":"{{display}}",
"system":"{{system}}",
"version":"{{version}}",
{{/with}}
{{else}}
"code":"{{CWE-1}}",
"display":"{{CWE-2}}",
"system":"https://api.openconceptlab.org/orgs/I-TECH-UW/sources/IPMSLAB/",
"version":"{{CWE-7}}",
{{/if}}
},
{
{{#if mapping}}
{{#with (evaluate mapping inCode=CWE-4)}}
"code":"{{code}}",
"display":"{{display}}",
"system":"{{system}}",
"version":"{{version}}",
{{/with}}
{{else}}
"code":"{{CWE-4}}",
"display":"{{CWE-5}}",
"system":"https://api.openconceptlab.org/orgs/I-TECH-UW/sources/IPMSLAB/",
"version":"{{CWE-8}}",
{{/if}}
},
{
{{#if mapping}}
{{#with (evaluate mapping inCode=CWE-10)}}
"code":"{{code}}",
"display":"{{display}}",
"system":"{{system}}",
"version":"{{version}}",
{{/with}}
{{else}}
"code":"{{CWE-10}}",
"display":"{{CWE-11}}",
"system":"https://api.openconceptlab.org/orgs/I-TECH-UW/sources/IPMSLAB/",
"version":"{{CWE-13}}",
{{/if}}
},
],
"text":"{{CWE-9}}",
16 changes: 13 additions & 3 deletions data/templates/hl7v2/Resources/DiagnosticReport.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,26 @@
],
},
},
{ {{>DataType/EIIdentifier.hbs EI=OBR-2}} },
{ {{>DataType/EIIdentifier.hbs EI=OBR-3}} },
{{#if OBR-2}},
{
"system":"http://moh.bw.org/ext/identifier/lab-order-id",
{{>DataType/EIIdentifier.hbs EI=OBR-2}},
},
{{/if}},
{{#if OBR-3}},
{
"system":"http://moh.bw.org/ext/identifier/pi",
{{>DataType/EIIdentifier.hbs EI=OBR-3}},
},
{{/if}},
],
"effectiveDateTime":"{{formatAsDateTime ORC-9}}",
{{#if (not OBR-8)}},
"effectiveDateTime":"{{formatAsDateTime OBR-7}}",
{{/if}},
"code":
{
{{>DataType/CWECodeableConcept.hbs CWE=OBR-4}},
{{>DataType/CWECodeableConceptIpms.hbs CWE=OBR-4}},
},
"effectivePeriod":
{
Expand Down
4 changes: 2 additions & 2 deletions debug.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
container_name: built-fhir-converter
hostname: fhir-converter
restart: unless-stopped
image: ghcr.io/b-techbw/openhim-mediator-fhir-converter:local
image: itechuw/openhim-mediator-fhir-converter:debug
build: ./
ports:
- 2019:2019
Expand All @@ -32,4 +32,4 @@ services:
networks:
hie:
external: true
name: hie-botswana_hie
name: openhim_public
73 changes: 63 additions & 10 deletions src/lib/fhir/fhir.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,66 @@ module.exports = class fhir extends dataHandler {
let entry = bundle.entry.find(e => e.resource.resourceType == resourceName)
return (entry && entry.resource) ? entry.resource : null
} catch (e) {
logger.error(`Can't get ${resourceName} from \n${JSON.stringify(bundle)}`)
console.log(`Can't get ${resourceName} from \n${JSON.stringify(bundle)}`)
return null
}
}

getSourceLocation(bundle) {
try {
let task = this.getResource(bundle, "Task")
const sourceLocationId = task.requester ? task.requester.reference.split('/')[1] : null

let sourceLocation = bundle.entry.find(e => e.resource.resourceType == "Location" && e.resource.id == sourceLocationId)
if(sourceLocation && sourceLocation.resource) {
return sourceLocation.resource.name
}
} catch (error) {
console.log(`Can't get source location from \n${JSON.stringify(bundle)}`)
}
return null
}

/** Set IPMS-specific location mappings */
setIpmsLocationInformation(bundle, res) {
try {
let task = this.getResource(bundle, "Task")
const targetLocationId = task.location ? task.location.reference.split('/')[1] : null

let targetLocation = bundle.entry.find(e => e.resource.resourceType == "Location" && e.resource.id == targetLocationId)
if(targetLocation && targetLocation.resource) {
let target = targetLocation.resource
let provider = target.extension.find(e => e && e.url && e.url.includes("ipms-provider") && e.valueString)
let patientType = target.extension.find(e => e && e.url && e.url.includes("ipms-patient-type") && e.valueString)
let patientStatus = target.extension.find(e => e && e.url && e.url.includes("ipms-patient-status") && e.valueString)
let ipmsXlocation = target.extension.find(e => e && e.url && e.url.includes("ipms-xlocation") && e.valueString)

res.targetFacility = {
name: target.name,
provider: provider ? provider.valueString : "",
patientType: patientType ? patientType.valueString : "",
patientStatus: patientStatus ? patientStatus.valueString : "",
ipmsXlocation: ipmsXlocation ? ipmsXlocation.valueString : ""
}
}
} catch (error) {
console.log(`Can't get target location information from \n${JSON.stringify(bundle)}`)
}
console.log(`Target facility: ${JSON.stringify(res.targetFacility)}`)
return res
}

parseAdt(bundle) {
let res = {};
let patient = this.getResource(bundle, "Patient");
let sourceLocation = this.getResource(bundle, "Location");
let provider = this.getResource(bundle, "Practitioner");;
let sourceLocation = this.getSourceLocation(bundle);
let provider = this.getResource(bundle, "Practitioner");

res = this.setPatientData(patient, res);
res = this.setProviderData(provider, res);
res = this.setIpmsLocationInformation(bundle, res);

res.facilityId = sourceLocation ? sourceLocation.id : "";
res.facilityId = sourceLocation ? sourceLocation : "";
res.kinFamilyName = "";
res.kinFirstName = "";
res.kinRelCode = "";
Expand All @@ -79,6 +124,7 @@ module.exports = class fhir extends dataHandler {
res.kinCity = "";
res.kinProvince = "";
res.kinPostalCode = "";

return res;
}
parseOrm(bundle) {
Expand All @@ -95,7 +141,8 @@ module.exports = class fhir extends dataHandler {
res = this.setProviderData(provider, res);

res.facilityId = sourceLocation ? sourceLocation.id : "";
res.labOrderId = task.identifier ? task.identifier[0].value : "";
res.labOrderId = serviceRequest ? serviceRequest.id : "";

let orderDateTime = new Date()
try {
orderDateTime = serviceRequest.authoredOn ? new Date(serviceRequest.authoredOn) : (task.authoredOn ? new Date(task.authoredOn) : orderDateTime)
Expand All @@ -109,8 +156,13 @@ module.exports = class fhir extends dataHandler {
let ipmsCode = serviceRequest.code.coding.find(e => e.system == "https://api.openconceptlab.org/orgs/I-TECH-UW/sources/IPMSLAB/")
res.labOrderMnemonic = ipmsCode && ipmsCode.code ? ipmsCode.code : "";
res.labOrderName = ipmsCode && ipmsCode.display ? ipmsCode.display : "";
if(ipmsCode && ipmsCode.extension && ipmsCode.extension.length > 0) {
let orderTypeFlag = ipmsCode.extension.find(e => e && e.url && e.url.includes("ipms-order-type") && e.valueString)
res.orderTypeFlag = orderTypeFlag ? orderTypeFlag.valueString : "LAB";
}
}


return res;
}

Expand All @@ -119,12 +171,13 @@ module.exports = class fhir extends dataHandler {
res.patientDob = patient.birthDate.split('-').join('');
res.patientSex = patient.gender && patient.gender == 'male' ? "M" : "F";

if(patient.address){
res.patientStreetAddress = patient.address.length > 0 && patient.address[0].line.length > 0 ? patient.address[0].line[0] : "";
res.patientCity = patient.address.length > 0 ? patient.address[0].city : "";
res.patientProvince = patient.address.length > 0 ? patient.address[0].state : "";
res.patientPostalCode = patient.address.length > 0 ? patient.address[0].postalCode : "";
if(patient.address && patient.address.length > 0){
res.patientStreetAddress = patient.address[0].line && patient.address[0].line.length > 0 ? patient.address[0].line[0] : "";
res.patientCity = patient.address[0].city || "";
res.patientProvince = patient.address[0].state || "";
res.patientPostalCode = patient.address[0].postalCode || "";
}

res.patientMaritalStatus = patient.maritalStatus && patient.maritalStatus.coding.length > 0 ? patient.maritalStatus.coding[0].code : "";

let q;
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@
// "skipLibCheck": true, /* Skip type checking of declaration files. */
// "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": ["src/**/*"],
"include": ["src/**/*", "src/lib/**/*"],
"exclude" : ["src/**/__tests__"]
}

0 comments on commit 65f310c

Please sign in to comment.