From 3bb8aedbfbbcbbfb1949c220835a05ca09d1c8f8 Mon Sep 17 00:00:00 2001 From: Luke Duncan Date: Fri, 8 Jun 2018 20:51:28 +0000 Subject: [PATCH] Added in initial sync script for DHIS2->Hearth in mCSD/FHIR format. --- dhis2sync/loadDHIS2Metadata.js | 191 +++++++++++++++++++++++++ dhis2sync/loadDHIS2MetadataConfig.json | 14 ++ dhis2sync/package.json | 14 ++ 3 files changed, 219 insertions(+) create mode 100644 dhis2sync/loadDHIS2Metadata.js create mode 100644 dhis2sync/loadDHIS2MetadataConfig.json create mode 100644 dhis2sync/package.json diff --git a/dhis2sync/loadDHIS2Metadata.js b/dhis2sync/loadDHIS2Metadata.js new file mode 100644 index 000000000..c6d5203b1 --- /dev/null +++ b/dhis2sync/loadDHIS2Metadata.js @@ -0,0 +1,191 @@ +var nconf = require('nconf') +var http = require('http') +var https = require('https') +var url = require('url') + + +nconf.argv().file( { file: './loadDHIS2MetadataConfig.json' } ) + +let uflag = 'false' +if ( nconf.get('dhis2:dousers') ) { + uflag = 'true' +} +let sflag = 'false' +if ( nconf.get('dhis2:doservices') ) { + sflag = 'true' +} + +const metadataOpts = [ + 'assumeTrue=false', + 'organisationUnits=true', + 'organisationUnitGroups=true', + 'organisationUnitLevels=true', + 'organisationUnitGroupSets=true', + "categoryOptions="+sflag, + "optionSets="+sflag, + "dataElementGroupSets="+sflag, + "categoryOptionGroupSets="+sflag, + "categoryCombos="+sflag, + "options="+sflag, + "categoryOptionCombos="+sflag, + "dataSets="+sflag, + "dataElementGroups="+sflag, + "dataElements="+sflag, + "categoryOptionGroups="+sflag, + "categories="+sflag, + "users="+uflag, + "userGroups="+uflag, + "userRoles="+uflag, +] + +const dhis2URL = url.parse( nconf.get('dhis2:url') ) +let auth = 'Basic ' + Buffer.from( nconf.get('dhis2:user') + ':' + nconf.get('dhis2:pass') ).toString('base64') + +let req = (dhis2URL.protocol == 'https:' ? https : http).request({ + hostname: dhis2URL.hostname, + port: dhis2URL.port, + path: dhis2URL.path + '/api/metadata.json?' + metadataOpts.join('&'), + headers: { + Authorization: auth + }, + method: 'GET' +}, (res) => { + console.log('STATUS: '+res.statusCode) + console.log('HEADERS: ' +JSON.stringify(res.headers,null,2)) + var body = '' + res.on('data', (chunk) => { + body += chunk + }) + res.on('end', () => { + let metadata = JSON.parse(body); + processOrgUnit( metadata, 0, metadata.organisationUnits.length ) + }) + res.on('error', (e) => { + console.log('ERROR: ' +e.message) + }) +}).end() + +function processOrgUnit( metadata, i, max ) { + org = metadata.organisationUnits[i] + console.log("Processing ("+i+"/"+max+") "+org.id) + let fhir = { + resourceType: 'Location', + id: org.id, + status: "active", + mode: "instance" + } + fhir.identifier = [ + { system: "http://dhis2.org/code", + value: org.code }, + { system: "http://dhis2.org/id", + value: org.id } + ] + fhir.meta = { + lastUpdated: org.lastUpdated + } + let path = org.path.split('/') + let level = metadata.organisationUnitLevels.find( x => x.level == path.length-1 ) + fhir.meta.tag = [ + { + system: "http://test.geoaling.datim.org/organistionUnitLevels", + code: level.id, + display: level.name + } + ] + fhir.name = org.name + fhir.alias = [ org.shortName ] + if ( metadata.organisationUnits.find( x => x.parent && x.parent.id && x.parent.id == org.id ) ) { + fhir.physicalType = { + coding: [ + { system: "http://hl7.org/fhir/location-physical-type", + code: "area", + display: "Area", + } + ], + text: "Administrative Area" + } + } else { + fhir.physicalType = { + coding: [ + { system: "http://hl7.org/fhir/location-physical-type", + code: "bu", + display: "Building", + } + ], + text: "Facility" + } + } + + if ( org.featureType == 'POINT' && org.coordinates ) { + try { + coords = JSON.parse( org.coordinates ) + fhir.position = { + longitude: coords[1], + latitude: coords[0] + } + } catch( e ) { + console.log("Failed to load coordinates. "+e.message) + } + } + if ( org.parent ) { + fhir.partOf = { reference: "Location/" + org.parent.id } + } + if ( org.attributeValues ) { + for( let attr of org.attributeValues ) { + if ( attr.attribute.id == 'XxZsKNpu4nB' ) { + fhir.identifier.push( { + system: "http://dhis2.org/mohid", + value: attr.value + } ) + } + if ( attr.attribute.id == 'Ed6SCy0OXfx' ) { + fhir.identifier.push( { + system: "http://dhis2.org/mohcode", + value: attr.value + } ) + } + } + } + + const ilrURL = url.parse( nconf.get('ilr:url') ) + let auth = 'Basic ' + Buffer.from( nconf.get('ilr:user') + ':' + nconf.get('ilr:pass') ).toString('base64') + + console.log("Sending FHIR to " +ilrURL.hostname+" "+ilrURL.port+" "+ilrURL.path+"/Location/"+fhir.id) + let req = (ilrURL.protocol == 'https:' ? https : http).request({ + hostname: ilrURL.hostname, + port: ilrURL.port, + path: ilrURL.path + '/Location/'+ fhir.id, + headers: { + 'Content-Type': 'application/fhir+json' + //Authorization: auth + }, + method: 'PUT' + }, (res) => { + console.log('STATUS: '+res.statusCode) + console.log('HEADERS: '+JSON.stringify(res.headers)) + var body = '' + res.on('data', (chunk) => { + body += chunk + }) + res.on('end', () => { + console.log(body) + }) + res.on('error', (e) => { + console.log('ERROR: ' + e.message) + }) + }) + req.on('error', (e) => { + console.log("REQ ERROR: "+e.message) + }) + req.write(JSON.stringify(fhir)) + req.end() + + if ( ++i < max ) { + // Had to do it this way to free up the event loop + // so the request can go out before the entire + // data set is processed. + setTimeout( () => { processOrgUnit( metadata, i, max ) }, 0 ) + } + +} + diff --git a/dhis2sync/loadDHIS2MetadataConfig.json b/dhis2sync/loadDHIS2MetadataConfig.json new file mode 100644 index 000000000..7c1293382 --- /dev/null +++ b/dhis2sync/loadDHIS2MetadataConfig.json @@ -0,0 +1,14 @@ +{ + "ilr": { + "url": "", + "user": "", + "pass": "" + }, + "dhis2": { + "url": "", + "user": "", + "pass": "", + "dousers": false, + "doservices": true + } +} diff --git a/dhis2sync/package.json b/dhis2sync/package.json new file mode 100644 index 000000000..e62d0fe43 --- /dev/null +++ b/dhis2sync/package.json @@ -0,0 +1,14 @@ +{ + "name": "dhis2sync", + "version": "1.0.0", + "description": "", + "main": "loadDHIS2Metadata.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "dependencies": { + "nconf": "^0.10.0" + } +}