Produced by Araxis Merge on 10/4/2017 8:04:35 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 | rdk.zip\rdk\product\production\rdk\src\resources\patient-search | patient-search-util.js | Mon Aug 28 19:41:48 2017 UTC |
| 2 | rdk.zip\rdk\product\production\rdk\src\resources\patient-search | patient-search-util.js | Tue Oct 3 18:20:44 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 2 | 1278 |
| Changed | 1 | 2 |
| 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 rdk = require('. ./../core/ rdk'); | |
| 4 | var httpUt il = rdk.u tils.http; | |
| 5 | var _ = re quire('lod ash'); | |
| 6 | var nullCh ecker = rd k.utils.nu llchecker; | |
| 7 | var async = require( 'async'); | |
| 8 | var search Jds = requ ire('./sea rch-jds'); | |
| 9 | var S = re quire('str ing'); | |
| 10 | var sensit ivityUtils = rdk.uti ls.sensiti vity; | |
| 11 | var search Util = req uire('./re sults-pars er'); | |
| 12 | var hmpPat ientSelect = require ('./hmp-pa tient-sele ct'); | |
| 13 | var NO_HMP _SELECT_RP C_ERR_REGE X = /^Vist A SECURITY error(.*) $/i; | |
| 14 | var COMMA_ REGEX = /, +/gi; | |
| 15 | var NAME_S EARCH_TYPE = 'NAME'; | |
| 16 | var LAST5_ SEARCH_TYP E = 'LAST5 '; | |
| 17 | var PID_SE ARCH_TYPE = 'PID'; | |
| 18 | var JDSPat ientAttrib uteWhiteli st = ['bir thDate', ' displayNam e', 'famil yName', 'f ullName', 'genderCod e', 'gende rName', 'g ivenNames' , 'icn', ' last5', 'l ocalId', ' pid', 'roo mBed', 'se nsitive', 'ssn', 'su mmary']; | |
| 19 | ||
| 20 | /** | |
| 21 | * | |
| 22 | * Retriev es patient informati on from Vi stA and/or JDS. | |
| 23 | * | |
| 24 | * @param {Object} r eq - The r equest obj ect. | |
| 25 | * @param {string} l ogMessageP refix - Us ed when lo gging mess ages to sh ow who is calling th is - usefu l for debu gging. | |
| 26 | * @param {Object} j dsServer - Connectiv ity inform ation for JDS. Pulle d from req .app.confi g.jdsServe r | |
| 27 | * @param {Object} s earchOptio ns - The s earch opti ons for th e patient search que ry. | |
| 28 | * @param {string} s earchOptio ns.site - The site t o search f or patient s on. | |
| 29 | * @param {string} s earchOptio ns.searchT ype - The type of se arch to pe rform. Can be ICN, P ID, LAST5, or NAME. | |
| 30 | * @param {string} s earchOptio ns.searchS tring - Th e string t o search o n. ICN for ICN searc h, PID for PID searc h, | |
| 31 | * f irst lette r of last name + las t 4 of SSN for last5 search, f ull or par tial name for name s earch. | |
| 32 | * @param {function} callback - The func tion to ca ll when al l of the p atient dat a has been retrieved . | |
| 33 | */ | |
| 34 | module.exp orts.callP atientSear ch = funct ion(req, l ogMessageP refix, jds Server, se archOption s, callbac k) { | |
| 35 | var lo gger = req .logger; | |
| 36 | var si te = searc hOptions.s ite; | |
| 37 | var se archType = searchOpt ions.searc hType; | |
| 38 | var se archString = searchO ptions.sea rchString; | |
| 39 | if (se archType = == 'PID' & & !_.start sWith(sear chString, site + ';' )) { | |
| 40 | re turn callb ack(logMes sagePrefix + ' site "' + site + '" doesn \'t match site in pi d "' + sea rchString + '"'); | |
| 41 | } | |
| 42 | var se nsitivePat ientAcknow leged = _. result(req , 'query._ ack') || _ .result(re q, 'params ._ack') || _.result( req, 'body ._ack') || false; | |
| 43 | var ha sDGAccess = _.result (req, 'ses sion.user. dgSensitiv eAccess', 'false') = == 'true'; | |
| 44 | var LO G_MESSAGE_ PREFIX = ' patient-se arch-util. callPatien tSearch'; | |
| 45 | if (!l ogMessageP refix) { | |
| 46 | lo gMessagePr efix = LOG _MESSAGE_P REFIX; | |
| 47 | } else { | |
| 48 | lo gMessagePr efix += '. ' + LOG_ME SSAGE_PREF IX; | |
| 49 | } | |
| 50 | var ha sHmpPatien tSelectRpc = _.resul t(req, 'ap p.config.v istaSites[ ' + site + '].hasHmp PatientSel ectRpc', n ull); | |
| 51 | logger .debug('%s beginning with hasH mpPatientS electRpc s et to %s', logMessag ePrefix, h asHmpPatie ntSelectRp c); | |
| 52 | ||
| 53 | // If the site i s configur ed to have the HMP P ATIENT SEL ECT RPC, c all it to retrieve t he patient search re sults. | |
| 54 | // Oth erwise, ge t the pati ent search results f rom JDS. | |
| 55 | if (ha sHmpPatien tSelectRpc !== false ) { | |
| 56 | lo gger.debug ('%s perfo rming hmpP atientSele ct.fetch u sing site= %s &search Type=%s &s earchStrin g=%s', log MessagePre fix, site, searchTyp e, searchS tring); | |
| 57 | hm pPatientSe lect.fetch (req, sear chOptions, site, fun ction(erro r, respons e) { | |
| 58 | if (erro r) { | |
| 59 | /** | |
| 60 | * I f we get t he securit y error fr om the HMP PATIENT S ELECT call we assume that the | |
| 61 | * R PC is not installed at the sit e and need to call p t-select f rom RC23 f orward | |
| 62 | */ | |
| 63 | if ( error.matc h(NO_HMP_S ELECT_RPC_ ERR_REGEX) ) { | |
| 64 | if (!_.isE mpty(_.res ult(req, ' app.config .vistaSite s[' + site + ']', {} ))) { | |
| 65 | //set the config to not ha ve hasHmpP atientSele ctRpc | |
| 66 | req.ap p.config.v istaSites[ site].hasH mpPatientS electRpc = false; | |
| 67 | logger .trace(req .app.confi g.vistaSit es[site]); | |
| 68 | } | |
| 69 | logger.deb ug('%s per forming pt -select se arch after failed hm pPatientSe lect attem pt using s ite=%s &se archType=% s &searchS tring=%s', logMessag ePrefix, s ite, searc hType, sea rchString) ; | |
| 70 | return sea rchJds.get Patients(r eq, search Options, j dsServer, function(e rr, respon se) { | |
| 71 | var op tions = { | |
| 72 | fi nalCB: cal lback, | |
| 73 | ha sDGAccess: hasDGAcce ss, | |
| 74 | se nsitivePat ientAcknow leged: sen sitivePati entAcknowl eged, | |
| 75 | lo gMessagePr efix: logM essagePref ix | |
| 76 | }; | |
| 77 | ptSele ctCB(err, response, logger, op tions); | |
| 78 | }); | |
| 79 | } | |
| 80 | logg er.error(l ogMessageP refix + 'E rror perfo rming sear ch [%s]', (error.mes sage || er ror)); | |
| 81 | erro r.message = 'There w as an erro r processi ng your re quest. The error has been logg ed: '; | |
| 82 | retu rn callbac k(logMessa gePrefix + ' ' + err or); | |
| 83 | } | |
| 84 | ||
| 85 | if (resp onse.statu sCode >= 3 00) { | |
| 86 | logg er.error(l ogMessageP refix + 'r esponse.st atusCode [ %s]', resp onse.statu sCode); | |
| 87 | retu rn callbac k({ | |
| 88 | status: re sponse.sta tusCode, | |
| 89 | message: r esponse | |
| 90 | }); | |
| 91 | } | |
| 92 | // If we 're doing a patient search (i. e. NAME or LAST5), t here's no need to ca ll JDS. | |
| 93 | // If we 're doing patient se lection, w e do need to call JD S to get t he unmaske d SSN. | |
| 94 | if (sear chType === NAME_SEAR CH_TYPE || searchTyp e === LAST 5_SEARCH_T YPE) { | |
| 95 | hmpP atientSele ctSearchCB (response, { | |
| 96 | req: req, | |
| 97 | hasDGAcces s: hasDGAc cess, | |
| 98 | logMessage Prefix: lo gMessagePr efix, | |
| 99 | finalCB: c allback, | |
| 100 | sensitiveP atientAckn owleged: s ensitivePa tientAckno wleged, | |
| 101 | searchOpti ons: searc hOptions | |
| 102 | }); | |
| 103 | } else { | |
| 104 | hmpP atientSele ctSelectio nCB(respon se, { | |
| 105 | req: req, | |
| 106 | jdsServer: jdsServer , | |
| 107 | hasDGAcces s: hasDGAc cess, | |
| 108 | logMessage Prefix: lo gMessagePr efix, | |
| 109 | finalCB: c allback, | |
| 110 | sensitiveP atientAckn owleged: s ensitivePa tientAckno wleged, | |
| 111 | searchOpti ons: searc hOptions | |
| 112 | }); | |
| 113 | } | |
| 114 | }) ; | |
| 115 | } else { | |
| 116 | lo gger.debug ('%s perfo rming pt-s elect sear ch instead of hmpPat ientSelect using sit e=%s &sear chType=%s &searchStr ing=%s', l ogMessageP refix, sit e, searchT ype, searc hString); | |
| 117 | se archJds.ge tPatients( req, searc hOptions, jdsServer, function( err, respo nse) { | |
| 118 | var opti ons = { | |
| 119 | fina lCB: callb ack, | |
| 120 | hasD GAccess: h asDGAccess , | |
| 121 | sens itivePatie ntAcknowle ged: sensi tivePatien tAcknowleg ed, | |
| 122 | logM essagePref ix: logMes sagePrefix | |
| 123 | }; | |
| 124 | ptSelect CB(err, re sponse, lo gger, opti ons); | |
| 125 | }) ; | |
| 126 | } | |
| 127 | }; | |
| 128 | ||
| 129 | var ptSele ctCB = fun ction(err, response, logger, o ptions) { | |
| 130 | var ha sDGAccess = options. hasDGAcces s; | |
| 131 | var se nsitivePat ientAcknow leged = op tions.sens itivePatie ntAcknowle ged; | |
| 132 | if (er r) { | |
| 133 | re turn final PatientSea rchCallbac k(err, res ponse, log ger, optio ns); | |
| 134 | } | |
| 135 | if (_. result(res ponse, 'da ta.items', []).lengt h > 0) { | |
| 136 | fo r (var i = 0; i < re sponse.dat a.items.le ngth; i += 1) { | |
| 137 | var pati ent = resp onse.data. items[i]; | |
| 138 | if (!pat ient.sensi tive || se nsitivePat ientAcknow leged || h asDGAccess ) { | |
| 139 | pati ent = clea nJDSPatien tAttribute s(sensitiv ityUtils.r emoveSensi tiveFields (patient)) ; | |
| 140 | } else { | |
| 141 | pati ent = sens itivityUti ls.hideSen sitiveFiel ds(patient ); | |
| 142 | } | |
| 143 | patient = searchUt il.transfo rmPatient( patient, t rue); | |
| 144 | response .data.item s[i] = pat ient; | |
| 145 | } | |
| 146 | } | |
| 147 | finalP atientSear chCallback (err, resp onse, logg er, option s); | |
| 148 | }; | |
| 149 | ||
| 150 | var hmpPat ientSelect SelectionC B = functi on(respons e, options ) { | |
| 151 | var re q = option s.req; | |
| 152 | var lo gger = req .logger; | |
| 153 | var jd sServer = options.jd sServer; | |
| 154 | var ha sDGAccess = options. hasDGAcces s; | |
| 155 | var se nsitivePat ientAcknow leged = op tions.sens itivePatie ntAcknowle ged; | |
| 156 | var se archOption s = option s.searchOp tions; | |
| 157 | var si te = searc hOptions.s ite; | |
| 158 | var lo gMessagePr efix = opt ions.logMe ssagePrefi x ? option s.logMessa gePrefix + '.hmpPati entSelectS electionCB ' : 'patie ntSearch.h mpPatientS electSelec tionCB'; | |
| 159 | ||
| 160 | if (!_ .isEmpty(_ .result(re q, 'app.co nfig.vista Sites[' + site + ']' , {}))) { | |
| 161 | // set the co nfig to ha ve hasHmpP atientSele ctRpc | |
| 162 | re q.app.conf ig.vistaSi tes[site]. hasHmpPati entSelectR pc = true; | |
| 163 | lo gger.trace (req.app.c onfig.vist aSites[sit e]); | |
| 164 | } | |
| 165 | ||
| 166 | async. mapSeries( response, function(p atient, cb ) { | |
| 167 | lo gger.debug ('%s sensi tive flag was %s for patient % s;', logMe ssagePrefi x, patient .sensitive , patient. fullName); | |
| 168 | ||
| 169 | // If patien t is sensi tive and t he user do esn't have DG access and they haven't ac knowledged that the patient is sensitive , | |
| 170 | // hide the sensitive fields and return th e patient data. | |
| 171 | if (patient. sensitive && !sensit ivePatient Acknowlege d && !hasD GAccess) { | |
| 172 | logger.t race(patie nt, logMes sagePrefix + ' has a n _ack of ' + sensit ivePatient Acknowlege d); | |
| 173 | patient = sensitiv ityUtils.h ideSensiti veFields(p atient); | |
| 174 | patient = searchUt il.transfo rmPatient( patient, f alse); | |
| 175 | return s etImmediat e(cb, null , patient) ; | |
| 176 | } | |
| 177 | ||
| 178 | lo gger.debug ('%s check ing for pa tient in J DS', logMe ssagePrefi x); | |
| 179 | ||
| 180 | // Set up ca ll to retr ieve full SSN from J DS since t he VistA d ata masks it out | |
| 181 | va r options = _.create (searchOpt ions, { | |
| 182 | searchSt ring: pati ent.pid, | |
| 183 | searchTy pe: PID_SE ARCH_TYPE | |
| 184 | }) ; | |
| 185 | se archJds.ge tPatients( req, optio ns, jdsSer ver, funct ion(err, j dsResult) { | |
| 186 | if (err) { | |
| 187 | retu rn cb(err) ; | |
| 188 | } | |
| 189 | if (!_.i sEmpty(_.r esult(jdsR esult, 'da ta.items', []))) { | |
| 190 | pati ent.ssn = _.result(_ .find(jdsR esult.data .items, fu nction(jds Patient) { | |
| 191 | return !_. isEmpty(_. result(jds Patient, ' ssn', '')) ; | |
| 192 | }), 'ssn', pat ient.ssn); | |
| 193 | pati ent.sensit ive = _.re sult(_.fin d(jdsResul t.data.ite ms, functi on(jdsPati ent) { | |
| 194 | return _.r esult(jdsP atient, 's ensitive', false) == = true; | |
| 195 | }), 'sensitive ', false); | |
| 196 | } else { | |
| 197 | pati ent.sensit ive = fals e; | |
| 198 | } | |
| 199 | ||
| 200 | if (!pat ient.sensi tive || se nsitivePat ientAcknow leged || h asDGAccess ) { | |
| 201 | pati ent = clea nJDSPatien tAttribute s(sensitiv ityUtils.r emoveSensi tiveFields (patient)) ; | |
| 202 | } else { | |
| 203 | pati ent = sens itivityUti ls.hideSen sitiveFiel ds(patient ); | |
| 204 | } | |
| 205 | patient = searchUt il.transfo rmPatient( patient, f alse); | |
| 206 | return c b(null, pa tient); | |
| 207 | }) ; | |
| 208 | }, fun ction(err, patients) { | |
| 209 | va r retvalue = { | |
| 210 | apiVersi on: '1.0', | |
| 211 | data: { | |
| 212 | tota lItems: 0, | |
| 213 | curr entItemCou nt: 0, | |
| 214 | item s: [] | |
| 215 | } | |
| 216 | }; | |
| 217 | // format the RPC data to look li ke the JDS data that we used t o send bac k | |
| 218 | if (!_.isEmp ty(patient s)) { | |
| 219 | retvalue .data.tota lItems = p atients.le ngth; | |
| 220 | retvalue .data.curr entItemCou nt = patie nts.length ; | |
| 221 | retvalue .data.item s = patien ts; | |
| 222 | } | |
| 223 | fi nalPatient SearchCall back(err, retvalue, logger, op tions); | |
| 224 | }); | |
| 225 | }; | |
| 226 | ||
| 227 | /** | |
| 228 | * Process es respons e from RPC search in the conte xt of a fu ll name or last 5 se arch. | |
| 229 | * | |
| 230 | * @param {Object} r esponse - results fr om HMP PAT IENT SELEC T. | |
| 231 | * @param {Object} o ptions - c ontains re levant inf o for proc essing the results. | |
| 232 | */ | |
| 233 | var hmpPat ientSelect SearchCB = function( response, options) { | |
| 234 | var re q = option s.req; | |
| 235 | var lo gger = req .logger; | |
| 236 | var ha sDGAccess = options. hasDGAcces s; | |
| 237 | var se nsitivePat ientAcknow leged = op tions.sens itivePatie ntAcknowle ged; | |
| 238 | var se archOption s = option s.searchOp tions; | |
| 239 | var si te = searc hOptions.s ite; | |
| 240 | var se archType = _.get(sea rchOptions , 'searchT ype'); | |
| 241 | var se archString = _.get(s earchOptio ns, 'searc hString'); | |
| 242 | var lo gMessagePr efix = opt ions.logMe ssagePrefi x ? option s.logMessa gePrefix + '.hmpPati entSelectS electionCB ' : 'patie ntSearch.h mpPatientS electSearc hCB'; | |
| 243 | ||
| 244 | if (!_ .isEmpty(_ .result(re q, 'app.co nfig.vista Sites[' + site + ']' , {}))) { | |
| 245 | // set the co nfig to ha ve hasHmpP atientSele ctRpc | |
| 246 | re q.app.conf ig.vistaSi tes[site]. hasHmpPati entSelectR pc = true; | |
| 247 | lo gger.trace ({ 'config .vistasite s': req.ap p.config.v istaSites[ site] }, ' hmpPatient SelectRpc set to tru e'); | |
| 248 | } | |
| 249 | ||
| 250 | logger .debug('%s given a r esponse va lue', logM essagePref ix); | |
| 251 | logger .trace({ h mpPatientS electRpcRe sponse: re sponse }); | |
| 252 | ||
| 253 | var fi ndComma = new RegExp (COMMA_REG EX).test(s earchStrin g); | |
| 254 | var re moveImprop erlyMatche dPatients = (searchT ype === NA ME_SEARCH_ TYPE && fi ndComma); | |
| 255 | ||
| 256 | // US1 7390 - If there is a comma in our search String red uce the re sults from the HMP P ATIENT SEL ECT RPC so that the last name is an exac t match | |
| 257 | if (re moveImprop erlyMatche dPatients) { | |
| 258 | va r improper lyMatchedP atients = _.remove(r esponse, f unction la stNameExac tMatch(val ue, index, array) { | |
| 259 | var myNa me = _.get (value, 'f ullName'); | |
| 260 | var rege x = new Re gExp('^' + _.escapeR egExp(sear chString), 'gi'); | |
| 261 | var matc hed = rege x.test(myN ame); | |
| 262 | // This is a rever sal of if we find a match. If we find th e match we are keepi ng it and not removi ng | |
| 263 | return ! matched; | |
| 264 | }) ; | |
| 265 | re q.logger.d ebug(impro perlyMatch edPatients , logMessa gePrefix + ' comma s eparated v alue retur ned these' ); | |
| 266 | } | |
| 267 | ||
| 268 | async. mapSeries( response, function(p atient, cb ) { | |
| 269 | ||
| 270 | pa tient = se nsitivityU tils.remov eSensitive Fields(pat ient); | |
| 271 | ||
| 272 | if (patient. sensitive && !sensit ivePatient Acknowlege d && !hasD GAccess) { | |
| 273 | patient = sensitiv ityUtils.h ideSensiti veFields(p atient); | |
| 274 | } | |
| 275 | ||
| 276 | pa tient = se archUtil.t ransformPa tient(pati ent, false ); | |
| 277 | re turn cb(nu ll, patien t); | |
| 278 | ||
| 279 | }, fun ction(err, patients) { | |
| 280 | va r retvalue = { | |
| 281 | data: { | |
| 282 | tota lItems: 0, | |
| 283 | curr entItemCou nt: 0, | |
| 284 | item s: [] | |
| 285 | } | |
| 286 | }; | |
| 287 | // format the RPC data to look li ke the JDS data that we used t o send bac k | |
| 288 | if (!_.isEmp ty(patient s)) { | |
| 289 | retvalue .data.tota lItems = p atients.le ngth; | |
| 290 | retvalue .data.curr entItemCou nt = patie nts.length ; | |
| 291 | retvalue .data.item s = patien ts; | |
| 292 | } | |
| 293 | fi nalPatient SearchCall back(err, retvalue, logger, op tions); | |
| 294 | }); | |
| 295 | }; | |
| 296 | ||
| 297 | function f inalPatien tSearchCal lback(err, data, log ger, optio ns) { | |
| 298 | var lo gMessagePr efix = opt ions.logMe ssagePrefi x ? option s.logMessa gePrefix + '.finalPa tientSearc hCallback' : 'patien tSearch.fi nalPatient SearchCall back'; | |
| 299 | if (er r) { | |
| 300 | re turn optio ns.finalCB (err); | |
| 301 | } | |
| 302 | data.s tatus = 20 0; | |
| 303 | logger .trace(dat a, logMess agePrefix + ' return ing result '); | |
| 304 | option s.finalCB( null, data ); | |
| 305 | } | |
| 306 | ||
| 307 | /** | |
| 308 | * Retriev es patient demograph ic informa tion from JDS based on a given PID. | |
| 309 | * | |
| 310 | * @param {Object} r eq - The r equest obj ect. | |
| 311 | * @param {string} l ogMessageP refix - Us ed when lo gging mess ages to sh ow who is calling th is - usefu l for debu gging. | |
| 312 | * @param {string} s ite - The site to se arch for p atients in . | |
| 313 | * @param {string} s earchType - The type of search to perfor m. Can be ICN, PID, LAST5, or NAME. | |
| 314 | * @param {string} p id - The P ID of the patient to search fo r. | |
| 315 | * @param {function} callback - The func tion to ca ll when al l of the d ata has be en retriev ed. | |
| 316 | */ | |
| 317 | module.exp orts.callJ DSPatientS earch = fu nction(req , logMessa gePrefix, site, sear chType, pi d, callbac k) { | |
| 318 | var LO G_MESSAGE_ PREFIX = ' patient-se arch-util. callJDSPat ientSearch '; | |
| 319 | if (!l ogMessageP refix) { | |
| 320 | lo gMessagePr efix = LOG _MESSAGE_P REFIX; | |
| 321 | } else { | |
| 322 | lo gMessagePr efix += '. ' + LOG_ME SSAGE_PREF IX; | |
| 323 | } | |
| 324 | var lo gger = req .logger; | |
| 325 | var se nsitivePat ientAcknow leged = _. result(req , 'query._ ack') || _ .result(re q, 'params ._ack') || _.result( req, 'body ._ack') || false; | |
| 326 | ||
| 327 | var ha sDGAccess = _.result (req, 'ses sion.user. dgSensitiv eAccess', 'false') = == 'true'; | |
| 328 | ||
| 329 | var op tions = _. extend({}, req.app.c onfig.jdsS erver, { | |
| 330 | ur l: '/vpr/' + pid, | |
| 331 | lo gger: logg er, | |
| 332 | js on: true | |
| 333 | }); | |
| 334 | logger .debug(log MessagePre fix + ' pe rforming s earch usin g pid=' + pid); | |
| 335 | httpUt il.get(opt ions, func tion(error , response , result) { | |
| 336 | if (error) { | |
| 337 | logger.e rror(logMe ssagePrefi x + ' Erro r performi ng search [%s]', (er ror.messag e || error )); | |
| 338 | error.me ssage = 'T here was a n error pr ocessing y our reques t. The err or has bee n logged: '; | |
| 339 | return c allback(lo gMessagePr efix + ' ' + error, null); | |
| 340 | } | |
| 341 | if (response .statusCod e >= 300) { | |
| 342 | logger.e rror(logMe ssagePrefi x + ' resp onse.statu sCode [%s] ', respons e.statusCo de); | |
| 343 | return c allback({ | |
| 344 | stat us: respon se.statusC ode, | |
| 345 | mess age: resul t | |
| 346 | }, null) ; | |
| 347 | } | |
| 348 | if (_.isEmpt y(_.result (result, ' data.items ', {}))) { | |
| 349 | return c allback(nu ll, { | |
| 350 | data : {} | |
| 351 | }); | |
| 352 | } | |
| 353 | _. each(resul t.data.ite ms, functi on(patient ) { | |
| 354 | if (_.is Undefined( patient.se nsitive)) { | |
| 355 | pati ent.sensit ive = fals e; | |
| 356 | } | |
| 357 | if (!pat ient.sensi tive || se nsitivePat ientAcknow leged || h asDGAccess ) { | |
| 358 | pati ent = clea nJDSPatien tAttribute s(sensitiv ityUtils.r emoveSensi tiveFields (patient)) ; | |
| 359 | } else { | |
| 360 | pati ent = sens itivityUti ls.hideSen sitiveFiel ds(patient ); | |
| 361 | } | |
| 362 | patient = searchUt il.transfo rmPatient( patient, t rue); | |
| 363 | }) ; | |
| 364 | ||
| 365 | re turn callb ack(null, result); | |
| 366 | }); | |
| 367 | }; | |
| 368 | ||
| 369 | /** | |
| 370 | * Removes unnecessa ry attribu tes from a patient. | |
| 371 | * | |
| 372 | * @param {object} p atient - T he patient to remove attribute s from. | |
| 373 | * @return {object} cleanedPat ient - The patient, with unnec essary att ributes re moved. | |
| 374 | */ | |
| 375 | function c leanJDSPat ientAttrib utes(patie nt) { | |
| 376 | var cl eanedPatie nt = _.pic k(patient, JDSPatien tAttribute Whitelist) ; | |
| 377 | return cleanedPa tient; | |
| 378 | } | |
| 379 | ||
| 380 | function v alidRespon seDataItem s(logger, logMessage Prefix, re sponse) { | |
| 381 | //Chec k response .data.item s | |
| 382 | if (!r esponse) { | |
| 383 | lo gger.debug (logMessag ePrefix + '_validRes ponseDataI tems got a null resp onse objec t'); | |
| 384 | re turn false ; | |
| 385 | } else if (!resp onse.data) { | |
| 386 | lo gger.debug (logMessag ePrefix + '_validRes ponseDataI tems got a response object wit h no data' ); | |
| 387 | re turn false ; | |
| 388 | } else if (!resp onse.data. items) { | |
| 389 | lo gger.debug (logMessag ePrefix + '_validRes ponseDataI tems got a response object wit h no data. items'); | |
| 390 | re turn false ; | |
| 391 | } | |
| 392 | logger .debug(log MessagePre fix + '_va lidRespons eDataItems got a val id respons e object') ; | |
| 393 | return true; | |
| 394 | } | |
| 395 | ||
| 396 | /** | |
| 397 | * Pass in 'req.quer y.order' a nd the res ponse whic h contains data.item s that nee d to be or dered. | |
| 398 | * Example : https:// ehmp.vista core.us/re source/pat ient-searc h/full-nam e?name.ful l=Seven&or der=givenN ames%20DES C | |
| 399 | * | |
| 400 | * @param logger - r eq.logger - The logg er | |
| 401 | * @param logMessage Prefix - U sed when l ogging mes sages to s how who is calling t his - usef ul for deb ugging. | |
| 402 | * @param order - th e field (i n an insta nce of dat a.items) t hat you wa nt to sear ch on. | |
| 403 | * If this is not pa ssed in, t he data wi ll be retu rned as it is - no s orting wil l take pla ce. | |
| 404 | * After t he field y ou want to search on , you can specify on e of two v alues: | |
| 405 | * 'ASC' f or ascendi ng or 'DES C' for des cending. If fieldNa me is supp lied but ' ASC' or 'D ESC' is no t supplied , 'ASC' wi ll be assu med. | |
| 406 | * @param response T he object containing data.item s that was returned from the c all to cal lPatientSe arch | |
| 407 | */ | |
| 408 | module.exp orts.sort = function (logger, l ogMessageP refix, ord er, respon se) { | |
| 409 | //Chec k order ob ject | |
| 410 | if (!o rder) { | |
| 411 | lo gger.debug (logMessag ePrefix + '_sort no sort speci fied - ret urning dat a as is'); | |
| 412 | re turn; | |
| 413 | } | |
| 414 | if (va lidRespons eDataItems (logger, l ogMessageP refix + '_ sort', res ponse) === false) { | |
| 415 | re turn; | |
| 416 | } | |
| 417 | var fi eldAndOrde r = order. split(' ') ; | |
| 418 | var fi eld = fiel dAndOrder[ 0]; | |
| 419 | var fi eldOrder = (fieldAnd Order.leng th === 2 ? fieldAndO rder[1] : 'ASC'); | |
| 420 | if (fi eldOrder) { | |
| 421 | fi eldOrder = fieldOrde r.toLowerC ase(); | |
| 422 | } | |
| 423 | logger .debug(log MessagePre fix + '_so rt sorting by ' + fi eldOrder); | |
| 424 | if (fi eldOrder = == 'desc') { | |
| 425 | re sponse.dat a.items = _.sortBy(r esponse.da ta.items, field).rev erse(); | |
| 426 | } else { | |
| 427 | re sponse.dat a.items = _.sortBy(r esponse.da ta.items, field); | |
| 428 | } | |
| 429 | }; | |
| 430 | ||
| 431 | /** | |
| 432 | * Because lodash tr eats NaN a s a number , we need a way to e nsure that the value passed in is not on ly a numbe r but | |
| 433 | * that it is not a floating v alue. | |
| 434 | * | |
| 435 | * @param num the va riable to check to s ee if it's a whole n umber | |
| 436 | * @return s {boolean } True if a whole nu mber. | |
| 437 | */ | |
| 438 | function i sWholeNumb er(num) { | |
| 439 | if (nu llChecker. isNullish( num)) { | |
| 440 | re turn false ; | |
| 441 | } | |
| 442 | if (ty peof num = == 'string ' && _.isE mpty(num)) { | |
| 443 | re turn false ; | |
| 444 | } | |
| 445 | return num % 1 = == 0; | |
| 446 | } | |
| 447 | ||
| 448 | /** | |
| 449 | * | |
| 450 | * @param logger - r eq.logger - The logg er | |
| 451 | * @param logMessage Prefix - U sed when l ogging mes sages to s how who is calling t his - usef ul for deb ugging. | |
| 452 | * @param start Wher e do you w ant to sta rt returni ng results . | |
| 453 | * @param limit How many resul ts do you want retur ned for ea ch page. | |
| 454 | * @param response T he object containing data.item s that was returned from the c all to cal lPatientSe arch | |
| 455 | */ | |
| 456 | module.exp orts.limit = functio n(logger, logMessage Prefix, st art, limit , response ) { | |
| 457 | logger .debug(log MessagePre fix + '_li mit start= ' + start + ', limit =' + limit ); | |
| 458 | if (!l imit) { | |
| 459 | lo gger.debug (logMessag ePrefix + '_limit no limit spe cified - r eturning d ata as is' ); | |
| 460 | re turn; | |
| 461 | } | |
| 462 | if (!i sWholeNumb er(limit)) { | |
| 463 | lo gger.debug (logMessag ePrefix + '_limit li mit specif ied was no t a whole number - r eturning d ata as is' ); | |
| 464 | re turn; | |
| 465 | } | |
| 466 | if (!s tart) { | |
| 467 | st art = 0; | |
| 468 | } | |
| 469 | if (!i sWholeNumb er(start)) { | |
| 470 | lo gger.debug (logMessag ePrefix + '_limit st art specif ied was no t a whole number - s etting to zero'); | |
| 471 | st art = 0; | |
| 472 | } | |
| 473 | limit = Number(l imit); | |
| 474 | start = Number(s tart); | |
| 475 | if (va lidRespons eDataItems (logger, l ogMessageP refix + ' limit', re sponse) == = false) { | |
| 476 | lo gger.debug (logMessag ePrefix + '_limit va lidRespons eDataItems returned false - re turning da ta as is') ; | |
| 477 | re turn; | |
| 478 | } | |
| 479 | var to talItems = response. data.items .length; | |
| 480 | limit = limit < totalItems ? limit : totalItem s; //If li mit is big ger than t otalItems, then just use total Items | |
| 481 | ||
| 482 | respon se.data.it emsPerPage = limit; | |
| 483 | respon se.data.st artIndex = start; | |
| 484 | respon se.data.pa geIndex = (start / l imit | 0); // jshint ignore:li ne | |
| 485 | respon se.data.to talPages = (totalIte ms / limit | 0) + (t otalItems % limit > 0 ? 1 : 0) ; // jshin t ignore:l ine | |
| 486 | logger .debug({ | |
| 487 | li mit: limit , | |
| 488 | it emsPerPage : _.result (response, 'data.ite msPerPage' , 'No item s per page found'), | |
| 489 | st art: _.res ult(respon se, 'data. startIndex ', 'No sta rt found') , | |
| 490 | pa geIndex: _ .result(re sponse, 'd ata.pageIn dex', 'No page index found'), | |
| 491 | to talPages: _.result(r esponse, ' data.total Pages', 'N o total pa ges found' ), | |
| 492 | to talItems: _.result(r esponse, ' data.total Items', 'N o total it ems count found') | |
| 493 | }, log MessagePre fix + 'res ponse data '); | |
| 494 | ||
| 495 | if (li mit > 0) { | |
| 496 | lo gger.debug (logMessag ePrefix + '_limit st art(' + ty peof start + ')=' + start + ', limit(' + typeof li mit + ')=' + limit); | |
| 497 | va r end = st art + limi t; | |
| 498 | lo gger.debug ({ | |
| 499 | items: r esponse.da ta.items | |
| 500 | }, logMessag ePrefix + '_limit re sponse.dat a.items - before sli ce(' + sta rt + ', ' + end + ') '); | |
| 501 | re sponse.dat a.items = response.d ata.items. slice(star t, end); | |
| 502 | lo gger.debug ({ | |
| 503 | items: r esponse.da ta.items | |
| 504 | }, logMessag ePrefix + '_limit re sponse.dat a.items - after slic e(' + star t + ', ' + end + ')' ); | |
| 505 | } else { | |
| 506 | lo gger.debug ({ | |
| 507 | items: r esponse.da ta.items | |
| 508 | }, logMessag ePrefix + '_limit re sponse.dat a.items - before sli ce(' + sta rt + ')'); | |
| 509 | re sponse.dat a.items = response.d ata.items. slice(star t); | |
| 510 | lo gger.debug ({ | |
| 511 | items: r esponse.da ta.items | |
| 512 | }, logMessag ePrefix + '_limit re sponse.dat a.items - after slic e(' + star t + ')'); | |
| 513 | } | |
| 514 | logger .debug(log MessagePre fix + '_li mit respon se.data.it ems.length : ' + resp onse.data. items.leng th); | |
| 515 | respon se.data.cu rrentItemC ount = res ponse.data .items.len gth; | |
| 516 | logger .debug(log MessagePre fix + '_li mit respon se.data.cu rrentItemC ount: ' + response.d ata.curren tItemCount ); | |
| 517 | }; | |
| 518 | ||
| 519 | function v alidateFil ter(logger , logMessa gePrefix, filter, re sponse) { | |
| 520 | if (!f ilter) { | |
| 521 | lo gger.debug (logMessag ePrefix + '_validate Filter no filter spe cified - r eturning d ata as is' ); | |
| 522 | re turn false ; | |
| 523 | } | |
| 524 | if (va lidRespons eDataItems (logger, l ogMessageP refix + ' filter', r esponse) = == false) { | |
| 525 | re turn false ; | |
| 526 | } | |
| 527 | if (!_ .startsWit h(filter, 'eq(')) { | |
| 528 | lo gger.warn( logMessage Prefix + ' _validateF ilter filt er was not eq - retu rning data as is'); | |
| 529 | re turn false ; | |
| 530 | } | |
| 531 | if (!_ .endsWith( filter, ') ')) { | |
| 532 | lo gger.warn( logMessage Prefix + ' _validateF ilter filt er was not of the fo rm eq(fiel dName,"fie ldValue") - no closi ng paren - returning data as i s'); | |
| 533 | re turn false ; | |
| 534 | } | |
| 535 | if (_. indexOf(fi lter, ',') === -1) { | |
| 536 | lo gger.warn( logMessage Prefix + ' _validateF ilter filt er was not of the fo rm eq(fiel dName,"fie ldValue") - no comma - returni ng data as is'); | |
| 537 | re turn false ; | |
| 538 | } | |
| 539 | return true; | |
| 540 | } | |
| 541 | ||
| 542 | function p arseFilter (logger, l ogMessageP refix, fil ter) { | |
| 543 | var st r = filter .slice(3, filter.len gth - 1); | |
| 544 | var fi eldName = _.trim(str .slice(0, _.indexOf( str, ',')) , '\'"'); | |
| 545 | var fi eldValue = _.trim(st r.slice(_. indexOf(st r, ',') + 1, str.len gth), '\'" '); | |
| 546 | return { | |
| 547 | fi eldName: f ieldName, | |
| 548 | fi eldValue: fieldValue | |
| 549 | }; | |
| 550 | } | |
| 551 | /** | |
| 552 | * Pass in 'req.quer y.filter' and the re sponse whi ch contain s data.ite ms that ne ed to be o rdered. | |
| 553 | * Example : http:// IP /resource/ locations/ clinics/pa tients?uid =urn:va:lo cation: R E D A CTED :23&filter =eq(family Name,%22EI GHT%22) | |
| 554 | * | |
| 555 | * @param logger - r eq.logger - The logg er | |
| 556 | * @param logMessage Prefix - U sed when l ogging mes sages to s how who is calling t his - usef ul for deb ugging. | |
| 557 | * @param filter - t he filter that follo ws the pat tern " ;eq(fieldN ame,"field Value")&qu ot;. Only eq is sup ported | |
| 558 | * and if this patte rn is not found, we just retur n the data as it is. | |
| 559 | * @param response T he object containing data.item s that was returned from the c all to cal lPatientSe arch | |
| 560 | */ | |
| 561 | module.exp orts.filte r = functi on(logger, logMessag ePrefix, f ilter, res ponse) { | |
| 562 | logger .debug(log MessagePre fix + '_fi lter filte ring by ' + filter); | |
| 563 | if (!v alidateFil ter(logger , logMessa gePrefix + '_filter' , filter, response)) { | |
| 564 | re turn; | |
| 565 | } | |
| 566 | var fi eldNameAnd Value = pa rseFilter( logger, lo gMessagePr efix + '_f ilter', fi lter); | |
| 567 | var fi eldName = fieldNameA ndValue.fi eldName; | |
| 568 | var fi eldValue = fieldName AndValue.f ieldValue; | |
| 569 | logger .debug({ | |
| 570 | fi eldName: f ieldName, | |
| 571 | fi eldValue: fieldValue | |
| 572 | }, log MessagePre fix + '_fi lter field Name and f ieldValue' ); | |
| 573 | ||
| 574 | fieldV alue = fie ldValue.to LowerCase( ); | |
| 575 | var ne wItems = _ .filter(re sponse.dat a.items, f unction(it em) { | |
| 576 | lo gger.trace ({ | |
| 577 | item: it em | |
| 578 | }, logMessag ePrefix + '_filter p erforming filter'); | |
| 579 | ||
| 580 | va r actualVa lue = item [fieldName ]; | |
| 581 | lo gger.debug (logMessag ePrefix + '_filter a ctualValue is ' + ac tualValue) ; | |
| 582 | ||
| 583 | if (nullChec ker.isNotN ullish(act ualValue)) { | |
| 584 | actualVa lue = actu alValue.to LowerCase( ); | |
| 585 | } | |
| 586 | lo gger.debug (logMessag ePrefix + '_filter p erforming actualValu e is now ' + actualV alue); | |
| 587 | ||
| 588 | if (actualVa lue === fi eldValue) { | |
| 589 | logger.d ebug(logMe ssagePrefi x + '_filt er actualV alue (' + actualValu e + ') mat ches field Value (' + fieldValu e + ')'); | |
| 590 | return t rue; | |
| 591 | } else { | |
| 592 | logger.d ebug(logMe ssagePrefi x + '_filt er actualV alue (' + actualValu e + ') doe s NOT matc h fieldVal ue (' + fi eldValue + ')'); | |
| 593 | return f alse; | |
| 594 | } | |
| 595 | }); | |
| 596 | logger .debug(log MessagePre fix + '_fi lter filte ring finis hed'); | |
| 597 | respon se.totalIt ems = newI tems.lengt h; | |
| 598 | respon se.current ItemCount = newItems .length; | |
| 599 | respon se.data.it ems = newI tems; | |
| 600 | }; | |
| 601 | ||
| 602 | function g etSiteFrom Pid(pid) { | |
| 603 | if (nu llChecker. isNotNulli sh(pid) && S(pid).co ntains(';' )) { | |
| 604 | re turn pid.s plit(';')[ 0]; | |
| 605 | } | |
| 606 | return undefined ; | |
| 607 | } | |
| 608 | ||
| 609 | /** | |
| 610 | * Retriev es the sit e from the session, pid, or re quest - if not found , null is returned. | |
| 611 | * | |
| 612 | * @param logger - r eq.logger - The logg er | |
| 613 | * @param logMessage Prefix - U sed when l ogging mes sages to s how who is calling t his - usef ul for deb ugging. | |
| 614 | * @param pid - the pid that c ould conta in the sit e. | |
| 615 | * @param req The re quest that could con tain the s ite | |
| 616 | */ | |
| 617 | module.exp orts.getSi te = funct ion(logger , logMessa gePrefix, pid, req) { | |
| 618 | logger .debug(log MessagePre fix + '_ge tSite retr ieving sit e'); | |
| 619 | var si te; | |
| 620 | req.lo gger.debug (logMessag ePrefix + '_getSite pid=' + pi d); | |
| 621 | site = getSiteFr omPid(pid) ; | |
| 622 | if (nu llChecker. isNotNulli sh(site)) { | |
| 623 | re q.logger.d ebug(logMe ssagePrefi x + '_getS ite obtain ed site (' + site + ') from pi d'); | |
| 624 | re turn site; | |
| 625 | } | |
| 626 | if (nu llChecker. isNotNulli sh(req)) { | |
| 627 | si te = req.p aram('site '); | |
| 628 | if (nullChec ker.isNotN ullish(sit e)) { | |
| 629 | req.logg er.debug(l ogMessageP refix + '_ getSite ob tained sit e (' + sit e + ') fro m request' ); | |
| 630 | return s ite; | |
| 631 | } | |
| 632 | } | |
| 633 | if (_. has(req, ' session.us er.site')) { | |
| 634 | si te = req.s ession.use r.site; | |
| 635 | re q.logger.d ebug(logMe ssagePrefi x + '_getS ite obtain ed site (' + site + ') from re q.session. user.site' ); | |
| 636 | re turn site; | |
| 637 | } | |
| 638 | req.lo gger.error (logMessag ePrefix + '_getSite unable to obtain sit e from req uest'); | |
| 639 | return null; | |
| 640 | }; |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.