Produced by Araxis Merge on 10/3/2017 11:15:28 AM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.
| # | Location | File | Last Modified |
|---|---|---|---|
| 1 | ehmp.zip\ehmp\ehmp\product\production\NodeMockServices\mockHdrPubSub | mockHdr.js | Tue Jan 10 16:20:50 2017 UTC |
| 2 | ehmp.zip\ehmp\ehmp\product\production\NodeMockServices\mockHdrPubSub | mockHdr.js | Mon Oct 2 19:38:58 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 5 | 1670 |
| Changed | 4 | 8 |
| Inserted | 0 | 0 |
| Removed | 0 | 0 |
| Whitespace | |
|---|---|
| Character case | Differences in character case are significant |
| Line endings | Differences in line endings (CR and LF characters) are ignored |
| CR/LF characters | Not shown in the comparison detail |
No regular expressions were active.
| 1 | 'use stric t'; | |
| 2 | ||
| 3 | var yargs = require( 'yargs'); | |
| 4 | var expres s = requir e('express '); | |
| 5 | var bodyPa rser = req uire('body -parser'); | |
| 6 | var _ = re quire('und erscore'); | |
| 7 | var moment = require ('moment') ; | |
| 8 | var fs = r equire('fs '); | |
| 9 | var config = require ('./config '); | |
| 10 | ||
| 11 | var log = require('b unyan').cr eateLogger (config.lo gger); | |
| 12 | ||
| 13 | var port = config.po rt; | |
| 14 | ||
| 15 | log.debug( 'mockHdr: Starting u p...'); | |
| 16 | ||
| 17 | var app = express(); | |
| 18 | ||
| 19 | var statio nNumbersTo SiteHash = {}; | |
| 20 | ||
| 21 | var sites = initiali zeSites(); | |
| 22 | //Example of sites s tructure: | |
| 23 | /* | |
| 24 | sites = { | |
| 25 | '84F0' : { | |
| 26 | 's tationNumb er': 578, | |
| 27 | 's iteId': '8 4F0', | |
| 28 | '_ lastUpdate ': { | |
| 29 | prefix: '3', | |
| 30 | moment: moment().f ormat('YYM MDD'), | |
| 31 | hits: 0 | |
| 32 | }, | |
| 33 | 'd omain': 'R APHAEL.VIS TACORE.US' , | |
| 34 | 'l astUpdate' : 0, | |
| 35 | 'u pdated': m oment().fo rmat('YYYY MMDDHHmmss '), | |
| 36 | 'w aitingPids ': [], | |
| 37 | 'p rocessingP ids': [], | |
| 38 | 'w aitingIcns ': [], | |
| 39 | 'w aitingPoll Data': [], | |
| 40 | 'p atientsSub scribed': { | |
| 41 | '1-578-U SVHA': { | |
| 42 | 'ide ntifier': '1-578-USV HA', | |
| 43 | 'pid ': '84F0;1 ', | |
| 44 | 'dom ainsSynced ': { | |
| 45 | 'allergy': '20150826 121648' | |
| 46 | } | |
| 47 | } | |
| 48 | } | |
| 49 | } | |
| 50 | } | |
| 51 | */ | |
| 52 | ||
| 53 | var domain s = config .domains | | ['allerg y', 'patie nt']; | |
| 54 | ||
| 55 | process.on ('exit', f unction() { | |
| 56 | saveAn dExit(); | |
| 57 | }); | |
| 58 | ||
| 59 | process.on ('SIGINT', function( ) { | |
| 60 | saveAn dExit(); | |
| 61 | }); | |
| 62 | ||
| 63 | process.on ('SIGQUIT' , function () { | |
| 64 | saveAn dExit(); | |
| 65 | }); | |
| 66 | ||
| 67 | process.on ('SIGTERM' , function () { | |
| 68 | saveAn dExit(); | |
| 69 | }); | |
| 70 | ||
| 71 | app.use(bo dyParser.j son()); | |
| 72 | ||
| 73 | app.get('/ ping', fun ction(req, res) { | |
| 74 | res.se nd('pong') ; | |
| 75 | }); | |
| 76 | ||
| 77 | //HDR inte rface | |
| 78 | //Subscrib e | |
| 79 | app.post(' /repositor ies. URL /fpds/vpr/ subscribe' , [validat eSubscribe Params, ha ndleSubscr ibe]); | |
| 80 | //Poll | |
| 81 | app.get('/ repositori es. URL /fpds/vpr/ patientdat a/:siteId' , [validat ePollParam s, handleP oll]); | |
| 82 | //Unsubscr ibe | |
| 83 | app.post(' /repositor ies. URL /fpds/vpr/ cancel', [ validateUn subscribeP arams, han dleUnsubsc ribe]); | |
| 84 | ||
| 85 | //Not part of the re al HDR int erface | |
| 86 | //Clear al l subscrip tions | |
| 87 | app.post(' /repositor ies. URL /fpds/vpr/ cancel/all ', handleU nsubscribe All); | |
| 88 | //Unsolici ted update | |
| 89 | app.post(' /update', [validateU nsolicited Update, ha ndleUnsoli citedUpdat e]); | |
| 90 | ||
| 91 | app.listen (port); | |
| 92 | log.debug( 'mockHdr: Listening on port %s ', port); | |
| 93 | ||
| 94 | function i nitializeS ites() { | |
| 95 | var si tes; | |
| 96 | log.de bug('Check ing if sav e data fil e exists.. .'); | |
| 97 | try { | |
| 98 | si tes = requ ire(config .saveDataP ath + '/da ta'); | |
| 99 | if (sites) { | |
| 100 | log.debu g('Success fully load ed subscri ption data .'); | |
| 101 | } | |
| 102 | } catc h (e) { | |
| 103 | lo g.debug('C ould not o pen save d ata file. (Got error : %s) Init ializing d ata...', e ); | |
| 104 | si tes = requ ire('./ini tializeDat a'); | |
| 105 | ||
| 106 | _. each(sites , function (site) { | |
| 107 | site._la stUpdate = { | |
| 108 | pref ix: '3', | |
| 109 | mome nt: moment ().format( 'YYMMDD'), | |
| 110 | hits : 0 | |
| 111 | }; | |
| 112 | site.upd ated = mom ent().form at('YYYYMM DDHHmmss') ; | |
| 113 | ||
| 114 | site.las tUpdate = getLastUpd ate(site); | |
| 115 | }) ; | |
| 116 | } | |
| 117 | ||
| 118 | _.each (sites, fu nction(sit e) { | |
| 119 | st ationNumbe rsToSiteHa sh[site.st ationNumbe r] = site. siteId; | |
| 120 | }); | |
| 121 | ||
| 122 | log.de bug('Sites : %s', JSO N.stringif y(sites)); | |
| 123 | return sites; | |
| 124 | } | |
| 125 | ||
| 126 | function s aveAndExit () { | |
| 127 | try { | |
| 128 | fs .writeFile Sync(confi g.saveData Path + '/d ata.json', JSON.stri ngify(site s)); | |
| 129 | } catc h (e) { | |
| 130 | lo g.debug('E rror: Coul d not save data. Got : %s', e); | |
| 131 | } | |
| 132 | ||
| 133 | proces s.exit(); | |
| 134 | } | |
| 135 | ||
| 136 | function g etLastUpda te(site) { | |
| 137 | var la stUpdate = site._las tUpdate; | |
| 138 | return lastUpdat e.prefix + lastUpdat e.moment.t oString() + '-' + la stUpdate.h its; | |
| 139 | } | |
| 140 | ||
| 141 | function v alidateCom monRequest Params(req , res) { | |
| 142 | if (!r eq.param(' server')) { // check ing the se rver param eter | |
| 143 | re s.status(4 00).send(' Missing re quired par ameter: \' server\'') ; | |
| 144 | re turn false ; | |
| 145 | } | |
| 146 | if (!r eq.param(' clientName ')) { // c hecking th e clientNa me paramet er | |
| 147 | re s.status(4 00).send(' Missing re quired par ameter: \' clientName \''); | |
| 148 | re turn false ; | |
| 149 | } | |
| 150 | if (!r eq.param(' requestId' )) { | |
| 151 | re s.status(4 00).send(' Missing re quired par ameter: \' requestId\ ''); | |
| 152 | re turn false ; | |
| 153 | } | |
| 154 | if (!r eq.param(' clientRequ estInitiat ionTime')) { | |
| 155 | re s.status(4 00).send(' Missing re quired par ameter: \' clientRequ estInitiat ionTime\'' ); | |
| 156 | re turn false ; | |
| 157 | } | |
| 158 | return true; | |
| 159 | } | |
| 160 | ||
| 161 | function v alidateSub scribePara ms(req, re s, next) { | |
| 162 | if (!v alidateCom monRequest Params(req , res)) { | |
| 163 | re turn; | |
| 164 | } | |
| 165 | if (!r eq.param(' resolvedId entifier') || !verif yResolvedI dentifier( req.param( 'resolvedI dentifier' ))) { | |
| 166 | re turn res.s tatus(400) .send('Mis sing patie nt identif ier in for mat DFN-St ationNumbe r-USVHA'); | |
| 167 | } | |
| 168 | if (!r eq.param(' rootJobId' )) { | |
| 169 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'roo tJobId\'') ; | |
| 170 | } | |
| 171 | // log ic to hand le the ver sion infor mation | |
| 172 | if (ha sVersionIn fo(req)) { | |
| 173 | va r jobDomai nId = getJ obDomainId (req); | |
| 174 | if (_.isEmpt y(jobDomai nId)) { | |
| 175 | return r es.status( 400).send( 'Missing r equired pa rameter: \ 'jobDomain Id-domain\ ''); | |
| 176 | } | |
| 177 | } | |
| 178 | else i f (!req.pa ram('jobId ')) { | |
| 179 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'job Id\''); | |
| 180 | } | |
| 181 | ||
| 182 | next() ; | |
| 183 | } | |
| 184 | ||
| 185 | // Utility function to check i f there is any domai n job id i nformation | |
| 186 | function h asVersionI nfo(req) { | |
| 187 | return req.param ('HMPSVERS '); | |
| 188 | } | |
| 189 | ||
| 190 | // this fu nction wil l look up for jobDom ainId-<dom ain> param s in req.p arams, bod y, and que ry | |
| 191 | function g etJobDomai nId(req) { | |
| 192 | var jo bDomainId = {}; | |
| 193 | var do mainPrefix = 'jobDom ainId-'; | |
| 194 | _.each ([req.para ms, req.bo dy, req.qu ery], func tion(reqPa ram){ | |
| 195 | _. each(reqPa ram, funct ion(val, k ey){ | |
| 196 | if (key. substring( 0, domainP refix.leng th) === do mainPrefix ) { | |
| 197 | var domainName = key.sub string(dom ainPrefix. length); | |
| 198 | jobD omainId[do mainName] = val; | |
| 199 | } | |
| 200 | }) ; | |
| 201 | }); | |
| 202 | return jobDomain Id; | |
| 203 | } | |
| 204 | ||
| 205 | function v erifyResol vedIdentif ier(resolv edIdentifi er) { | |
| 206 | return /^[0-9]+- [0-9]+-USV HA/.test(r esolvedIde ntifier); | |
| 207 | } | |
| 208 | ||
| 209 | function e xtractStat ionNumberF romResolve dIdentifie r(resolved Identifier ) { | |
| 210 | return resolvedI dentifier. split('-') [1]; | |
| 211 | } | |
| 212 | ||
| 213 | function e xtractDfnF romResolve dIdentifie r(resolved Identifier ) { | |
| 214 | return resolvedI dentifier. split('-') [0]; | |
| 215 | } | |
| 216 | ||
| 217 | function e xtractSite HashFromPi d(pid) { | |
| 218 | return pid.split (';')[0]; | |
| 219 | } | |
| 220 | ||
| 221 | function h andleSubsc ribe(req, res) { | |
| 222 | var pa tientId = req.param( 'resolvedI dentifier' ); | |
| 223 | var cl ientName = req.param ('clientNa me'); | |
| 224 | log.de bug('mockH dr: subscr ibe patien t %s, clie nt: %s', p atientId, clientName ); | |
| 225 | ||
| 226 | var st ationNumbe r = extrac tStationNu mberFromRe solvedIden tifier(pat ientId); | |
| 227 | ||
| 228 | var si teHash = s tationNumb ersToSiteH ash[statio nNumber]; | |
| 229 | ||
| 230 | if(!si teHash){ | |
| 231 | re turn res.s tatus(404) .send('Sit e with sta tion numbe r ' + stat ionNumber + ' not fo und. Canno t subscrib e patient ' + patien tId); | |
| 232 | } | |
| 233 | var ro otJobId = req.param( 'rootJobId '); | |
| 234 | var jo bId = req. param('job Id') || ge tJobDomain Id(req); | |
| 235 | var mo ckResponse = {}; | |
| 236 | var si te = sites [siteHash] ; | |
| 237 | if (jo bId) { | |
| 238 | lo g.debug('m ockHdr: su bscribe pa tient %s, rootJobId: %s, jobId : %j', pat ientId, ro otJobId, j obId); | |
| 239 | ||
| 240 | mo ckResponse = { | |
| 241 | sites: [ subscribeP atientToMo ckSite(req , site, pa tientId, r ootJobId, jobId)] | |
| 242 | }; | |
| 243 | } | |
| 244 | res.js on(mockRes ponse); | |
| 245 | } | |
| 246 | ||
| 247 | ||
| 248 | function s ubscribePa tientToMoc kSite(req, site, ide ntifier, r ootJobId, jobId) { | |
| 249 | var si teId = sit e.siteId; | |
| 250 | var lo calId = ex tractDfnFr omResolved Identifier (identifie r); | |
| 251 | var pi d = siteId + ';' + l ocalId; | |
| 252 | ||
| 253 | if ( / *patientIs AtSite(sit eId) && */ !site.pat ientsSubsc ribed[iden tifier]) { | |
| 254 | va r newPatie ntObj = {} ; | |
| 255 | ne wPatientOb j.pid = pi d; | |
| 256 | ne wPatientOb j.identifi er = ident ifier; | |
| 257 | ne wPatientOb j.domainsS ynced = {} ; | |
| 258 | ne wPatientOb j.localId = localId; | |
| 259 | ne wPatientOb j.isSubscr ibed = tru e; | |
| 260 | ne wPatientOb j.rootJobI d = rootJo bId; | |
| 261 | ne wPatientOb j.jobId = jobId; | |
| 262 | si te.patient sSubscribe d[identifi er] = newP atientObj; | |
| 263 | si te.waiting Pids.push( newPatient Obj.pid); | |
| 264 | si te.waiting Icns.push( identifier ); | |
| 265 | ||
| 266 | lo g.debug('m ockHdr.sub scribePati entToMockS ite: gener ated and s ubscribed new patien t identifi er %s for site %s', identifier , siteId); | |
| 267 | re turn const ructMockSu bscribeRes ponse(req, site, pid ); | |
| 268 | } else /*if*/ { | |
| 269 | lo g.debug('m ockHdr: su bscribed p atient ide ntifier %s that exis ts on site %s.', ide ntifier, s iteId); | |
| 270 | if (!_.conta ins(site.w aitingIcns , identifi er)) { | |
| 271 | site.pat ientsSubsc ribed[iden tifier].is Subscribed = true; | |
| 272 | site.pat ientsSubsc ribed[iden tifier].ro otJobId = rootJobId; | |
| 273 | site.pat ientsSubsc ribed[iden tifier].jo bId = jobI d; | |
| 274 | site.wai tingPids.p ush(site.p atientsSub scribed[id entifier]. pid); | |
| 275 | site.wai tingIcns.p ush(site.p atientsSub scribed[id entifier]. identifier ); | |
| 276 | } | |
| 277 | re turn const ructMockSu bscribeRes ponse(req, site, sit e.patients Subscribed [identifie r].pid); | |
| 278 | } | |
| 279 | /*else { | |
| 280 | //Patient is not at this site | |
| 281 | return {a piVersion: '1.0', er ror: { mes sage: 'Pat ient not f ound' }}; | |
| 282 | }*/ | |
| 283 | ||
| 284 | log.de bug('mockH dr.handleS ubscribe: Patients c urrently s ubscribed to site %s : %s', sit e.siteId, _.filter(s ite.patien tsSubscrib ed, functi on(patient ) { | |
| 285 | re turn patie nt.isSubsc ribed; | |
| 286 | }).map (function( patient) { | |
| 287 | re turn patie nt.identif ier; | |
| 288 | })); | |
| 289 | } | |
| 290 | ||
| 291 | function c onstructMo ckSubscrib eResponse( req, site, pid) { | |
| 292 | return { | |
| 293 | ap iVersion: "1.0", | |
| 294 | lo cation: "/ hmp/subscr iption/" + req.param ('server') + '/patie nt/' + pid , | |
| 295 | wa itingPids: site.wait ingPids, | |
| 296 | pr ocessingPi ds: site.p rocessingP ids, | |
| 297 | re mainingObj ects: 0 | |
| 298 | }; | |
| 299 | } | |
| 300 | ||
| 301 | function v alidatePol lParams(re q, res, ne xt) { | |
| 302 | if (!v alidateCom monRequest Params(req , res)) { | |
| 303 | re turn; | |
| 304 | } | |
| 305 | if (!r eq.param(' extractSch ema')) { | |
| 306 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'ext ractSchema \''); | |
| 307 | } | |
| 308 | if (!r eq.param(' last')) { | |
| 309 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'las t\''); | |
| 310 | } | |
| 311 | if (!r eq.param(' max')) { | |
| 312 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'max \''); | |
| 313 | } | |
| 314 | if (!r eq.param(' siteId')) { | |
| 315 | re turn res.s tatus(400) .send('Mis sing requi red parame ter: \'sit eId\''); | |
| 316 | } | |
| 317 | ||
| 318 | next() ; | |
| 319 | } | |
| 320 | ||
| 321 | function h andlePoll( req, res) { | |
| 322 | //log. debug('moc kHdr: poll site with station n umber %s', req.param ('siteId') ); | |
| 323 | ||
| 324 | var si teHash = s tationNumb ersToSiteH ash[req.pa ram('siteI d')]; | |
| 325 | ||
| 326 | if (!s iteHash) { | |
| 327 | re s.status(4 04).send(' Site with station nu mber ' + r eq.param(' siteId') + ' not fou nd.'); | |
| 328 | re turn; | |
| 329 | } | |
| 330 | ||
| 331 | var mo ckResponse = { | |
| 332 | si tes: [getS yncDataFro mMockSite( sites[site Hash])] | |
| 333 | }; | |
| 334 | ||
| 335 | res.js on(mockRes ponse); | |
| 336 | } | |
| 337 | ||
| 338 | function g etSyncData FromMockSi te(site) { | |
| 339 | var da taForAllWa itingPids = []; | |
| 340 | _.each (site.wait ingIcns, f unction(id entifier) { | |
| 341 | da taForAllWa itingPids = dataForA llWaitingP ids.concat (getSyncDa taForPatie nt(site.pa tientsSubs cribed[ide ntifier], site)); | |
| 342 | }); | |
| 343 | ||
| 344 | dataFo rAllWaitin gPids = da taForAllWa itingPids. concat(sit e.waitingP ollData); | |
| 345 | ||
| 346 | site.w aitingIcns = []; | |
| 347 | site.w aitingPids = []; | |
| 348 | site.w aitingPoll Data = []; | |
| 349 | ||
| 350 | return { | |
| 351 | ap iVersion: '1.0', | |
| 352 | pa rams: { | |
| 353 | domain: site.domai n, | |
| 354 | systemId : site.sit eId | |
| 355 | }, | |
| 356 | da ta: { | |
| 357 | updated: site.upda ted, | |
| 358 | totalIte ms: dataFo rAllWaitin gPids.leng th, | |
| 359 | lastUpda te: site.l astUpdate, | |
| 360 | waitingP ids: site. waitingPid s, | |
| 361 | processi ngPids: si te.process ingPids, | |
| 362 | remainin gObjects: 0, | |
| 363 | items: d ataForAllW aitingPids | |
| 364 | } | |
| 365 | }; | |
| 366 | } | |
| 367 | ||
| 368 | function g etSyncData ForPatient (patient, site) { | |
| 369 | var me ssageTriad = []; | |
| 370 | var pa tientData = []; | |
| 371 | var si teId = sit e.siteId; | |
| 372 | ||
| 373 | var st ampTime = moment().f ormat('YYY YMMDDHHmms s'); //FUT URETODO: F igure out whether th is is supp osed to eq ual lastUp dateTime.. . | |
| 374 | var me taStamp = {}; | |
| 375 | ||
| 376 | log.de bug('mockH dr.getSync DataForPat ient: Gene rating syn cStatus ob ject for p atient %s' , patient. pid); | |
| 377 | var sy ncStatusOb ject = gen erateSyncS tatusTempl ate(patien t, siteId) ; | |
| 378 | ||
| 379 | log.de bug('mockH dr.getSync DataForPat ient: Gene rating syn cStart obj ect for pa tient %s', patient.p id); | |
| 380 | var sy ncStartObj ect = {}; | |
| 381 | if (!_ .isObject( patient.jo bId)) { | |
| 382 | me taStamp = generateMe taStamp(st ampTime, p atient, si teId); | |
| 383 | sy ncStartObj ect = gene rateSyncSt artTemplat e(patient, siteId); | |
| 384 | ||
| 385 | if (_.isEmpt y(patient. domainsSyn ced)) { | |
| 386 | log.debu g('mockHdr .getSyncDa taForPatie nt: Includ ing demogr aphics obj ect in syn cStart mes sage for p atient %s' , patient. pid); | |
| 387 | addDemog raphicData ForSyncSta rt(patient , site, sy ncStartObj ect); | |
| 388 | } | |
| 389 | ||
| 390 | _. each(domai ns, functi on(domain) { | |
| 391 | if (!pat ient.domai nsSynced[d omain] || domain === 'patient' ) { | |
| 392 | log. debug('moc kHdr.getSy ncDataForP atient: Ge tting %s d ata for pa tient %s', domain, p atient.pid ); | |
| 393 | addD omainDataA ndMetaStam p(stampTim e, patient , site, do main, meta Stamp, pat ientData, syncStatus Object); | |
| 394 | } | |
| 395 | }) ; | |
| 396 | ||
| 397 | sy ncStartObj ect.metaSt amp = meta Stamp; | |
| 398 | lo g.debug('m ockHdr.get SyncDataFo rPatient: Compiling final poll response for patien t %s', pat ient.pid); | |
| 399 | me ssageTriad .push(sync StartObjec t); | |
| 400 | } | |
| 401 | else { | |
| 402 | _. each(patie nt.jobId, function(j obId, doma in){ | |
| 403 | metaStam p = genera teMetaStam p(stampTim e, patient , siteId); | |
| 404 | syncStar tObject = generateSy ncStartTem plate(pati ent, siteI d, jobId); | |
| 405 | if (_.is Empty(pati ent.domain sSynced)) { | |
| 406 | log. debug('moc kHdr.getSy ncDataForP atient: In cluding de mographics object in syncStart message f or patient %s', pati ent.pid); | |
| 407 | addD emographic DataForSyn cStart(pat ient, site , syncStar tObject); | |
| 408 | } | |
| 409 | if (!pat ient.domai nsSynced[d omain] || domain === 'patient' ) { | |
| 410 | log. debug('moc kHdr.getSy ncDataForP atient: Ge tting %s d ata for pa tient %s', domain, p atient.pid ); | |
| 411 | addD omainDataA ndMetaStam p(stampTim e, patient , site, do main, meta Stamp, pat ientData, syncStatus Object); | |
| 412 | } | |
| 413 | syncStar tObject.me taStamp = metaStamp; | |
| 414 | messageT riad.push( syncStartO bject); | |
| 415 | }) ; | |
| 416 | } | |
| 417 | ||
| 418 | _.each (patientDa ta, functi on(item) { | |
| 419 | me ssageTriad .push(item ); | |
| 420 | }); | |
| 421 | messag eTriad.pus h(syncStat usObject); | |
| 422 | ||
| 423 | return messageTr iad; | |
| 424 | } | |
| 425 | ||
| 426 | function a ddDemograp hicDataFor SyncStart( patient, s ite, syncS tartObject ) { | |
| 427 | var de mographics Template = require(' ./data/tem plates/pat ient'); | |
| 428 | var de mographics Data = JSO N.parse(JS ON.stringi fy(demogra phicsTempl ate)); | |
| 429 | fillIn ObjectData (demograph icsData.ob ject, pati ent, site, 'patient' ); | |
| 430 | syncSt artObject. object = d emographic sData.obje ct; | |
| 431 | } | |
| 432 | ||
| 433 | function a ddDomainDa taAndMetaS tamp(stamp Time, pati ent, site, domain, m etaStamp, patientDat a, syncSta tusObject) { | |
| 434 | var si teId = sit e.siteId; | |
| 435 | var do mainTempla te; | |
| 436 | try { | |
| 437 | do mainTempla te = requi re('./data /templates /' + domai n); | |
| 438 | } catc h (e){ | |
| 439 | // not nee ded, not an error | |
| 440 | // log.info( 'Error get ting data for domain : %s: erro r: %s , Se nding and empty meta Stamp indi cating tha t there is no data f or that do main', dom ain, e); | |
| 441 | // send out empty doma inStamp | |
| 442 | me taStamp.so urceMetaSt amp[siteId ].domainMe taStamp[do main] = ge tDomainMet aStamp(sta mpTime, do main); | |
| 443 | pa tient.doma insSynced[ domain] = stampTime; | |
| 444 | re turn; | |
| 445 | } | |
| 446 | ||
| 447 | var do mainData = JSON.pars e(JSON.str ingify(dom ainTemplat e)); | |
| 448 | fillIn Collection Data(domai nData, pat ient, site Id); | |
| 449 | fillIn ObjectData (domainDat a.object, patient, s ite, domai n); | |
| 450 | domain Data.objec t.stampTim e = domain Data.objec t.lastUpda teTime.toS tring(); | |
| 451 | var do mainMetaSt amp = getD omainMetaS tamp(stamp Time, doma in, domain Data.objec t); | |
| 452 | ||
| 453 | metaSt amp.source MetaStamp[ siteId].do mainMetaSt amp[domain ] = domain MetaStamp; | |
| 454 | patien tData.push (domainDat a); | |
| 455 | patien t.domainsS ynced[doma in] = stam pTime; | |
| 456 | syncSt atusObject .object.do mainTotals [domain] = 1; | |
| 457 | } | |
| 458 | ||
| 459 | function f illInColle ctionData( data, pati ent, siteI d) { | |
| 460 | if (da ta.pid) { | |
| 461 | da ta.pid = p atient.pid ; | |
| 462 | } | |
| 463 | if (da ta.systemI d) { | |
| 464 | da ta.systemI d = siteId ; | |
| 465 | } | |
| 466 | if (da ta.localId ) { | |
| 467 | da ta.localId = patient .localId; | |
| 468 | } | |
| 469 | } | |
| 470 | ||
| 471 | function f illInObjec tData(data , patient, site, dom ain) { | |
| 472 | var pa tientLocal Id = patie nt.localId ; | |
| 473 | var si teId = sit e.siteId; | |
| 474 | ||
| 475 | if (da ta.pid) { | |
| 476 | da ta.pid = p atient.pid ; | |
| 477 | } | |
| 478 | if (da ta.systemI d) { | |
| 479 | da ta.systemI d = siteId ; | |
| 480 | } | |
| 481 | ||
| 482 | if (da ta.comment s) { | |
| 483 | _. each(data. comments, function(c omment) { | |
| 484 | if (comm ent.entere dByUid) { | |
| 485 | comm ent.entere dByUid = f ixSiteInUi d(comment. enteredByU id, siteId ); | |
| 486 | } | |
| 487 | ||
| 488 | if (comm ent.entere dByCode) { | |
| 489 | comm ent.entere dByCode = fixSiteInU id(comment .enteredBy Code, site Id); | |
| 490 | } | |
| 491 | }) ; | |
| 492 | } | |
| 493 | ||
| 494 | if (da ta.locatio nUid) { | |
| 495 | da ta.locatio nUid = fix SiteInUid( data.locat ionUid, si teId); | |
| 496 | } | |
| 497 | ||
| 498 | if (da ta.facilit yCode) { | |
| 499 | da ta.facilit yCode = si te.station Number; | |
| 500 | } | |
| 501 | ||
| 502 | if (da ta.provide rs) { | |
| 503 | _. each(data. providers, function( provider) { | |
| 504 | provider .providerU id = fixSi teInUid(pr ovider.pro viderUid, siteId); | |
| 505 | }) ; | |
| 506 | } | |
| 507 | ||
| 508 | if (da ta.orderUi d) { | |
| 509 | da ta.orderUi d = fixSit eAndDfnInU id(data.or derUid, pa tientLocal Id, siteId ); | |
| 510 | } | |
| 511 | ||
| 512 | if (da ta.encount erUid) { | |
| 513 | da ta.encount erUid = fi xSiteAndDf nInUid(dat a.encounte rUid, pati entLocalId , siteId); | |
| 514 | } | |
| 515 | ||
| 516 | if (da ta.text) { | |
| 517 | _. each(data. text, func tion(text) { | |
| 518 | if (text .clinician s) { | |
| 519 | _.ea ch(text.cl inicians, function(c linician) { | |
| 520 | clinician. uid = fixS iteInUid(c linician.u id, siteId ); | |
| 521 | clinician. summary = fixSiteInU id(clinici an.summary , siteId); | |
| 522 | }); | |
| 523 | } | |
| 524 | text.sum mary = fix SiteAndDfn InUid(text .summary, patientLoc alId, site Id); | |
| 525 | text.uid = fixSite AndDfnInUi d(text.uid , patientL ocalId, si teId); | |
| 526 | }) ; | |
| 527 | } | |
| 528 | ||
| 529 | if (da ta.clinici ans) { | |
| 530 | _. each(data. clinicians , function (clinician ) { | |
| 531 | clinicia n.uid = fi xSiteInUid (clinician .uid, site Id); | |
| 532 | clinicia n.summary = fixSiteI nUid(clini cian.summa ry, siteId ); | |
| 533 | }) ; | |
| 534 | } | |
| 535 | ||
| 536 | if (da ta.documen tDefUid) { | |
| 537 | da ta.documen tDefUid = fixSiteInU id(data.do cumentDefU id, siteId ); | |
| 538 | } | |
| 539 | ||
| 540 | if (da ta.locatio nUid) { | |
| 541 | da ta.locatio nUid = fix SiteInUid( data.locat ionUid, si teId); | |
| 542 | } | |
| 543 | ||
| 544 | if (da ta.perform erUid) { | |
| 545 | da ta.perform erUid = fi xSiteInUid (data.perf ormerUid, siteId); | |
| 546 | } | |
| 547 | ||
| 548 | if (da ta.provide rUid) { | |
| 549 | da ta.provide rUid = fix SiteInUid( data.provi derUid, si teId); | |
| 550 | } | |
| 551 | ||
| 552 | if (da ta.results ) { | |
| 553 | _. each(data. results, f unction(re sult) { | |
| 554 | result.u id = fixSi teAndDfnIn Uid(result .uid, pati entLocalId , siteId); | |
| 555 | }) ; | |
| 556 | } | |
| 557 | ||
| 558 | if (da ta.groupUi d) { | |
| 559 | da ta.groupUi d = fixSit eInUid(dat a.groupUid , siteId); | |
| 560 | } | |
| 561 | ||
| 562 | if (da ta.orders) { | |
| 563 | _. each(data. orders, fu nction(ord er) { | |
| 564 | order.lo cationUid = fixSiteI nUid(order .locationU id, siteId ); | |
| 565 | order.or derUid = f ixSiteAndD fnInUid(or der.orderU id, patien tLocalId, siteId); | |
| 566 | order.ph armacistUi d = fixSit eInUid(ord er.pharmac istUid, si teId); | |
| 567 | order.pr oviderUid = fixSiteI nUid(order .providerU id, siteId ); | |
| 568 | }) ; | |
| 569 | } | |
| 570 | ||
| 571 | if (da ta.facilit y && domai n === 'pat ient') { | |
| 572 | va r facility = _.find( data.facil ity, funct ion(facili ty) { | |
| 573 | return f acility.co de === 451 ; | |
| 574 | }) ; | |
| 575 | ||
| 576 | if (facility ) { | |
| 577 | facility .code = si te.station Number; | |
| 578 | facility .localPati entId = pa tientLocal Id; | |
| 579 | facility .systemId = siteId; | |
| 580 | } | |
| 581 | } | |
| 582 | ||
| 583 | if (da ta.teamInf o && data. teamInfo.t eam) { | |
| 584 | da ta.teamInf o.team.uid = fixSite InUid(data .teamInfo. team.uid, siteId); | |
| 585 | } | |
| 586 | ||
| 587 | var lo calId; | |
| 588 | if (do main === ' patient') { | |
| 589 | lo calId = pa tientLocal Id; | |
| 590 | da ta.localId = localId ; | |
| 591 | } else { | |
| 592 | lo calId = _. last(data. uid.split( ':')); | |
| 593 | } | |
| 594 | ||
| 595 | var ui d = getUid ForPidAndD omain(pati ent.pid, d omain, loc alId); | |
| 596 | data.u id = uid; | |
| 597 | } | |
| 598 | ||
| 599 | function f ixSiteInUi d(uid, sit eId) { | |
| 600 | return uid.repla ce(/ABCD/, siteId); | |
| 601 | } | |
| 602 | ||
| 603 | function f ixSiteAndD fnInUid(ui d, patient LocalId, s iteId) { | |
| 604 | return uid.repla ce(/ABCD:[ 0-9]+/, si teId + ':' + patient LocalId); | |
| 605 | } | |
| 606 | ||
| 607 | function g etUidForPi dAndDomain (pid, doma in, localI d) { | |
| 608 | return 'urn:va:' + domain + ':' + pi d.replace( /;/, ':') + ':' + lo calId; | |
| 609 | } | |
| 610 | ||
| 611 | function v alidateUns ubscribePa rams(req, res, next) { | |
| 612 | if (!v alidateCom monRequest Params(req , res)) { | |
| 613 | re turn; | |
| 614 | } | |
| 615 | if (!r eq.param(' resolvedId entifier') || !verif yResolvedI dentifier( req.param( 'resolvedI dentifier' ))) { | |
| 616 | re turn res.s tatus(400) .send('Mis sing patie nt identif ier in for mat DFN-St ationNumbe r-USVHA'); | |
| 617 | } | |
| 618 | next() ; | |
| 619 | } | |
| 620 | ||
| 621 | function h andleUnsub scribe(req , res) { | |
| 622 | var pa tientId = req.param( 'resolvedI dentifier' ); | |
| 623 | log.de bug('mockH dr: unsubs cribe pati ent %s', p atientId); | |
| 624 | var si te = sites [stationNu mbersToSit eHash[extr actStation NumberFrom ResolvedId entifier(p atientId)] ]; | |
| 625 | var mo ckResponse = { | |
| 626 | si tes: [unsu bscribePat ient(site, patientId )] | |
| 627 | }; | |
| 628 | ||
| 629 | res.js on(mockRes ponse); | |
| 630 | } | |
| 631 | ||
| 632 | function u nsubscribe Patient(si te, identi fier) { | |
| 633 | log.de bug('mockH dr.unsubsc ribePatien t: unsubsc ribing pat ient with identifier %s from s ite %s', i dentifier, site.site Id); | |
| 634 | var pa tient = si te.patient sSubscribe d[identifi er]; | |
| 635 | if (pa tient) { | |
| 636 | pa tient.doma insSynced = {}; | |
| 637 | pa tient.isSu bscribed = false; | |
| 638 | si te.waiting Pids = _.w ithout(sit e.waitingP ids, patie nt.pid); | |
| 639 | si te.waiting Icns = _.w ithout(sit e.waitingI cns, patie nt.identif ier); | |
| 640 | si te.waiting PollData = _.filter( site.waiti ngPollData , function (item){ret urn item.p id !== pat ient.pid;} ); | |
| 641 | lo g.debug('m ockHdr.uns ubscribePa tient: Rem aining pat ients at s ite %s: %s ', site.si teId, _.fi lter(site. patientsSu bscribed, function(p atient) { | |
| 642 | return p atient.isS ubscribed; | |
| 643 | }) .map(funct ion(patien t) { | |
| 644 | return p atient.ide ntifier; | |
| 645 | }) ); | |
| 646 | } else { | |
| 647 | lo g.debug('m ockHdr.uns ubscribePa tient: pat ient with identifier %s doesn\ 't exist a t site %s' , identifi er, site); | |
| 648 | } | |
| 649 | return { | |
| 650 | 'a piVersion' : '1.0', | |
| 651 | 's ucess': tr ue | |
| 652 | }; | |
| 653 | } | |
| 654 | ||
| 655 | function h andleUnsub scribeAll( req, res) { | |
| 656 | log.de bug('mockH dr: unsubs cribe all patients f rom all si tes'); | |
| 657 | _.each (sites, fu nction(sit e) { | |
| 658 | _. each(site. patientsSu bscribed, function(p atient) { | |
| 659 | unsubscr ibePatient (site, pat ient.ident ifier); | |
| 660 | }) ; | |
| 661 | }); | |
| 662 | ||
| 663 | res.se nd('All pa tients uns ubscribed. '); | |
| 664 | } | |
| 665 | ||
| 666 | function v alidateUns olicitedUp date(req, res, next) { | |
| 667 | var da ta = req.b ody; | |
| 668 | if (!d ata) { | |
| 669 | re turn res.s tatus(400) .send('Inv alid or em pty JSON d ata reciev ed in POST message b ody'); | |
| 670 | } else if (!data .uid) { | |
| 671 | re turn res.s tatus(400) .send('Mis sing uid i n POST mes sage body' ); | |
| 672 | } else if(!isVal idUid(data .uid)){ | |
| 673 | re turn res.s tatus(400) .send('inv alid uid i n POST mes sage body: ' + data. uid); | |
| 674 | } | |
| 675 | ||
| 676 | var pi d = extrac tPidFromUi d(data.uid ); | |
| 677 | var si teHash = e xtractSite HashFromPi d(pid); | |
| 678 | var si te = sites [siteHash] ; | |
| 679 | if (!s ite) { | |
| 680 | re turn res.s tatus(400) .send('pid does not correspond to any co nfigured m ock HDR si te'); | |
| 681 | } | |
| 682 | ||
| 683 | var pa tientsSubs cribed = s ite.patien tsSubscrib ed; | |
| 684 | var re solvedIden tifier = _ .findKey(p atientsSub scribed, f unction(pa tient) { | |
| 685 | re turn patie nt.pid === pid; | |
| 686 | }); | |
| 687 | ||
| 688 | var pa tient = pa tientsSubs cribed[res olvedIdent ifier]; | |
| 689 | ||
| 690 | if (!r esolvedIde ntifier || !patient. isSubscrib ed) { | |
| 691 | re turn res.s tatus(400) .send('pat ient with pid ' + pi d + ' has not been s ubscribed' ); | |
| 692 | } | |
| 693 | ||
| 694 | var do main = ext ractDomain FromUid(da ta.uid); | |
| 695 | if (!_ .contains( domains, d omain)) { | |
| 696 | re turn res.s tatus(400) .send('dom ain ' + do main + ' i s not pres ent in the list of c onfigured HDR domain s'); | |
| 697 | } | |
| 698 | ||
| 699 | req.si te = site; | |
| 700 | req.pa tient = pa tient; | |
| 701 | req.da taDomain = domain; | |
| 702 | ||
| 703 | next() ; | |
| 704 | } | |
| 705 | ||
| 706 | function e xtractDoma inFromUid( uid) { | |
| 707 | var do main = uid .split(':' )[2]; | |
| 708 | return domain; | |
| 709 | } | |
| 710 | ||
| 711 | function e xtractPidF romUid(uid ){ | |
| 712 | var ui dParts = u id.split(' :'); | |
| 713 | return uidParts[ 3] + ';' + uidParts[ 4]; | |
| 714 | } | |
| 715 | ||
| 716 | function i sValidUid( uid){ | |
| 717 | return /^urn:va: \w*:([0-9] |[A-F]){4} :[0-9]*:[\ s\S]+/.tes t(uid); | |
| 718 | } | |
| 719 | ||
| 720 | function h andleUnsol icitedUpda te(req, re s) { | |
| 721 | var da ta = req.b ody; | |
| 722 | var ne wLastUpdat eTime = mo ment().for mat('YYYYM MDDHHmmss' ); | |
| 723 | data.l astUpdateT ime = newL astUpdateT ime; | |
| 724 | ||
| 725 | var pa tient = re q.patient; | |
| 726 | var si teId = req .site.site Id; | |
| 727 | var do main = req .dataDomai n; | |
| 728 | ||
| 729 | var me taStamp = generateMe taStamp(ne wLastUpdat eTime, pat ient, site Id, domain , data); | |
| 730 | var co llectionWr apper = ge tCollectio nWrapper(d omain, pat ient, site Id, 1, 1); | |
| 731 | collec tionWrappe r.object = data; | |
| 732 | var sy ncStart = generateSy ncStartTem plate(pati ent, siteI d); | |
| 733 | syncSt art.metaSt amp = meta Stamp; | |
| 734 | var sy ncStatus = generateS yncStatusT emplate(pa tient, sit eId, domai n); | |
| 735 | ||
| 736 | req.si te.waiting PollData.p ush(syncSt art); | |
| 737 | req.si te.waiting PollData.p ush(collec tionWrappe r); | |
| 738 | req.si te.waiting PollData.p ush(syncSt atus); | |
| 739 | ||
| 740 | res.st atus(201). send(); | |
| 741 | } | |
| 742 | ||
| 743 | function g etCollecti onWrapper( domain, pa tient, sit eId, seq, total) { | |
| 744 | return { | |
| 745 | co llection: domain, | |
| 746 | pi d: patient .pid, | |
| 747 | sy stemId: si teId, | |
| 748 | lo calId: pat ient.local Id, | |
| 749 | se q: seq, | |
| 750 | to tal: total , | |
| 751 | ob ject: {} | |
| 752 | }; | |
| 753 | } | |
| 754 | ||
| 755 | function g enerateMet aStamp(sta mpTime, pa tient, sit eId, domai n, data) { | |
| 756 | var me taStamp = { | |
| 757 | ic n: null, | |
| 758 | st ampTime: s tampTime, | |
| 759 | so urceMetaSt amp: {} | |
| 760 | }; | |
| 761 | ||
| 762 | metaSt amp.source MetaStamp[ siteId] = getSourceM etaStamp(s tampTime, patient, d omain, dat a); | |
| 763 | return metaStamp ; | |
| 764 | } | |
| 765 | ||
| 766 | //Variadic function: domain an d data are optional parameters . | |
| 767 | // Include t hem when t he sourceM etaStamp i s only for 1 patient data obje ct, as in an unsolic ited updat e. | |
| 768 | // otherwise , domainMe taStamp ne eds to be filled in seperately for each domain | |
| 769 | function g etSourceMe taStamp(st ampTime, p atient, do main, data ) { | |
| 770 | var so urceMetaSt amp = { | |
| 771 | pi d: patient .pid, | |
| 772 | lo calId: pat ient.local Id, | |
| 773 | st ampTime: s tampTime, | |
| 774 | do mainMetaSt amp: {} | |
| 775 | }; | |
| 776 | ||
| 777 | if(dom ain && dat a){ | |
| 778 | so urceMetaSt amp.domain MetaStamp[ domain] = getDomainM etaStamp(s tampTime, domain, da ta); | |
| 779 | } | |
| 780 | ||
| 781 | return sourceMet aStamp; | |
| 782 | } | |
| 783 | ||
| 784 | function g etDomainMe taStamp(st ampTime, d omain, dat a) { | |
| 785 | return { | |
| 786 | do main: doma in, | |
| 787 | st ampTime: s tampTime, | |
| 788 | ev entMetaSta mp: data ? getEventM etaStamp(d ata) : {} | |
| 789 | }; | |
| 790 | } | |
| 791 | ||
| 792 | function g etEventMet aStamp(dat aObject) { | |
| 793 | var ev entMetaSta mp = {}; | |
| 794 | eventM etaStamp[d ataObject. uid] = { | |
| 795 | st ampTime: d ataObject. lastUpdate Time.toStr ing() | |
| 796 | }; | |
| 797 | return eventMeta Stamp; | |
| 798 | } | |
| 799 | ||
| 800 | //Note: th is returns an incomp lete sync start obje ct; The 'm etaStamp' and 'objec t' attribu tes need t o be set s eperately. | |
| 801 | function g enerateSyn cStartTemp late(patie nt, siteId , jobId) { | |
| 802 | return { | |
| 803 | co llection: 'syncStart ', | |
| 804 | pi d: patient .pid, | |
| 805 | sy stemId: si teId, | |
| 806 | lo calId: pat ient.local Id, | |
| 807 | ic n: null, | |
| 808 | ro otJobId: p atient.roo tJobId, | |
| 809 | jo bId: jobId || patien t.jobId, | |
| 810 | se q: 1, | |
| 811 | to tal: 1 | |
| 812 | }; | |
| 813 | } | |
| 814 | ||
| 815 | //Variadic function: domain is an option al paramet er; | |
| 816 | // include w hen the sy ncStatus i s only int ended for 1 patient data objec t, as in a n unsolici ted update | |
| 817 | // otherwise domainTot als will n eed to be seperately filled in for each domain | |
| 818 | function g enerateSyn cStatusTem plate(pati ent, siteI d, domain) { | |
| 819 | var ob ject = { | |
| 820 | do mainTotals : {}, | |
| 821 | in itialized: true, | |
| 822 | ui d: 'urn:va :syncStatu s:' + pati ent.pid.re place(/;/, ':') + ': H4680' | |
| 823 | }; | |
| 824 | ||
| 825 | if(dom ain){ | |
| 826 | ob ject.domai nTotals[do main] = 1; | |
| 827 | } | |
| 828 | ||
| 829 | return { | |
| 830 | co llection: 'syncStatu s', | |
| 831 | pi d: patient .pid, | |
| 832 | sy stemId: si teId, | |
| 833 | lo calId: pat ient.local Id, | |
| 834 | // icn: patie nt.icn, | |
| 835 | se q: 1, | |
| 836 | to tal: 1, | |
| 837 | ob ject: obje ct | |
| 838 | }; | |
| 839 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.