PXVWICE ;ISP/LMT - ICE interface main routine ;Jun 06, 2019@07:59:57
;;1.0;PCE PATIENT CARE ENCOUNTER;**217**;Aug 12, 1996;Build 134
;
; Thanks to George Lilly for developing (and sharing) his prototype of the interface of VistA and ICE;
; it was instrumental in the development of this production version.
;
; TODO:
; - Create national Clinical Reminders and update Build Logic
; in PX ICE MESSAGE entries that call into GETREM^PXVWVMR
; to use national reminders.
; - Add code to SELECT^ORWPC to check if ICE cache has been validated today;
; and if not, task job to validate cache, and if necessary update cache
;
;
RPC(PXRETURN,DFN,PXCHKCACHE,PXASYNC) ; Entry point for RPC
;
; Returns ICE recommendations
;
;Input:
; DFN - Patient (#2) IEN
; PXCHKCACHE - Use cached results, if available? 1=Yes; 0=No (default: 1)
; PXASYNC - Call ICE asynchronously? 1=Yes; 0=No; Handle; (default: 0)
; (See EN tag below for more info on asynchronous functionality).
;
;Returns:
; If Unsuccessful:
; 0) = X^Error Message
; Note: X can be one of the following values:
; 0: Cache is in middle of being built; check back later
; -1: Invalid input
; -2: Could not make SOAP call (e.g., URL not populated in 920.75, etc.)
; -3: HTTP call returned unsuccessful status code (i.e., Server returned status code other than 200)
; -4: Unable to process incoming message from ICE
; -5: Error during asynchronous process.
; -6: Interface is down/disabled
; n) = If SOAP call was unsuccessful, this will be the message returned by the ICE server.
;
; If Successful:
; 0) = 1 ^ Number of Lines
; n) = GRP ^ Vaccine Group Name ^ Group/CVX Code Recommended ^ Group/CVX Display Name ^ Earliest Recommended Date ^
; Overdue Date ^ Recommend Code ^ Recommend Display Name ^ Doses Remaining
; 1: GRP
; 2: Vaccine Group Name - This is the vaccine group for this recommendation
; 3: Group/CVX Code Recommended - Vaccine or vaccine group recommended.
; If a specific vaccine is recommended, this will be the CVX code, in the format C:CVX_Code.
; More commonly, this will be populated with the vaccine group, in the format G:Group_Name
; 4: Group/CVX Display Name - Display Name for CVX/Group in piece #3.
; 5: Recommended Date
; 6: Overdue Date
; 7: Earliest Date
; 8: Recommend Code (currently either RECOMMENDED, FUTURE_RECOMMENDED, CONDITIONALLY_RECOMMENDED, or NOT_RECOMMENDED)
; 9: Recommend Display Name
; 10: Doses Remaining
; n) = RSN ^ Reason Code ^ Reason Display Name
; Note: This is the reason(s) for the recommendation above.
; 1: RSN
; 2: Reason Code
; 3: Reason Display Name
; n) = HIST ^ V Immunization IEN ^ Immunization Name ^ Administered CVX Code ^ Admin date/time ^ Dose Number ^
; Component CVX Code ^ CVX Display Name ^ Validity Code ^ Validity Display Name
; 1: HIST
; 2: V Immunization IEN (#9000010.11 IEN)
; 3: Immunization Name (#9999999.14, #.01)
; 4: Administered CVX Code (#9999999.14, #.03)
; 5: Admin date/time
; 6: Dose Number
; 7: Component CVX Code (for combination vaccines, this can defer from the CVX administered)
; 8: CVX Display Name
; 9: Validity Code
; 10: Validity Display Name
; n) = HISTRSN ^ Reason Code ^ Reason Display Name
; Note: This is the reason(s) why the vaccine is valid, invalid or accepted.
; 1: HISTRSN
; 2: Reason Code
; 3: Reason Display Name
;
N PXCNT,PXI,PXICEWEB,PXJ,PXK
;
S PXRETURN=$NA(^TMP("PXICERPC",$J))
K ^TMP("PXICERPC",$J)
;
D EN(.PXICEWEB,$G(DFN),$G(PXCHKCACHE),$G(PXASYNC))
;
S PXCNT=0
;
S ^TMP("PXICERPC",$J,0)=$G(^TMP("PXICEWEB",$J,0))
;
; If Unsuccessful
I $P(^TMP("PXICERPC",$J,0),U,1)<1 D Q
. M ^TMP("PXICERPC",$J)=^TMP("PXICEWEB",$J)
;
; If Successful, flatten output
S PXI=0
F S PXI=$O(^TMP("PXICEWEB",$J,PXI)) Q:PXI="" D
. S PXCNT=PXCNT+1
. S ^TMP("PXICERPC",$J,PXCNT)="GRP^"_PXI_U_$G(^TMP("PXICEWEB",$J,PXI))
. ;
. S PXJ=""
. F S PXJ=$O(^TMP("PXICEWEB",$J,PXI,"REASON",PXJ)) Q:PXJ="" D
. . S PXCNT=PXCNT+1
. . S ^TMP("PXICERPC",$J,PXCNT)="RSN^"_$G(^TMP("PXICEWEB",$J,PXI,"REASON",PXJ))
. ;
. S PXJ=""
. F S PXJ=$O(^TMP("PXICEWEB",$J,PXI,"HISTORY",PXJ)) Q:PXJ="" D
. . S PXCNT=PXCNT+1
. . S ^TMP("PXICERPC",$J,PXCNT)="HIST^"_PXJ_U_$G(^TMP("PXICEWEB",$J,PXI,"HISTORY",PXJ))
. . ;
. . S PXK=""
. . F S PXK=$O(^TMP("PXICEWEB",$J,PXI,"HISTORY",PXJ,"REASON",PXK)) Q:PXK="" D
. . . S PXCNT=PXCNT+1
. . . S ^TMP("PXICERPC",$J,PXCNT)="HISTRSN^"_$G(^TMP("PXICEWEB",$J,PXI,"HISTORY",PXJ,"REASON",PXK))
;
S $P(^TMP("PXICERPC",$J,0),U,2)=PXCNT
;
K ^TMP("PXICEWEB",$J)
;
Q
;
;
EN(PXRETURN,DFN,PXCHKCACHE,PXASYNC) ; Entry point for API
;
; Returns ICE recommendations
;
;Input:
; DFN - Patient (#2) IEN
; PXCHKCACHE - Use cached results, if available? 1=Yes; 0=No; (default: 1)
; PXASYNC - Call ICE asynchronously? 1=Yes; 0=No; Handle; (default: 0)
; When calling ICE asynchronously, first pass "1" as the PXASYNC argument.
; If cached results are available (AND PXCHKCACHE is set to 1),
; we will return them immediately.
; If cached results are not available (OR PXCHKCACHE is set to 0),
; we will task a job to call ICE, and return a handle to the calling
; process. This handle should be passed in as the PXASYNC paramater
; on future calls. The calling process should keep checking back to see
; if the ICE task completed. On these subsequent calls, the same arguments
; should be passed in as the original call, except that in the subsequent
; calls, the PXASYNC argument should be the "handle" returned in the original
; call.
;
;
;Returns:
;
; If called asynchronously (i.e., PXASYNC>0) AND a background task was queued (or is still running):
; @PXRETURN@(0)=0^Handle
; This "Handle" is a number >1 and should be passed in on future calls.
;
; If Unsuccessful:
; @PXRETURN@(0)=X^Error Message
; Note: X can be one of the following values:
; -1: Invalid input
; -2: Could not make SOAP call (e.g., URL not populated in 920.75, etc.)
; -3: HTTP call returned unsuccessful status code (i.e., Server returned status code other than 200)
; -4: Unable to process incoming message from ICE
; -5: Error during asynchronous process.
; -6: Interface is down/disabled
; @PXRETURN@(n)=If SOAP call was unsuccessful, this will be the message returned by the ICE server.
;
; If Successful:
; @PXRETURN@(0)=1
; @PXRETURN@(VaccineGroup)=Group/CVX Code Recommended ^ Group/CVX Display Name ^ Recommended Date ^ Overdue Date ^
; Earliest Date ^ Recommend Code ^ Recommend Display Name ^ Doses Remaining
; @PXRETURN@(VaccineGroup,"REASON",n)=Reason Code ^ Reason Display Name
; @PXRETURN@(VaccineGroup,"HISTORY",V_Imm_IEN)=Immunization Name ^ Administered CVX Code ^ Admin date/time ^
; Dose Number ^ Component CVX Code ^ CVX Display Name ^
; Validity Code ^ Validity Display Name
; @PXRETURN@(VaccineGroup,"HISTORY",V_Imm_IEN,"REASON",n)=Reason Code ^ Reason Display Name
;
N PXCACHESTAT,PXCNT,PXDESC,PXHANDLE,PXRTN,PXSTALL,PXTASK,PXURL,PXVARS,PXVOTH
;
S PXRETURN=$NA(^TMP("PXICEWEB",$J))
K ^TMP("PXICEWEB",$J)
K ^TMP("PXVWMSG",$J)
S PXCNT=0
;
; TODO - if ICE is down, should we allow to return from cache if available?
; currently, if disabled, we dont check cache; but if unavailable, we check
I $$CHKSTAT^PXVWSTAT()=0 D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-6^ICE interface is disabled"
;
I $G(PXCHKCACHE)'?1(1"0",1"1") S PXCHKCACHE=1
I $G(PXASYNC)="" S PXASYNC=0
I PXASYNC>1 S PXHANDLE="PXVWICETMP-"_PXASYNC
;
I '$G(DFN) D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-1^Missing DFN parameter"
S PXURL=$$GETURL()
I PXURL="" D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-2^Unable to determine default ICE server"
;
; Check asynchronous background task and quit
I PXASYNC>1 D Q
. D ASYNC(PXHANDLE,DFN,PXASYNC,PXCNT)
. D LOGSTAT^PXVWSTAT(DFN)
;
; if synchronous, call ICE in this process
I 'PXASYNC D CALLICE
;
; if asynchronous, call ICE in tasked process. Return handle to caller.
I PXASYNC D
. ;
. ; Before tasking background process, check cache. If cache is
. ; valid, return from cache and no need to task background job.
. I PXCHKCACHE,$$EXIST^PXVWCCH(DFN) D Q:$G(PXCACHESTAT)=1
. . D BLDVMR^PXVWVMR(DFN)
. . I '$D(^TMP("PXVWMSG",$J)) D Q
. . . S ^TMP("PXICEWEB",$J,PXCNT)="-2^Unable to generate outbound VMR message"
. . . S PXCACHESTAT=1
. . S PXCACHESTAT=$$CHKCACHE(DFN,0)
. . K ^TMP("PXVWMSG",$J)
. ;
. I '$$CHKSTAT^PXVWSTAT() D Q
. . S ^TMP("PXICEWEB",$J,PXCNT)="-6^ICE interface is down"
. ;
. ; Task process to call ICE
. S PXHANDLE=$$HANDLE(DFN)
. S PXRTN="CALLICE^PXVWICE"
. S PXDESC="PCE Call ICE Engine (Immunizations)"
. S PXVARS="PXCHKCACHE;PXURL;DFN;PXHANDLE"
. S PXVOTH("ZTDTH")=$H
. S PXTASK=$$NODEV^XUTMDEVQ(PXRTN,PXDESC,PXVARS,.PXVOTH)
. ;
. I $G(PXTASK)>0 D
. . S ^XTMP(PXHANDLE,"STATUS")=0_U_PXTASK
. . S ^TMP("PXICEWEB",$J,PXCNT)="0^"_$P(PXHANDLE,"-",2)
. ;
. I $G(PXTASK)=-1 D
. . S ^TMP("PXICEWEB",$J,PXCNT)="-5^Error tasking asynchronous process."
. . K ^XTMP(PXHANDLE)
;
D LOGSTAT^PXVWSTAT(DFN)
;
K ^TMP("PXVWMSG",$J)
;
Q
;
;
CHKCACHE(DFN,PXSTALL) ;Check Cache for DFN
;
; Requires vMR to already be created in ^TMP("PXVWMSG",$J)
;
N PXCACHESTAT,PXI
;
S PXCACHESTAT=$$STAT^PXVWCCH(DFN)
;
I $G(PXSTALL),PXCACHESTAT=2 D
. F PXI=1:1:40 D Q:PXCACHESTAT'=2
. . H .5
. . S PXCACHESTAT=$$STAT^PXVWCCH(DFN)
;
I PXCACHESTAT'=1 Q PXCACHESTAT
;
D LOAD^PXVWCCH(DFN)
;
Q PXCACHESTAT
;
;
ASYNC(PXHANDLE,DFN,PXASYNC,PXCNT) ;Check asynchronous background task
;
N PXDT
;
I '$D(^XTMP(PXHANDLE)) D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-5^Error during asynchronous process."
;
I $P($G(^XTMP(PXHANDLE,1)),U,1)'=DFN D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-5^Error during asynchronous process. DFN does not match."
;
S PXDT=$P($G(^XTMP(PXHANDLE,"DT")),U,1)
I 'PXDT D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-5^Error during asynchronous process."
; if background task is running for more than 2 min, return error
I $$HDIFF^XLFDT($H,PXDT,2)>120 D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-5^Error during asynchronous process. Process timed out."
;
; background task completed.
I $P($G(^XTMP(PXHANDLE,"STATUS")),U,1)=1 D Q
. M ^TMP("PXICEWEB",$J)=^XTMP(PXHANDLE,"ICE")
. K ^XTMP(PXHANDLE)
;
; background task is still running
I $P($G(^XTMP(PXHANDLE,"STATUS")),U,1)=0 D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="0^"_PXASYNC
;
Q
;
;
CALLICE ;
;
; ZEXCEPT: PXCHKCACHE,PXURL,DFN,PXHANDLE,ZTQUEUED,ZTREQ
;
N PXCACHESTAT,PXCNT,PXNOW
;
S ZTREQ="@"
K ^TMP("PXICEWEB",$J)
K ^TMP("PXVWMSG",$J)
S PXNOW=$$NOW^XLFDT
S PXCNT=0
;
D BLDVMR^PXVWVMR(DFN)
;
I '$D(^TMP("PXVWMSG",$J)) D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-2^Unable to generate outbound VMR message"
. I $G(PXHANDLE)'="" D MOVERES(PXHANDLE)
;
; check cache
I PXCHKCACHE D Q:$G(PXCACHESTAT)=1
. S PXCACHESTAT=$$CHKCACHE(DFN,1) ;Check Cache for DFN
. I PXCACHESTAT=1 D
. . I $G(PXHANDLE)'="" D MOVERES(PXHANDLE)
. . K ^TMP("PXVWMSG",$J)
;
I '$$CHKSTAT^PXVWSTAT() D Q
. S ^TMP("PXICEWEB",$J,PXCNT)="-6^ICE interface is down"
. I $G(PXHANDLE)'="" D MOVERES(PXHANDLE)
;
; Set flag that cache is in middle of building
D BLDNG^PXVWCCH(DFN)
;
D EN^PXVWSOAP(PXURL) ; Call ICE
;
; if ICE call successfull, save output to cache
I $P($G(^TMP("PXICEWEB",$J,0)),U,1)=1 D SAVE^PXVWCCH(DFN,PXNOW)
;
; Clear flag that cache is in middle of building
D CLRBLDNG^PXVWCCH(DFN)
;
; if this is a background task, save output to XTMP
I $G(PXHANDLE)'="" D MOVERES(PXHANDLE)
;
K ^TMP("PXVWMSG",$J)
;
Q
;
;
MOVERES(PXHANDLE) ;
M ^XTMP(PXHANDLE,"ICE")=^TMP("PXICEWEB",$J)
S ^XTMP(PXHANDLE,"STATUS")=1
K ^TMP("PXICEWEB",$J)
Q
;
;
HANDLE(DFN) ;Return a unique handle into ^XTMP
;
N PXHANDLE,PXI,PXSUCCESS
;
S PXI=$R(9999)+2
S PXHANDLE="PXVWICETMP-"_PXI
F D Q:$G(PXSUCCESS)
. S PXSUCCESS=$$HANDLE2(PXHANDLE,DFN)
. I $G(PXSUCCESS) Q
. S PXI=PXI+1
. S PXHANDLE="PXVWICETMP-"_PXI
;
Q PXHANDLE
;
HANDLE2(PXHANDLE,DFN) ;
;
I $D(^XTMP(PXHANDLE)) Q 0
;
L +^XTMP(PXHANDLE):DILOCKTM
I '$T Q 0
;
I $D(^XTMP(PXHANDLE)) L -^XTMP(PXHANDLE) Q 0
;
S ^XTMP(PXHANDLE,0)=DT_".24^"_DT
S ^XTMP(PXHANDLE,1)=DFN
S ^XTMP(PXHANDLE,"STATUS")=0
S ^XTMP(PXHANDLE,"DT")=$H
;
L -^XTMP(PXHANDLE)
;
Q 1
;
;
GETURL() ; Get ICE Server URL
;
N PXIEN,PXTMP
;
S PXIEN=$$GET^XPAR("ALL","PX ICE WEB DEFAULT SERVER")
; If the value has not been set, then see if there is only one
I 'PXIEN D
. S PXTMP=$O(^PXV(920.75,0))
. I $O(^PXV(920.75,PXTMP))'>0 S PXIEN=PXTMP
I 'PXIEN Q ""
Q $$GET1^DIQ(920.75,PXIEN,8)
;
;
TESTICE() ; Test ICE Interface
; Returns:
; 1 - Success
; 0 - Fail
;
N PXSUCCESS,PXURL
;
S PXURL=$$GETURL()
I PXURL="" Q 0
;
K ^TMP("PXICEWEB",$J)
K ^TMP("PXVWMSG",$J)
;
D TESTVMR^PXVWVMR
;
I '$D(^TMP("PXVWMSG",$J)) Q 0
;
D EN^PXVWSOAP(PXURL) ; Call ICE
;
S PXSUCCESS=0
I $P($G(^TMP("PXICEWEB",$J,0)),U,1)=1 S PXSUCCESS=1
;
K ^TMP("PXICEWEB",$J)
K ^TMP("PXVWMSG",$J)
;
Q PXSUCCESS
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HPXVWICE 14197 printed Oct 16, 2024@18:32:51 Page 2
PXVWICE ;ISP/LMT - ICE interface main routine ;Jun 06, 2019@07:59:57
+1 ;;1.0;PCE PATIENT CARE ENCOUNTER;**217**;Aug 12, 1996;Build 134
+2 ;
+3 ; Thanks to George Lilly for developing (and sharing) his prototype of the interface of VistA and ICE;
+4 ; it was instrumental in the development of this production version.
+5 ;
+6 ; TODO:
+7 ; - Create national Clinical Reminders and update Build Logic
+8 ; in PX ICE MESSAGE entries that call into GETREM^PXVWVMR
+9 ; to use national reminders.
+10 ; - Add code to SELECT^ORWPC to check if ICE cache has been validated today;
+11 ; and if not, task job to validate cache, and if necessary update cache
+12 ;
+13 ;
RPC(PXRETURN,DFN,PXCHKCACHE,PXASYNC) ; Entry point for RPC
+1 ;
+2 ; Returns ICE recommendations
+3 ;
+4 ;Input:
+5 ; DFN - Patient (#2) IEN
+6 ; PXCHKCACHE - Use cached results, if available? 1=Yes; 0=No (default: 1)
+7 ; PXASYNC - Call ICE asynchronously? 1=Yes; 0=No; Handle; (default: 0)
+8 ; (See EN tag below for more info on asynchronous functionality).
+9 ;
+10 ;Returns:
+11 ; If Unsuccessful:
+12 ; 0) = X^Error Message
+13 ; Note: X can be one of the following values:
+14 ; 0: Cache is in middle of being built; check back later
+15 ; -1: Invalid input
+16 ; -2: Could not make SOAP call (e.g., URL not populated in 920.75, etc.)
+17 ; -3: HTTP call returned unsuccessful status code (i.e., Server returned status code other than 200)
+18 ; -4: Unable to process incoming message from ICE
+19 ; -5: Error during asynchronous process.
+20 ; -6: Interface is down/disabled
+21 ; n) = If SOAP call was unsuccessful, this will be the message returned by the ICE server.
+22 ;
+23 ; If Successful:
+24 ; 0) = 1 ^ Number of Lines
+25 ; n) = GRP ^ Vaccine Group Name ^ Group/CVX Code Recommended ^ Group/CVX Display Name ^ Earliest Recommended Date ^
+26 ; Overdue Date ^ Recommend Code ^ Recommend Display Name ^ Doses Remaining
+27 ; 1: GRP
+28 ; 2: Vaccine Group Name - This is the vaccine group for this recommendation
+29 ; 3: Group/CVX Code Recommended - Vaccine or vaccine group recommended.
+30 ; If a specific vaccine is recommended, this will be the CVX code, in the format C:CVX_Code.
+31 ; More commonly, this will be populated with the vaccine group, in the format G:Group_Name
+32 ; 4: Group/CVX Display Name - Display Name for CVX/Group in piece #3.
+33 ; 5: Recommended Date
+34 ; 6: Overdue Date
+35 ; 7: Earliest Date
+36 ; 8: Recommend Code (currently either RECOMMENDED, FUTURE_RECOMMENDED, CONDITIONALLY_RECOMMENDED, or NOT_RECOMMENDED)
+37 ; 9: Recommend Display Name
+38 ; 10: Doses Remaining
+39 ; n) = RSN ^ Reason Code ^ Reason Display Name
+40 ; Note: This is the reason(s) for the recommendation above.
+41 ; 1: RSN
+42 ; 2: Reason Code
+43 ; 3: Reason Display Name
+44 ; n) = HIST ^ V Immunization IEN ^ Immunization Name ^ Administered CVX Code ^ Admin date/time ^ Dose Number ^
+45 ; Component CVX Code ^ CVX Display Name ^ Validity Code ^ Validity Display Name
+46 ; 1: HIST
+47 ; 2: V Immunization IEN (#9000010.11 IEN)
+48 ; 3: Immunization Name (#9999999.14, #.01)
+49 ; 4: Administered CVX Code (#9999999.14, #.03)
+50 ; 5: Admin date/time
+51 ; 6: Dose Number
+52 ; 7: Component CVX Code (for combination vaccines, this can defer from the CVX administered)
+53 ; 8: CVX Display Name
+54 ; 9: Validity Code
+55 ; 10: Validity Display Name
+56 ; n) = HISTRSN ^ Reason Code ^ Reason Display Name
+57 ; Note: This is the reason(s) why the vaccine is valid, invalid or accepted.
+58 ; 1: HISTRSN
+59 ; 2: Reason Code
+60 ; 3: Reason Display Name
+61 ;
+62 NEW PXCNT,PXI,PXICEWEB,PXJ,PXK
+63 ;
+64 SET PXRETURN=$NAME(^TMP("PXICERPC",$JOB))
+65 KILL ^TMP("PXICERPC",$JOB)
+66 ;
+67 DO EN(.PXICEWEB,$GET(DFN),$GET(PXCHKCACHE),$GET(PXASYNC))
+68 ;
+69 SET PXCNT=0
+70 ;
+71 SET ^TMP("PXICERPC",$JOB,0)=$GET(^TMP("PXICEWEB",$JOB,0))
+72 ;
+73 ; If Unsuccessful
+74 IF $PIECE(^TMP("PXICERPC",$JOB,0),U,1)<1
Begin DoDot:1
+75 MERGE ^TMP("PXICERPC",$JOB)=^TMP("PXICEWEB",$JOB)
End DoDot:1
QUIT
+76 ;
+77 ; If Successful, flatten output
+78 SET PXI=0
+79 FOR
SET PXI=$ORDER(^TMP("PXICEWEB",$JOB,PXI))
if PXI=""
QUIT
Begin DoDot:1
+80 SET PXCNT=PXCNT+1
+81 SET ^TMP("PXICERPC",$JOB,PXCNT)="GRP^"_PXI_U_$GET(^TMP("PXICEWEB",$JOB,PXI))
+82 ;
+83 SET PXJ=""
+84 FOR
SET PXJ=$ORDER(^TMP("PXICEWEB",$JOB,PXI,"REASON",PXJ))
if PXJ=""
QUIT
Begin DoDot:2
+85 SET PXCNT=PXCNT+1
+86 SET ^TMP("PXICERPC",$JOB,PXCNT)="RSN^"_$GET(^TMP("PXICEWEB",$JOB,PXI,"REASON",PXJ))
End DoDot:2
+87 ;
+88 SET PXJ=""
+89 FOR
SET PXJ=$ORDER(^TMP("PXICEWEB",$JOB,PXI,"HISTORY",PXJ))
if PXJ=""
QUIT
Begin DoDot:2
+90 SET PXCNT=PXCNT+1
+91 SET ^TMP("PXICERPC",$JOB,PXCNT)="HIST^"_PXJ_U_$GET(^TMP("PXICEWEB",$JOB,PXI,"HISTORY",PXJ))
+92 ;
+93 SET PXK=""
+94 FOR
SET PXK=$ORDER(^TMP("PXICEWEB",$JOB,PXI,"HISTORY",PXJ,"REASON",PXK))
if PXK=""
QUIT
Begin DoDot:3
+95 SET PXCNT=PXCNT+1
+96 SET ^TMP("PXICERPC",$JOB,PXCNT)="HISTRSN^"_$GET(^TMP("PXICEWEB",$JOB,PXI,"HISTORY",PXJ,"REASON",PXK))
End DoDot:3
End DoDot:2
End DoDot:1
+97 ;
+98 SET $PIECE(^TMP("PXICERPC",$JOB,0),U,2)=PXCNT
+99 ;
+100 KILL ^TMP("PXICEWEB",$JOB)
+101 ;
+102 QUIT
+103 ;
+104 ;
EN(PXRETURN,DFN,PXCHKCACHE,PXASYNC) ; Entry point for API
+1 ;
+2 ; Returns ICE recommendations
+3 ;
+4 ;Input:
+5 ; DFN - Patient (#2) IEN
+6 ; PXCHKCACHE - Use cached results, if available? 1=Yes; 0=No; (default: 1)
+7 ; PXASYNC - Call ICE asynchronously? 1=Yes; 0=No; Handle; (default: 0)
+8 ; When calling ICE asynchronously, first pass "1" as the PXASYNC argument.
+9 ; If cached results are available (AND PXCHKCACHE is set to 1),
+10 ; we will return them immediately.
+11 ; If cached results are not available (OR PXCHKCACHE is set to 0),
+12 ; we will task a job to call ICE, and return a handle to the calling
+13 ; process. This handle should be passed in as the PXASYNC paramater
+14 ; on future calls. The calling process should keep checking back to see
+15 ; if the ICE task completed. On these subsequent calls, the same arguments
+16 ; should be passed in as the original call, except that in the subsequent
+17 ; calls, the PXASYNC argument should be the "handle" returned in the original
+18 ; call.
+19 ;
+20 ;
+21 ;Returns:
+22 ;
+23 ; If called asynchronously (i.e., PXASYNC>0) AND a background task was queued (or is still running):
+24 ; @PXRETURN@(0)=0^Handle
+25 ; This "Handle" is a number >1 and should be passed in on future calls.
+26 ;
+27 ; If Unsuccessful:
+28 ; @PXRETURN@(0)=X^Error Message
+29 ; Note: X can be one of the following values:
+30 ; -1: Invalid input
+31 ; -2: Could not make SOAP call (e.g., URL not populated in 920.75, etc.)
+32 ; -3: HTTP call returned unsuccessful status code (i.e., Server returned status code other than 200)
+33 ; -4: Unable to process incoming message from ICE
+34 ; -5: Error during asynchronous process.
+35 ; -6: Interface is down/disabled
+36 ; @PXRETURN@(n)=If SOAP call was unsuccessful, this will be the message returned by the ICE server.
+37 ;
+38 ; If Successful:
+39 ; @PXRETURN@(0)=1
+40 ; @PXRETURN@(VaccineGroup)=Group/CVX Code Recommended ^ Group/CVX Display Name ^ Recommended Date ^ Overdue Date ^
+41 ; Earliest Date ^ Recommend Code ^ Recommend Display Name ^ Doses Remaining
+42 ; @PXRETURN@(VaccineGroup,"REASON",n)=Reason Code ^ Reason Display Name
+43 ; @PXRETURN@(VaccineGroup,"HISTORY",V_Imm_IEN)=Immunization Name ^ Administered CVX Code ^ Admin date/time ^
+44 ; Dose Number ^ Component CVX Code ^ CVX Display Name ^
+45 ; Validity Code ^ Validity Display Name
+46 ; @PXRETURN@(VaccineGroup,"HISTORY",V_Imm_IEN,"REASON",n)=Reason Code ^ Reason Display Name
+47 ;
+48 NEW PXCACHESTAT,PXCNT,PXDESC,PXHANDLE,PXRTN,PXSTALL,PXTASK,PXURL,PXVARS,PXVOTH
+49 ;
+50 SET PXRETURN=$NAME(^TMP("PXICEWEB",$JOB))
+51 KILL ^TMP("PXICEWEB",$JOB)
+52 KILL ^TMP("PXVWMSG",$JOB)
+53 SET PXCNT=0
+54 ;
+55 ; TODO - if ICE is down, should we allow to return from cache if available?
+56 ; currently, if disabled, we dont check cache; but if unavailable, we check
+57 IF $$CHKSTAT^PXVWSTAT()=0
Begin DoDot:1
+58 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-6^ICE interface is disabled"
End DoDot:1
QUIT
+59 ;
+60 IF $GET(PXCHKCACHE)'?1(1"0",1"1")
SET PXCHKCACHE=1
+61 IF $GET(PXASYNC)=""
SET PXASYNC=0
+62 IF PXASYNC>1
SET PXHANDLE="PXVWICETMP-"_PXASYNC
+63 ;
+64 IF '$GET(DFN)
Begin DoDot:1
+65 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-1^Missing DFN parameter"
End DoDot:1
QUIT
+66 SET PXURL=$$GETURL()
+67 IF PXURL=""
Begin DoDot:1
+68 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-2^Unable to determine default ICE server"
End DoDot:1
QUIT
+69 ;
+70 ; Check asynchronous background task and quit
+71 IF PXASYNC>1
Begin DoDot:1
+72 DO ASYNC(PXHANDLE,DFN,PXASYNC,PXCNT)
+73 DO LOGSTAT^PXVWSTAT(DFN)
End DoDot:1
QUIT
+74 ;
+75 ; if synchronous, call ICE in this process
+76 IF 'PXASYNC
DO CALLICE
+77 ;
+78 ; if asynchronous, call ICE in tasked process. Return handle to caller.
+79 IF PXASYNC
Begin DoDot:1
+80 ;
+81 ; Before tasking background process, check cache. If cache is
+82 ; valid, return from cache and no need to task background job.
+83 IF PXCHKCACHE
IF $$EXIST^PXVWCCH(DFN)
Begin DoDot:2
+84 DO BLDVMR^PXVWVMR(DFN)
+85 IF '$DATA(^TMP("PXVWMSG",$JOB))
Begin DoDot:3
+86 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-2^Unable to generate outbound VMR message"
+87 SET PXCACHESTAT=1
End DoDot:3
QUIT
+88 SET PXCACHESTAT=$$CHKCACHE(DFN,0)
+89 KILL ^TMP("PXVWMSG",$JOB)
End DoDot:2
if $GET(PXCACHESTAT)=1
QUIT
+90 ;
+91 IF '$$CHKSTAT^PXVWSTAT()
Begin DoDot:2
+92 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-6^ICE interface is down"
End DoDot:2
QUIT
+93 ;
+94 ; Task process to call ICE
+95 SET PXHANDLE=$$HANDLE(DFN)
+96 SET PXRTN="CALLICE^PXVWICE"
+97 SET PXDESC="PCE Call ICE Engine (Immunizations)"
+98 SET PXVARS="PXCHKCACHE;PXURL;DFN;PXHANDLE"
+99 SET PXVOTH("ZTDTH")=$HOROLOG
+100 SET PXTASK=$$NODEV^XUTMDEVQ(PXRTN,PXDESC,PXVARS,.PXVOTH)
+101 ;
+102 IF $GET(PXTASK)>0
Begin DoDot:2
+103 SET ^XTMP(PXHANDLE,"STATUS")=0_U_PXTASK
+104 SET ^TMP("PXICEWEB",$JOB,PXCNT)="0^"_$PIECE(PXHANDLE,"-",2)
End DoDot:2
+105 ;
+106 IF $GET(PXTASK)=-1
Begin DoDot:2
+107 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-5^Error tasking asynchronous process."
+108 KILL ^XTMP(PXHANDLE)
End DoDot:2
End DoDot:1
+109 ;
+110 DO LOGSTAT^PXVWSTAT(DFN)
+111 ;
+112 KILL ^TMP("PXVWMSG",$JOB)
+113 ;
+114 QUIT
+115 ;
+116 ;
CHKCACHE(DFN,PXSTALL) ;Check Cache for DFN
+1 ;
+2 ; Requires vMR to already be created in ^TMP("PXVWMSG",$J)
+3 ;
+4 NEW PXCACHESTAT,PXI
+5 ;
+6 SET PXCACHESTAT=$$STAT^PXVWCCH(DFN)
+7 ;
+8 IF $GET(PXSTALL)
IF PXCACHESTAT=2
Begin DoDot:1
+9 FOR PXI=1:1:40
Begin DoDot:2
+10 HANG .5
+11 SET PXCACHESTAT=$$STAT^PXVWCCH(DFN)
End DoDot:2
if PXCACHESTAT'=2
QUIT
End DoDot:1
+12 ;
+13 IF PXCACHESTAT'=1
QUIT PXCACHESTAT
+14 ;
+15 DO LOAD^PXVWCCH(DFN)
+16 ;
+17 QUIT PXCACHESTAT
+18 ;
+19 ;
ASYNC(PXHANDLE,DFN,PXASYNC,PXCNT) ;Check asynchronous background task
+1 ;
+2 NEW PXDT
+3 ;
+4 IF '$DATA(^XTMP(PXHANDLE))
Begin DoDot:1
+5 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-5^Error during asynchronous process."
End DoDot:1
QUIT
+6 ;
+7 IF $PIECE($GET(^XTMP(PXHANDLE,1)),U,1)'=DFN
Begin DoDot:1
+8 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-5^Error during asynchronous process. DFN does not match."
End DoDot:1
QUIT
+9 ;
+10 SET PXDT=$PIECE($GET(^XTMP(PXHANDLE,"DT")),U,1)
+11 IF 'PXDT
Begin DoDot:1
+12 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-5^Error during asynchronous process."
End DoDot:1
QUIT
+13 ; if background task is running for more than 2 min, return error
+14 IF $$HDIFF^XLFDT($HOROLOG,PXDT,2)>120
Begin DoDot:1
+15 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-5^Error during asynchronous process. Process timed out."
End DoDot:1
QUIT
+16 ;
+17 ; background task completed.
+18 IF $PIECE($GET(^XTMP(PXHANDLE,"STATUS")),U,1)=1
Begin DoDot:1
+19 MERGE ^TMP("PXICEWEB",$JOB)=^XTMP(PXHANDLE,"ICE")
+20 KILL ^XTMP(PXHANDLE)
End DoDot:1
QUIT
+21 ;
+22 ; background task is still running
+23 IF $PIECE($GET(^XTMP(PXHANDLE,"STATUS")),U,1)=0
Begin DoDot:1
+24 SET ^TMP("PXICEWEB",$JOB,PXCNT)="0^"_PXASYNC
End DoDot:1
QUIT
+25 ;
+26 QUIT
+27 ;
+28 ;
CALLICE ;
+1 ;
+2 ; ZEXCEPT: PXCHKCACHE,PXURL,DFN,PXHANDLE,ZTQUEUED,ZTREQ
+3 ;
+4 NEW PXCACHESTAT,PXCNT,PXNOW
+5 ;
+6 SET ZTREQ="@"
+7 KILL ^TMP("PXICEWEB",$JOB)
+8 KILL ^TMP("PXVWMSG",$JOB)
+9 SET PXNOW=$$NOW^XLFDT
+10 SET PXCNT=0
+11 ;
+12 DO BLDVMR^PXVWVMR(DFN)
+13 ;
+14 IF '$DATA(^TMP("PXVWMSG",$JOB))
Begin DoDot:1
+15 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-2^Unable to generate outbound VMR message"
+16 IF $GET(PXHANDLE)'=""
DO MOVERES(PXHANDLE)
End DoDot:1
QUIT
+17 ;
+18 ; check cache
+19 IF PXCHKCACHE
Begin DoDot:1
+20 ;Check Cache for DFN
SET PXCACHESTAT=$$CHKCACHE(DFN,1)
+21 IF PXCACHESTAT=1
Begin DoDot:2
+22 IF $GET(PXHANDLE)'=""
DO MOVERES(PXHANDLE)
+23 KILL ^TMP("PXVWMSG",$JOB)
End DoDot:2
End DoDot:1
if $GET(PXCACHESTAT)=1
QUIT
+24 ;
+25 IF '$$CHKSTAT^PXVWSTAT()
Begin DoDot:1
+26 SET ^TMP("PXICEWEB",$JOB,PXCNT)="-6^ICE interface is down"
+27 IF $GET(PXHANDLE)'=""
DO MOVERES(PXHANDLE)
End DoDot:1
QUIT
+28 ;
+29 ; Set flag that cache is in middle of building
+30 DO BLDNG^PXVWCCH(DFN)
+31 ;
+32 ; Call ICE
DO EN^PXVWSOAP(PXURL)
+33 ;
+34 ; if ICE call successfull, save output to cache
+35 IF $PIECE($GET(^TMP("PXICEWEB",$JOB,0)),U,1)=1
DO SAVE^PXVWCCH(DFN,PXNOW)
+36 ;
+37 ; Clear flag that cache is in middle of building
+38 DO CLRBLDNG^PXVWCCH(DFN)
+39 ;
+40 ; if this is a background task, save output to XTMP
+41 IF $GET(PXHANDLE)'=""
DO MOVERES(PXHANDLE)
+42 ;
+43 KILL ^TMP("PXVWMSG",$JOB)
+44 ;
+45 QUIT
+46 ;
+47 ;
MOVERES(PXHANDLE) ;
+1 MERGE ^XTMP(PXHANDLE,"ICE")=^TMP("PXICEWEB",$JOB)
+2 SET ^XTMP(PXHANDLE,"STATUS")=1
+3 KILL ^TMP("PXICEWEB",$JOB)
+4 QUIT
+5 ;
+6 ;
HANDLE(DFN) ;Return a unique handle into ^XTMP
+1 ;
+2 NEW PXHANDLE,PXI,PXSUCCESS
+3 ;
+4 SET PXI=$RANDOM(9999)+2
+5 SET PXHANDLE="PXVWICETMP-"_PXI
+6 FOR
Begin DoDot:1
+7 SET PXSUCCESS=$$HANDLE2(PXHANDLE,DFN)
+8 IF $GET(PXSUCCESS)
QUIT
+9 SET PXI=PXI+1
+10 SET PXHANDLE="PXVWICETMP-"_PXI
End DoDot:1
if $GET(PXSUCCESS)
QUIT
+11 ;
+12 QUIT PXHANDLE
+13 ;
HANDLE2(PXHANDLE,DFN) ;
+1 ;
+2 IF $DATA(^XTMP(PXHANDLE))
QUIT 0
+3 ;
+4 LOCK +^XTMP(PXHANDLE):DILOCKTM
+5 IF '$TEST
QUIT 0
+6 ;
+7 IF $DATA(^XTMP(PXHANDLE))
LOCK -^XTMP(PXHANDLE)
QUIT 0
+8 ;
+9 SET ^XTMP(PXHANDLE,0)=DT_".24^"_DT
+10 SET ^XTMP(PXHANDLE,1)=DFN
+11 SET ^XTMP(PXHANDLE,"STATUS")=0
+12 SET ^XTMP(PXHANDLE,"DT")=$HOROLOG
+13 ;
+14 LOCK -^XTMP(PXHANDLE)
+15 ;
+16 QUIT 1
+17 ;
+18 ;
GETURL() ; Get ICE Server URL
+1 ;
+2 NEW PXIEN,PXTMP
+3 ;
+4 SET PXIEN=$$GET^XPAR("ALL","PX ICE WEB DEFAULT SERVER")
+5 ; If the value has not been set, then see if there is only one
+6 IF 'PXIEN
Begin DoDot:1
+7 SET PXTMP=$ORDER(^PXV(920.75,0))
+8 IF $ORDER(^PXV(920.75,PXTMP))'>0
SET PXIEN=PXTMP
End DoDot:1
+9 IF 'PXIEN
QUIT ""
+10 QUIT $$GET1^DIQ(920.75,PXIEN,8)
+11 ;
+12 ;
TESTICE() ; Test ICE Interface
+1 ; Returns:
+2 ; 1 - Success
+3 ; 0 - Fail
+4 ;
+5 NEW PXSUCCESS,PXURL
+6 ;
+7 SET PXURL=$$GETURL()
+8 IF PXURL=""
QUIT 0
+9 ;
+10 KILL ^TMP("PXICEWEB",$JOB)
+11 KILL ^TMP("PXVWMSG",$JOB)
+12 ;
+13 DO TESTVMR^PXVWVMR
+14 ;
+15 IF '$DATA(^TMP("PXVWMSG",$JOB))
QUIT 0
+16 ;
+17 ; Call ICE
DO EN^PXVWSOAP(PXURL)
+18 ;
+19 SET PXSUCCESS=0
+20 IF $PIECE($GET(^TMP("PXICEWEB",$JOB,0)),U,1)=1
SET PXSUCCESS=1
+21 ;
+22 KILL ^TMP("PXICEWEB",$JOB)
+23 KILL ^TMP("PXVWMSG",$JOB)
+24 ;
+25 QUIT PXSUCCESS