5. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 4/18/2019 5:55:12 PM Eastern 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.

5.1 Files compared

# Location File Last Modified
1 MCCF_EDI_TAS_TASCore v2.0_Build_10.zip\MCCF_EDI_TAS_API_Core\src\app\reports\ecme business.js Wed Apr 3 02:27:54 2019 UTC
2 MCCF_EDI_TAS_TASCore v2.0_Build_10.zip\MCCF_EDI_TAS_API_Core\src\app\reports\ecme business.js Tue Apr 16 13:20:39 2019 UTC

5.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 2 1470
Changed 1 2
Inserted 0 0
Removed 0 0

5.3 Comparison options

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

5.4 Active regular expressions

No regular expressions were active.

5.5 Comparison detail

  1   "use stric t"
  2  
  3   const debu g = requir e('debug') ('ecme')
  4   const tran sform = re quire('./t ransform')
  5   const {
  6       perfor mance
  7   } = requir e('perf_ho oks')
  8  
  9   const $tas  = require ('../../.. /tas')()
  10  
  11   const util  = require ('util')
  12  
  13   const data  = $tas.pr oviders.lo ad('report s')
  14  
  15   const logg ing = {
  16       add: a sync (item , secid) = > await $t as.command .run('logg ing', 'dat a', 'save' , item, {
  17           se cid
  18       })
  19   }
  20  
  21   const repo rts = {
  22       update : async (s ecid, id,  item) => d ata.update (secid, id , item),
  23       getOne : async (s ecid, id,  item) => d ata.getOne (secid, id , item),
  24   }
  25  
  26  
  27   const crit eria = [{
  28           pr edicate: ( error, res ponse, bod y) => ((er ror || {}) .message | | '').incl udes('ECON NRESET'),
  29           ac tion: (err or, respon se, body)  => true
  30       },
  31       {
  32           pr edicate: ( error, res ponse, bod y) => ((er ror || {}) .message | | '').incl udes('ENOT FOUND'),
  33           ac tion: (err or, respon se, body)  => false
  34       },
  35       {
  36           pr edicate: ( error, res ponse, bod y) => ((er ror || {}) .message | | '').incl udes('ETIM EDOUT'),
  37           ac tion: () = > true
  38       },
  39       {
  40           pr edicate: ( error, res ponse, bod y) => (res ponse || { }).statusC ode === 50 2,
  41           ac tion: () = > true
  42       },
  43       {
  44           pr edicate: ( error, res ponse, bod y) => ((bo dy || {}). entry || ' ').length  === 0,
  45           ac tion: () = > false
  46       }
  47   ]
  48  
  49  
  50   /**
  51    * 
  52    * see com mon:vista_ instance_m ap
  53    * {
  54        "681" : "eBillin g_dev",
  55        "682" : "eBillin g_cit",
  56        "519" : "ePharma cy_dev"
  57    }
  58    */
  59   const inst anceMap =  {
  60       get: a sync () =>  await $ta s.provider s.load('me tabase').g et('common :vista_ins tance_map' )
  61   }
  62  
  63   /**
  64    * 
  65    * @param  {*} extrac tConfig 
  66    * @param  {*} vistaI
  67    */
  68   let instan ceHelper =  async (ex tractConfi g, vistaId ) => {
  69       let re gex = new  RegExp('(\ \d+).*', ' gm')
  70       let _i nstanceMap  = await i nstanceMap .get()
  71       let ma tchArray =  regex.exe c(vistaId)
  72       if (ma tchArray & & matchArr ay.length)  {
  73           le t _instanc e = matchA rray[1]
  74           re turn _inst anceMap[_i nstance] | | 'bad_map '
  75       } else  {
  76           re turn 'bad_ map'
  77       }
  78   }
  79  
  80  
  81   /**
  82    * 
  83    * @param  {*} extrac tConfig 
  84    * @param  {*} claimR esponseIEN
  85    * @param  {*} vistaI
  86    */
  87   let assemb leClaimURL S = async  (extractCo nfig, clai mResponseI ENs, vista Id) => {
  88       let me ssage = "S uccess"
  89       let st atusCode =  200
  90       let ur ls = []
  91       let qu ery = `ent ry[*].reso urce.id[]`
  92       let ie nsArray =  $tas.helpe rs.jmespat h.search(c laimRespon seIENs, qu ery)
  93       const  USE = "ECM E"
  94       let in stance = a wait insta nceHelper( extractCon fig, vista Id)
  95       extrac tConfig.vi staInstanc e = instan ce
  96       extrac tConfig.vi staId = vi staId
  97       let ie nCount = 0
  98       let ie nLimit = e xtractConf ig.ienLimi t || 0
  99       if (ie nsArray &&  iensArray .length >  0) {
  100           ie nsArray.ma p(identifi er => {
  101                let id =  identifie r
  102                //let re ference =  resource.o rganizatio n.referenc e
  103                //let lo cation = r eference.s ubstr(refe rence.last IndexOf('/ ') + 1)
  104                //JWS 10 /1/18 adde d instance  def, chan ged uri bu ild using  location t o instance
  105                ienCount  = ienCoun t + 1
  106  
  107                //if (er ror !== nu ll || body  === null)
  108  
  109                if ((ien Count <= i enLimit) | | (ienLimi t == 0)) {
  110                    urls .push({
  111                         options: {
  112                             method : 'GET',
  113                             uri: ` ${extractC onfig.tasF HIREndpoin t}` + TEMP LATE_ecme_ bundle_url (extractCo nfig, USE,  id),
  114                             header s: {
  115                                 vi staid: ext ractConfig .vistaId
  116                             },
  117                             retry:  {
  118                                 ma xCount: 40 ,
  119                                 sl eepTime: 9 0,
  120                                 cr iteria
  121                             }
  122                         }
  123                    })
  124                }
  125           })
  126       } else  {
  127           st atusCode =  201
  128           me ssage = "N o iens fou nd " + JSO N.stringif y(claimRes ponseIENs)
  129       }
  130       return  {
  131           st atusCode,
  132           me ssage,
  133           ur ls
  134       }
  135   }
  136  
  137  
  138   let logIte m = functi on (priori ty, messag e) {
  139       return  {
  140           ty pe: "night ly_extract ",
  141           ac tion: prio rity,
  142           da ta: messag e // data  === outcom eDesc
  143       }
  144   }
  145  
  146   /**
  147    *
  148    * @param  user_id
  149    * @param  webClientO ptions
  150    * @return s {Promise <{statusCo de: string , message:  string, u ri: *, bun dle: any}> }
  151    */
  152   let getBun dle = asyn c function  (user_id,  webClient Options) {
  153  
  154       let me ssage = "S uccess"
  155       let st atusCode =  200
  156       let ur i = webCli entOptions .uri
  157       let bu ndle
  158       let {
  159           er ror,
  160           re sponse,
  161           bo dy
  162       } = aw ait $tas.w ebclient({
  163           se curityCont extNotUsed : user_id
  164       }, web ClientOpti ons)
  165  
  166       if (er ror !== nu ll || body  === null)  {
  167           if  (response  != null & & response .request)  {
  168                statusCo de = respo nse.status Code || 50 0
  169                if (resp onse.statu sCode ===  500) {
  170                    mess age = webC lientOptio ns.uri + ' body: ' +  body
  171                } else {
  172                    mess age = 'Err or from FH IR server: ' + util.i nspect(err or) + ' '  + webClien tOptions.u ri + ' ' +  body
  173                }
  174           }  else {
  175                statusCo de = 500
  176                message  = 'Error:  ' + webCli entOptions .uri + ' '  + util.in spect(erro r)
  177           }
  178       } else  if (body  !== null & & response  != null & & response .statusCod e !== 200)  {
  179           st atusCode =  response. statusCode
  180           me ssage = 'F HIR Server  returned  status cod e: ' + res ponse.stat usCode + '  ' + webCl ientOption s.uri + '  ' + body
  181       } else  {
  182           tr y {
  183                bundle =  JSON.pars e(body)
  184           }  catch (ex)  {
  185                statusCo de = 500
  186                message  = 'FHIR Se rver retur ned non js on (html?)  :' + webC lientOptio ns.uri + '  ' + body
  187           }
  188       }
  189  
  190       return  {
  191           st atusCode,
  192           me ssage,
  193           ur i,
  194           bu ndle
  195       }
  196   }
  197  
  198   /**
  199    *
  200    * @param  webClientO ptions
  201    * @return s {Promise <{statusCo de: string , message:  string, u ri: *, bun dle: any}> }
  202    */
  203   let setBun dle = asyn c function  (webClien tOptions)  {
  204       let me ssage = "S uccess"
  205       let st atusCode =  200
  206       let se curityCont ext = null
  207       let {
  208           er ror,
  209           re sponse,
  210           bo dy
  211       } = aw ait $tas.w ebclient(s ecurityCon text, webC lientOptio ns)
  212  
  213       if (er ror !== nu ll || body  === null)  {
  214           if  (response  != null & & response .request)  {
  215                statusCo de = respo nse.status Code || 50 0
  216                if (resp onse.statu sCode ===  500) {
  217                    mess age = webC lientOptio ns.uri + ' body: ' +  body
  218                    // 5 /29/2018 l og warning  and then  go head an d push the  Operation Outcome
  219                    logg ing.add(lo gItem('WAR NING', 'FH IR SERVER  RETURNED 5 00 ' + web ClientOpti ons.uri +  body))
  220                    // f all throug h
  221                } else {
  222                    mess age = 'Err or from FH IR server: ' + util.i nspect(err or) + ' '  + webClien tOptions.u ri
  223                }
  224           }  else {
  225                statusCo de = 500
  226                message  = 'Error:  ' + webCli entOptions .uri + ' '  + util.in spect(erro r)
  227           }
  228       } else  if (body  !== null & & response  != null & & response .statusCod e !== 200)  {
  229           st atusCode =  response. statusCode  || 500
  230           me ssage = 'F HIR Server  returned  status cod e: ' + res ponse.stat usCode + '  ' + webCl ientOption s.uri + '  ' + body
  231       }
  232  
  233       let bu ndle = bod y
  234  
  235       return  {
  236           st atusCode,
  237           me ssage,
  238           ur i: webClie ntOptions. uri,
  239           bu ndle
  240       }
  241   }
  242  
  243   /**
  244    * concat  _old into  new and th en keep (f ilter) onl y new obje cts
  245    *  
  246    * @param  {*} _old 
  247    * @param  {*} _new 
  248    */
  249   const merg eRemoveDup licate = ( _old, _new ) => _new. concat(_ol d).filter(
  250       (obj,  key, array ) => {
  251           co nst _key =  Object.ke ys(obj)[0]
  252           if  (!this[_k ey]) {
  253                this[_ke y] = true
  254                return t rue
  255           }
  256       }
  257   )
  258  
  259  
  260   /**
  261    * add obj ects from  _old only  if they do n't exist  in 
  262    * @param  {*} _old 
  263    * @param  {*} _new 
  264    */
  265   const repo rtMerge =  (_old, _ne w) => {
  266       let re sult = {}
  267  
  268       // get  any objec ts out of  _new not i n _old
  269       Object .keys(_new ).forEach( key => {
  270           if  (!_old[ke y]) {
  271                // copy  object fro m new
  272                result =  Object.as sign(resul t, {
  273                    [key ]: _new[ke y]
  274                })
  275           }
  276       })
  277  
  278       // loo p over top  level eg  ClaimRespo nse, Claim , Explanat ionOfBenef it...
  279       Object .keys(_old ).forEach( key => {
  280           if  (!_new[ke y]) {
  281                // copy  object fro m old
  282                result =  Object.as sign(resul t, {
  283                    [key ]: _old[ke y]
  284                })
  285           }  else {
  286                if (!Arr ay.isArray (_old[key] )) {
  287                    // n ot array
  288                    resu lt = Objec t.assign(r esult, {
  289                         [key]: _ol d[key]
  290                    })
  291                } else {
  292                    let  merged = m ergeRemove Duplicate( _old[key],  _new[key] )
  293                    resu lt = Objec t.assign(r esult, {
  294                         [key]: mer ged
  295                    })
  296                }
  297           }
  298  
  299       })
  300       return  result
  301  
  302   }
  303   /**
  304    * this is  is the da tabase mer ge
  305    * 
  306    * @param  {*} id 
  307    * @param  {*} item 
  308    */
  309   let merge  = async (i d, item) = > {
  310       let re adResults
  311       try {
  312           re adResults  = await re ports.getO ne(null, i d, item)
  313       } catc h (err) {
  314           if  (err && e rr.code ==  404 /* JS ON.stringi fy(err.bod y).code ==  'NotFound ' */ ) {
  315                // expec ted ignore
  316           }
  317       }
  318  
  319       // cop y tableauJ son fields  here
  320       if (re adResults)  {
  321           it em.tableau Json = rep ortMerge(r eadResults , item.tab leauJson)
  322       }
  323  
  324  
  325       return  await rep orts.updat e(null, id , item)
  326   }
  327  
  328   /**
  329    *
  330    * @param  bundleObj
  331    * @param  extractCon fig
  332    * @param  user_id
  333    * @return s {Promise <*>}
  334    */
  335   let writeR esults = a sync funct ion (bundl eObj, extr actConfig,  user_id,  vistaId) {
  336       if (bu ndleObj.st atusCode ! == 200) {
  337           re turn {
  338                statusCo de: 501,
  339                message:  "Skipping , record n ot written  to report ; upstream  500 from  VA_FHIR_Se rver",
  340           }
  341       }
  342  
  343       // JWS  11/5/18 i f FHIR Ser ver return  self for  some reaso n, bundle  msg is not  defined,  entry.leng th is unde fined
  344       if (bu ndleObj.bu ndle && bu ndleObj.bu ndle.entry  && bundle Obj.bundle .entry.len gth === 0)  {
  345           re turn {
  346                statusCo de: 501,
  347                message:  "Skipping , record n ot written  to report ; no bundl eObj.bundl e.entry",
  348           }
  349       }
  350  
  351       let pa yload = bu ndleObj.bu ndle
  352       let ad d_response
  353  
  354       try {
  355           le t response  = transfo rm.fhirToT ableau([pa yload], ex tractConfi g.reportTy pe, user_i d)
  356           //  assemble  the id for  documentd b upsert
  357           //  let _id =  /.*_id=(\ d*.\d*)/gm .exec(bund leObj.uri)
  358           le t _id = /. *_id=(\d*. \d*)/gm.ex ec(bundleO bj.uri)
  359           le t duz = vi staId.subs tring(0, 3 )
  360           le t id = 'cl aim_' + du z + '_' +  _id[1]
  361           Ob ject.assig n(response , {
  362                _id: id
  363           })
  364           de bug(respon se)
  365           ad d_response  = await m erge(id, {
  366                fhir: pa yload,
  367                tableauJ son: respo nse,
  368                reportTy pe: extrac tConfig.re portType
  369           })
  370  
  371       } catc h (ex) {
  372           lo gging.add( logItem('I NFO', ex.m essage + '  ' + ex.st ack, 'djh_ failure'),  user_id)
  373           re turn {
  374                statusCo de: 500,
  375                message:  ex.messag e,
  376                exceptio n: ex
  377           }
  378       }
  379       let st atusCode =  add_respo nse ? 200  : 500 //   || add_res ponse.stat us /* mong odb return s status * /
  380  
  381       return  {
  382           st atusCode,
  383           me ssage: `Su ccess :  r eports.add (): ${add_ response.d ata || add _response}   ${bundle Obj.uri}`
  384       }
  385   }
  386  
  387  
  388   var FHIR_C laim_Ack_R esponse =  {
  389       "resou rceType":  "Claim",
  390       "id":  "11112222" ,
  391       "exten sion": [{
  392           "u rl": "writ eTorReport Successful ",
  393           "v alueString ": 200
  394       }]
  395   }
  396  
  397  
  398   /**
  399    *
  400    * @param  readResult s
  401    * @param  extractCon fig
  402    * @param  user_id
  403    * @return s {Promise <*>}
  404    */
  405   let writeB ack = asyn c function  (bundleOb j, reportO bj, extrac tConfig, v istaId) {
  406       if (bu ndleObj.st atusCode ! == 200) {
  407           re turn {
  408                statusCo de: 501,
  409                message:  "Skipping , no write back; upst ream 500 f rom VA_FHI R_Server",
  410                uri: bun dleObj.uri
  411           }
  412       }
  413  
  414       if (!b undleObj.b undle) {
  415           re turn {
  416                statusCo de: 501,
  417                message:  "Skipping , no claim  bundle",
  418                uri: bun dleObj.uri
  419           }
  420       }
  421  
  422       if (re portObj.st atusCode ! == 200) {
  423           re turn {
  424                statusCo de: 501,
  425                message:  "Skipping , no write back; repo rt failed" ,
  426                uri: bun dleObj.uri
  427           }
  428       }
  429  
  430       const  USE = 'ECM EWB'
  431       let in stance = a wait insta nceHelper( extractCon fig, vista Id)
  432       extrac tConfig.vi staInstanc e = instan ce
  433       extrac tConfig.vi staId = vi staId
  434  
  435       let se tBundleObj
  436       // DJH  - Questio n for JWS  -is this p ulling out  of the bu ndle or fr om the URI ? 12/8/201 8 for some  reason th is was 
  437       // let  id = /.*_ id=(\d*)/g m.exec(bun dleObj.bun dle)
  438       let id  = /.*_id= (\d*.\d*)/ gm.exec(bu ndleObj.ur i)
  439       // TOD O check if  id[1] str ing is num ber
  440       // rep lace claim  ien id in  response  template w ith curren t claim ie n processi ng
  441       let UR L = `${ext ractConfig .tasFHIREn dpoint}` +  TEMPLATE_ ecme_write back_url(e xtractConf ig, USE, i d[1])
  442       let pa yload = JS ON.parse(J SON.string ify(FHIR_C laim_Ack_R esponse))
  443       payloa d.id = id[ 1]
  444       let op tions = {
  445           me thod: 'PUT ',
  446           ur i: URL,
  447           he aders: {
  448                vistaid:  extractCo nfig.vista Id
  449           },
  450           re try: {
  451                maxCount : 40,
  452                sleepTim e: 90,
  453                criteria
  454           },
  455           bo dy: payloa d,
  456           js on: true
  457       }
  458  
  459       setBun dleObj = a wait setBu ndle(optio ns)
  460  
  461       return  setBundle Obj
  462   }
  463  
  464   /***
  465    *
  466    * @param  user_id
  467    * @param  extractCon fig
  468    * @return s {Promise <*>}
  469    *
  470    * extract  is the wo rkhorse
  471    *
  472    * 1) call s VA_FHIR_ Server to  get claim  data
  473    * 2) writ es reports  to docume ntdb for c onsumption  by tablea u
  474    * 3) exec utes an ac knowledgem ent RPC in dicating c laim was p osted to r eport
  475    */
  476   let extrac tClaims =  async func tion (user _id, extra ctConfig,  bundleUrl,  vistaId)  {
  477  
  478       let su mmary = {
  479           bu ndleSucces s: 0,
  480           re portWriteS ucces: 0,
  481           wr iteBackSuc ces: 0,
  482           bu ndleFailur e: 0,
  483           re portWriteF ailure: 0,
  484           wr iteBackFai lure: 0,
  485           re portWriteS kip: 0,
  486           wr iteBackSki p: 0,
  487           to tal: 0
  488       }
  489  
  490       let re sults = aw ait Promis e.all(
  491           bu ndleUrl.ur ls.map(asy nc webclie ntObj => {
  492                try {
  493                    summ ary.total+ +
  494                    // r ead bundle s from VA- FHIR-Serve r
  495                    let  bundleObj  = await ge tBundle(us er_id, web clientObj. options)
  496                    bund leObj.stat usCode ==  200 ? summ ary.bundle Success++  : summary. bundleFail ure++
  497  
  498                    // w rite bundl es to amqp
  499                    let  reportWrit e = await  writeResul ts(bundleO bj, extrac tConfig, u ser_id, vi staId)
  500                    if ( reportWrit e.statusCo de == 200)  {
  501                         summary.re portWriteS ucces++
  502                    } el se if (rep ortWrite.s tatusCode  == 501) {
  503                         summary.re portWriteS kip++
  504                    } el se {
  505                         summary.re portWriteF ailure++
  506                    }
  507  
  508  
  509                    // w rite back  to vista a cknowledge ment that  claim was  posted to  report
  510                    let  writeBackR esult = aw ait writeB ack(bundle Obj, repor tWrite, ex tractConfi g, vistaId )
  511                    if ( writeBackR esult.stat usCode ==  200) {
  512                         summary.wr iteBackSuc ces++
  513                    } el se if (wri teBackResu lt.statusC ode == 501 ) {
  514                         summary.wr iteBackSki p++
  515                    } el se {
  516                         summary.wr iteBackFai lure++
  517                    }
  518  
  519                    dele te bundleO bj.bundle
  520  
  521                    debu g(webclien tObj.optio ns.uri + '  ' + util. inspect(su mmary))
  522  
  523                    let  _result =  {
  524                         statusCode : (bundleO bj.statusC ode == 200  && report Write.stat usCode ==  200 && wri teBackResu lt.statusC ode == 200 ) ? 200 :  500,
  525                         message: ( bundleObj. statusCode  == 200 &&  reportWri te.statusC ode == 200  && writeB ackResult. statusCode  == 200) ?  'Success'  : 'bundle Obj: ' + b undleObj.m essage + ' reportWrit e: ' + rep ortWrite.m essage + ' writeBackR esult: ' +  writeBack Result.mes sage,
  526                         bundleObj,
  527                         reportWrit e,
  528                         writeBack:  writeBack Result
  529                    }
  530  
  531                    // D JH 12/14/2 018 - when  we ran 10 00, result s was caus ing 2.5 MB  json, so  truncate
  532                    if ( _result.st atusCode ! = 200) {
  533                         return _re sult
  534                    } el se {
  535                         return
  536                    }
  537                } catch  (ex) {
  538                    retu rn {
  539                         statusCode : 500,
  540                         message: " Exception: " + ex.mes sage ? ex. message :  "no messag e extractC laims()",
  541                         exception:  ex
  542                    }
  543                }
  544  
  545           })
  546       )
  547  
  548       let st atusCode =  200
  549       let me ssage = 'S uccess'
  550       if ((s ummary.bun dleSuccess  + summary .reportWri teSucces +  summary.w riteBackSu cces) / 3  != summary .total) {
  551           st atusCode =  500
  552           me ssage = 'F ailure che cksum'
  553       }
  554  
  555       // DJH  12/14/201 8 remove u ndefined
  556       result s = result s.filter(n  => n)
  557  
  558       return  {
  559           st atusCode,
  560           me ssage,
  561           su mmary,
  562           re sults
  563       }
  564   }
  565  
  566  
  567   //let TEMP LATE_ecme_ iens_url =  (extractC onfig) =>   `/${extra ctConfig.f hirResourc eBundle}?l ocation=${ extractCon fig.vistaI nstance}&u se=${extra ctConfig.u se}&start= ${extractC onfig.star t}&end=${e xtractConf ig.end}`
  568   let TEMPLA TE_ecme_ie ns_url = ( extractCon fig) => `/ ${extractC onfig.fhir ResourceBu ndle}?loca tion=${ext ractConfig .vistaInst ance}&use= ${extractC onfig.use} &from=${ex tractConfi g.from}&lo g=${extrac tConfig.lo g}`
  569   let TEMPLA TE_ecme_bu ndle_url =  (extractC onfig, use , id) => ` /${extract Config.fhi rResourceB undle}?loc ation=${ex tractConfi g.vistaIns tance}&use =${use}&_i d=${id}`
  570   let TEMPLA TE_ecme_wr iteback_ur l = (extra ctConfig,  use, id) = > `/${extr actConfig. fhirResour ceClaim}/$ {id}?locat ion=${extr actConfig. vistaInsta nce}&use=$ {use}&extr actTimesta mp=${extra ctConfig.e xtractTime stamp}`
  571   //https:// DNS . URL /VA-FHIR-S erver/fhir /Claim/211 3326?locat ion=eBilli ng_dev&use =837WB
  572  
  573   /***
  574    *
  575    * @param  user_id
  576    * @param  extractCon fig
  577    * @return s {Promise <*>}
  578    *
  579    * assembl es claim i ens and ca ll loop to  loop over  
  580    *
  581    * 1) loop s over lis t of vista  servers
  582    * 2) call s VA_FHIR_ Server to  get list o f associat ed iens
  583    * 3) extr acts claim  response  URLS
  584    * 4) call s extractC laims()
  585    *  
  586    */
  587   let extrac tFromInsta nce = asyn c function  (user_id,  extractCo nfig, vist aId, statu sLog) {
  588       //let  statusLog  = fhir.sta tusLogEntr y()
  589       try {
  590           // statusLog. vistaid =  vistaId,
  591           ex tractConfi g.vistaIns tance = aw ait instan ceHelper(e xtractConf ig, vistaI d),
  592                extractC onfig.vist aId = vist aId
  593  
  594           le t URL = `$ {extractCo nfig.tasFH IREndpoint }` + TEMPL ATE_ecme_i ens_url(ex tractConfi g)
  595           le t options  = {
  596                method:  'GET',
  597                uri: URL ,
  598                headers:  {
  599                    vist aid: vista Id
  600                },
  601                retry: {
  602                    maxC ount: 40,
  603                    slee pTime: 90,
  604                    crit eria
  605                }
  606           }
  607  
  608           //  get IENs  list
  609           le t bundleOb j = await  getBundle( user_id, o ptions)
  610           st atusLog.se tStatus("i ens", bund leObj.stat usCode, bu ndleObj.me ssage, bun dleObj.uri )
  611           if  (bundleOb j.statusCo de === 500 ) {
  612                // short  circuit
  613                throw ne w Error('g etBundle()  for IENS  returned 5 00:  ' + b undleObj.m essage)
  614  
  615           }
  616  
  617           //  convert l ist of IEN s to webcl ient URL/o ptions
  618           le t bundleUr l = await  assembleCl aimURLS(ex tractConfi g, bundleO bj.bundle,  vistaId)
  619           st atusLog.se tStatus("b undleUrls" , bundleUr l.statusCo de, bundle Url.messag e, bundleO bj.uri)
  620           if  (bundleUr l.statusCo de === 500 ) {
  621                // short  circuit
  622                throw ne w Error('a ssembleCla imURLS() r eturned 50 0: ' + bun dleUrl.mes sage)
  623  
  624           }
  625  
  626           le t claimRes ponse = aw ait extrac tClaims(us er_id, ext ractConfig , bundleUr l, vistaId )
  627  
  628           cl aimRespons e.vistaId  = vistaId
  629           st atusLog.se tValue('cl aims', cla imResponse )
  630  
  631           re turn statu sLog
  632  
  633       } catc h (ex) {
  634           de bug('Excep tion: extr actFromIns tance::' +  util.insp ect(ex))
  635           st atusLog.se tException (ex, 500,  ex.message )
  636           re turn statu sLog
  637       }
  638   }
  639  
  640   /***
  641    *
  642    * @param  user_id
  643    * @param  extractCon fig
  644    * @return s {Promise <*>}
  645    *
  646    * loops o ver vista  ids
  647    * 
  648    */
  649  
  650   module.exp orts.extra ct = async  function  (user_id,  extractCon fig, statu sLog) {
  651  
  652       // set s up time  counter fo r entire p rocess sta rt to fini sh
  653       // con sole.time( "ECMEBusin essProcess ")
  654       status Log.extrac tTimestamp  = Date()
  655       let re sults
  656       let ti me0 = perf ormance.no w
  657  
  658       try {
  659           //  loop thru  enabled v istaIds fo r user 'IB TAS-ECME,A PPLICATION  PROXY' -  enabled fr om IAM moc k or alter native
  660  
  661           //  IBTAS-ECM E,APPLICAT ION PROXY  will alway s be the u ser that e xecutes th is ECME Bu siness Pro cess - cal l to IAM t o get
  662           //  list of a ll vista s ites that  have enabl ed IBTAS-E CME,APPLIC ATION PROX Y user via  the insta llation of  VistA pat ch
  663           //  IB.2.0*62 3
  664           le t iamVista Ids = awai t $tas.com mand.run(' metabase',  'data', ' load', {
  665                names: ' vistaid,sa mAccountNa me'
  666           },  {
  667                'secid':  'IBTAS-EC ME,APPLICA TION PROXY '
  668           })
  669  
  670           le t _vistaSi tes = iamV istaIds.da ta['vistai d']
  671           //  below cod e swaps ou t DUZ valu e in vista id string  from IAM w ith the us er name, ' IBTAS-ECME ,APPLICATI ON PROXY'
  672           //  special p rocessing  is perform ed by Vist A-Link whe n passing  'user name ' as oppos ed to user 's duz val ue (pointe r)
  673           le t vistaIds  = []
  674           if  (_vistaSi tes) {
  675                vistaIds  = _vistaS ites.split (',')
  676                let coun t = vistaI ds.length
  677                for (var  i = 0; i  < count; i ++) {
  678                    var  n = vistaI ds[i].inde xOf("^")
  679                    var  restofdata  = vistaId s[i].subst ring(n, 99 9)
  680                    var  newDuzName  = vistaId s[i].subst ring(0, 4)  + iamVist aIds.data. samAccount Name + res tofdata
  681                    vist aIds[i] =  newDuzName
  682                }
  683           }
  684  
  685           st atusLog.vi staIds = v istaIds
  686  
  687           le t resultPr omises = a wait vista Ids.map(as ync vistaI d => {
  688                return a wait extra ctFromInst ance(user_ id, extrac tConfig, v istaId, st atusLog)
  689           })
  690  
  691           re sults = aw ait Promis e.all(resu ltPromises )
  692  
  693           le t statusCo de = 200
  694           // statusLog. extractTim estamp = D ate()
  695           le t message  = "Success "
  696           aw ait result s.every(re sult => {
  697                if (resu lt.statusC ode !== 20 0) {
  698                    stat usCode = r esult.stat usCode
  699                    mess age = resu lt.message
  700                    retu rn false
  701                } else {
  702                    retu rn true
  703                }
  704           })
  705  
  706           re sults['sta tusCode']  = statusCo de
  707           re sults['mes sage'] = m essage
  708  
  709           st atusLog.se tValue('EC MEElapsedT ime', perf ormance.no w() - time 0)
  710  
  711  
  712           de bug('inspe ct status  log' + uti l.inspect( statusLog,  true, 5))
  713  
  714           //  console.t imeEnd("EC MEBusiness Process")
  715  
  716       } catc h (ex) {
  717           if  (!results ) {
  718                statusLo g.setExcep tion(ex, 5 00, ex.mes sage)
  719           }  else {
  720                results[ 'statusCod e'] = 500
  721                results[ 'message']  = "Severe  error: "  + ex.messa ge
  722                results[ 'exception '] = ex
  723           }
  724       }
  725  
  726       result s = result s || statu sLog
  727       return  results
  728  
  729   }
  730   module.exp orts.TEMPL ATE_ecme_b undle_url  = TEMPLATE _ecme_bund le_url
  731   module.exp orts.TEMPL ATE_ecme_i ens_url =  TEMPLATE_e cme_iens_u rl
  732   module.exp orts.TEMPL ATE_ecme_w riteback_u rl = TEMPL ATE_ecme_w riteback_u rl
  733   module.exp orts.assem bleClaimUR LS = assem bleClaimUR LS
  734   module.exp orts.write Results =  writeResul ts
  735   module.exp orts.merge  = merge
  736   module.exp orts.repor tMerge = r eportMerge