INHUT7 ; KAC ; 8 Jan 98 17:16; HL7 Utilities
;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
;COPYRIGHT 1991-2000 SAIC
Q
;
GETDEST(INACKTT,INA,INACKDST,INACKUIF) ; $$function - Used to support routing
; of Application Acknowledgement messages to the originating system
; when multiple instantiations of a remote system type exist. Only
; one of the input parameters (INA,INACKDST,INACKUIF) must be
; specified by the caller to route an Application Ack. If a valid
; destination cannot be identified, a fatal script error is logged
; and the O/P Ctlr will log an error in ^INTHER.
;
; Called by: SCRIPT GENERATOR MESSAGE file, Outgoing Initial MUMPS
; Code field, S INDEST=$$GETDEST^INHUT(INTT,.INA,INDEST)
;
; Input:
; INACKTT - (req) INTERFACE TRANSACTION TYPE IEN for Application
; Ack. Used for error handling.
; INA - (req) array containing information for routing
; Application Ack to originator's dest as
; specified by GIS Receiver
; INACKDST - (opt) INTERFACE DESTINATION IEN for outbound
; Application Ack as specified by user
; INACKUIF - (opt) UNIVERSAL INTERFACE IEN for outbound Application
; Ack. Contains destination specified for this
; Ack at time of Ack creation. Future implementation.
;
; Variables:
; X - scratch
; INERRMSG - error message to be returned in INHERR by Ack script
;
; Output:
; - INTERFACE DESTINATION IEN for outbound Application Ack
; - "" if fails to find valid dest
;
N INERRMSG,X
;
; GIS-Receiver-specified dest
I $G(INA("INDEST")),$D(^INRHD(INA("INDEST"),0)) Q INA("INDEST")
;
; User-specified dest
I $G(INACKDST),$D(^INRHD(INACKDST,0)) Q INACKDST
;
; Ack msg exists - use dest specified at time of msg creation
I $G(INACKUIF) S X=$P($G(^INTHU(INACKUIF,0)),U,2) I X,$D(^INRHD(X,0)) Q X
;
; Error - no valid destinations identified
S INERRMSG="Application Ack creation failed - no valid destinations identified for Ack transaction type "_$S($G(INACKTT):$P($G(^INRHT(INACKTT,0)),U),1:"")
D ERROR^INHS(INERRMSG,2) ; fatal Ack script error - set INHERR
Q ""
;
SUBESC(INREC,INDEL,INB) ;Substitute escape delimeters to and from HL7
; spec
;Input:
; INREC - Portion of HL7 MSG to check
; INDEL(opt) = FSRET values - each position is critical
; ie S INDEL="^\|~&"
; or
; array of delimiters
; S INDEL("F")="^"
; S INDEL("S")="\"
; S INDEL("R")="|"
; S INDEL("E")="~"
; S INDEL("T")="&"
; INB - I inbound, O outbound
;Returns - Record with replace values
;Outbound
Q:$G(INB)="O" $$CNVDLM(.INREC,.INDEL)
;Inbound
Q:$G(INB)="I" $$DLMCNV(.INREC,.INDEL)
Q INREC
CNVDLM(INREC,INDEL) ;;Convert delimeters to HL7 specifications if in record
; Input: INREC - Portion of HL7 MSG to check
; INDEL(opt) = FSRET values - each position is critical
; ie S INDEL="^\|~&"
; or
; array of delimiters
; S INDEL("F")="^"
; S INDEL("S")="\"
; S INDEL("R")="|"
; S INDEL("E")="~"
; S INDEL("T")="&"
; Returns - Record with replace values
;
N INF,I,J,K,E,R,S,F,T,INREC1,IND
S (INREC1,E,R,S,F,T)="",IND="FSRET"
I $L($G(INDEL)) F I=1:1:5 S @$E(IND,I)=$E(INDEL,I)
E I $D(INDEL)>1 S I="" F S I=$O(INDEL(I)) Q:I="" S @I=INDEL(I)
S:E="" E=$$ESC^INHUT() S:R="" R=$$REP^INHUT() S:S="" S=$$COMP^INHUT()
S:F="" F=$$FIELD^INHUT() S:T="" T=$$SUBCOMP^INHUT()
;
;Set array of HL7 delimters to replacement value
S J(R)=E_"R"_E,J(S)=E_"S"_E,J(E)=E_"E"_E,J(F)=E_"F"_E,J(T)=E_"T"_E
;
;loop through record looking for HL7 delimters
F K=1:1:$L(INREC) D
.;if special character doesn't exist keep else replace
.I '$D(J($E(INREC,K))) S INREC1=INREC1_$E(INREC,K)
.E S INREC1=INREC1_J($E(INREC,K))
Q INREC1
DLMCNV(INREC,INDEL) ;;HL7 specifications to correct delimitor if in record
; Input: INREC - Portion of HL7 MSG to check
; INDEL(opt) = FSRET values - each position is critical
; ie S INDEL="^\|~&"
; or
; array of delimiters
; S INDEL("F")="^"
; S INDEL("S")="\"
; S INDEL("R")="|"
; S INDEL("E")="~"
; S INDEL("T")="&"
; Returns - Record with replace values
;
N INF,I,J,K,E,R,S,F,T,INREC1,IND
S (INREC1,E,R,S,F,T)="",IND="FSRET"
I $L($G(INDEL)) F I=1:1:5 S @$E(IND,I)=$E(INDEL,I)
E I $D(INDEL)>1 S I="" F S I=$O(INDEL(I)) Q:I="" S @I=INDEL(I)
S:E="" E=$$ESC^INHUT() S:R="" R=$$REP^INHUT() S:S="" S=$$COMP^INHUT()
S:F="" F=$$FIELD^INHUT() S:T="" T=$$SUBCOMP^INHUT()
;
;Set array of HL7 delimters to replacement value
S J("R")=R,J("S")=S,J("E")=E,J("F")=F,J("T")=T
;
;loop through record looking for HL7 delimters
F S K=$F(INREC,E) Q:'K!($E(INREC,K+1)="") I $E(INREC,K+1)=E D
.S INREC1=INREC1_$E(INREC,1,K-2)
.I $D(J($E(INREC,K))) S INREC1=INREC1_J($E(INREC,K))
.E S INREC1=INREC1_$E(INREC,K-1,K+1)
.S INREC=$E(INREC,K+2,$L(INREC))
S INREC1=INREC1_INREC
Q INREC1
APPACK(INUIF,INAKMES,INASTAT,INERMSG) ;User API to ACKLOG^INHU
;
; Inputs:
; INUIF = UIF ien of ack message in Universal Interface file
; INAKMES = Acked message ID - Typically: @INV@("MSA2")
; INASTAT = Ack message status - Typically: @INV@("MSA1"), converted
; to 0=NAK or 1=ACK. ex: S INASTAT=("AA"=INASTAT)
; INERMSG = Message to store if NAK. Typically: @INV@("MSA6")
;
; Usage:
; D APPACK^INHUT(UIF,@INV@("MSA2"),@INV@("MSA1"),@INV@("MSA6"))
;
S INAKMES=$G(INAKMES),INASTAT=$G(INASTAT),INERMSG=$G(INERMSG)
N INFERR,INFMSG
S (INFERR,INFMSG)=""
;
I INAKMES="" S INFMSG="No message identified to acknowledge",INFERR=2
I 'INFERR D ;save the worst error
.I '$D(^INTHU("C",INAKMES)) S INFMSG="Acknowledge for unknown message ID - "_INAKMES,INFERR=2 Q
.I INASTAT S INASTAT=1 Q
.I $E(INASTAT,2)="A" S INASTAT=1 Q
.I INASTAT="" S INERMSG=$S($L(INERMSG):$E(INERMSG,1,475)_" ",1:"")_"No ACK status"
.S INASTAT=0
I INFERR D ERROR^INHS(INFMSG,INFERR) Q
D ACKLOG^INHU(INUIF,INAKMES,INASTAT,INERMSG)
Q
;
SETENV ;Set environment for GIS with DUZ postmaster array
S U="^",DUZ=.5,DUZ(0)="@",IO="",DTIME=1
;If Postmaster has no default division, find one and set it.
;IHS logic
I '$$SC^INHUTIL1 D SETDT^UTDT K Z Q
;CHCS logic
I '$P(^DIC(3,DUZ,0),U,16) D SETDIV
D SETDT^UTDT
D DUZAG^XUS1 ; set up agency codes, no user prompts
D ^XUDIV ; set up division. No user prompts since default div is set
K Z
Q
;
SETDIV ;Called from SETENV if needed to stuff the postmaster default division.
N INDEF,INDIV
S (INDEF,INDIV)=0 F S INDIV=$O(^DG(40.8,INDIV)) Q:'INDIV!INDEF D
.;Set as default if a) an inpatient facility and b) not inactive
.I $G(^DG(40.8,INDIV,8100)),'$G(^DG(40.8,INDIV,28)) S INDEF=INDIV
;If no divisions meet criteria, look for first non active division
I 'INDEF S INDEV=0 F S INDIV=$O(^DG(40.8,INDIV)) Q:'INDIV!INDEF D
.I '$G(^DG(40.8,INDIV,28)) S INDEF=INDIV
;If still no INDEFault, set default to first entry in 40.8
S:'INDEF INDEF=$O(^DG(40.8,0))
S DIE="^DIC(3,",DA=.5,DR="28.2///`"_INDEF D ^DIE
Q
;
INHUT7 ; KAC ; 8 Jan 98 17:16; HL7 Utilities
+1 ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
+2 ;COPYRIGHT 1991-2000 SAIC
+3 QUIT
+4 ;
GETDEST(INACKTT,INA,INACKDST,INACKUIF) ; $$function - Used to support routing
+1 ; of Application Acknowledgement messages to the originating system
+2 ; when multiple instantiations of a remote system type exist. Only
+3 ; one of the input parameters (INA,INACKDST,INACKUIF) must be
+4 ; specified by the caller to route an Application Ack. If a valid
+5 ; destination cannot be identified, a fatal script error is logged
+6 ; and the O/P Ctlr will log an error in ^INTHER.
+7 ;
+8 ; Called by: SCRIPT GENERATOR MESSAGE file, Outgoing Initial MUMPS
+9 ; Code field, S INDEST=$$GETDEST^INHUT(INTT,.INA,INDEST)
+10 ;
+11 ; Input:
+12 ; INACKTT - (req) INTERFACE TRANSACTION TYPE IEN for Application
+13 ; Ack. Used for error handling.
+14 ; INA - (req) array containing information for routing
+15 ; Application Ack to originator's dest as
+16 ; specified by GIS Receiver
+17 ; INACKDST - (opt) INTERFACE DESTINATION IEN for outbound
+18 ; Application Ack as specified by user
+19 ; INACKUIF - (opt) UNIVERSAL INTERFACE IEN for outbound Application
+20 ; Ack. Contains destination specified for this
+21 ; Ack at time of Ack creation. Future implementation.
+22 ;
+23 ; Variables:
+24 ; X - scratch
+25 ; INERRMSG - error message to be returned in INHERR by Ack script
+26 ;
+27 ; Output:
+28 ; - INTERFACE DESTINATION IEN for outbound Application Ack
+29 ; - "" if fails to find valid dest
+30 ;
+31 NEW INERRMSG,X
+32 ;
+33 ; GIS-Receiver-specified dest
+34 IF $GET(INA("INDEST"))
IF $DATA(^INRHD(INA("INDEST"),0))
QUIT INA("INDEST")
+35 ;
+36 ; User-specified dest
+37 IF $GET(INACKDST)
IF $DATA(^INRHD(INACKDST,0))
QUIT INACKDST
+38 ;
+39 ; Ack msg exists - use dest specified at time of msg creation
+40 IF $GET(INACKUIF)
SET X=$PIECE($GET(^INTHU(INACKUIF,0)),U,2)
IF X
IF $DATA(^INRHD(X,0))
QUIT X
+41 ;
+42 ; Error - no valid destinations identified
+43 SET INERRMSG="Application Ack creation failed - no valid destinations identified for Ack transaction type "_$SELECT($GET(INACKTT):$PIECE($GET(^INRHT(INACKTT,0)),U),1:"")
+44 ; fatal Ack script error - set INHERR
DO ERROR^INHS(INERRMSG,2)
+45 QUIT ""
+46 ;
SUBESC(INREC,INDEL,INB) ;Substitute escape delimeters to and from HL7
+1 ; spec
+2 ;Input:
+3 ; INREC - Portion of HL7 MSG to check
+4 ; INDEL(opt) = FSRET values - each position is critical
+5 ; ie S INDEL="^\|~&"
+6 ; or
+7 ; array of delimiters
+8 ; S INDEL("F")="^"
+9 ; S INDEL("S")="\"
+10 ; S INDEL("R")="|"
+11 ; S INDEL("E")="~"
+12 ; S INDEL("T")="&"
+13 ; INB - I inbound, O outbound
+14 ;Returns - Record with replace values
+15 ;Outbound
+16 IF $GET(INB)="O"
QUIT $$CNVDLM(.INREC,.INDEL)
+17 ;Inbound
+18 IF $GET(INB)="I"
QUIT $$DLMCNV(.INREC,.INDEL)
+19 QUIT INREC
CNVDLM(INREC,INDEL) ;;Convert delimeters to HL7 specifications if in record
+1 ; Input: INREC - Portion of HL7 MSG to check
+2 ; INDEL(opt) = FSRET values - each position is critical
+3 ; ie S INDEL="^\|~&"
+4 ; or
+5 ; array of delimiters
+6 ; S INDEL("F")="^"
+7 ; S INDEL("S")="\"
+8 ; S INDEL("R")="|"
+9 ; S INDEL("E")="~"
+10 ; S INDEL("T")="&"
+11 ; Returns - Record with replace values
+12 ;
+13 NEW INF,I,J,K,E,R,S,F,T,INREC1,IND
+14 SET (INREC1,E,R,S,F,T)=""
SET IND="FSRET"
+15 IF $LENGTH($GET(INDEL))
FOR I=1:1:5
SET @$EXTRACT(IND,I)=$EXTRACT(INDEL,I)
+16 IF '$TEST
IF $DATA(INDEL)>1
SET I=""
FOR
SET I=$ORDER(INDEL(I))
IF I=""
QUIT
SET @I=INDEL(I)
+17 IF E=""
SET E=$$ESC^INHUT()
IF R=""
SET R=$$REP^INHUT()
IF S=""
SET S=$$COMP^INHUT()
+18 IF F=""
SET F=$$FIELD^INHUT()
IF T=""
SET T=$$SUBCOMP^INHUT()
+19 ;
+20 ;Set array of HL7 delimters to replacement value
+21 SET J(R)=E_"R"_E
SET J(S)=E_"S"_E
SET J(E)=E_"E"_E
SET J(F)=E_"F"_E
SET J(T)=E_"T"_E
+22 ;
+23 ;loop through record looking for HL7 delimters
+24 FOR K=1:1:$LENGTH(INREC)
Begin DoDot:1
+25 ;if special character doesn't exist keep else replace
+26 IF '$DATA(J($EXTRACT(INREC,K)))
SET INREC1=INREC1_$EXTRACT(INREC,K)
+27 IF '$TEST
SET INREC1=INREC1_J($EXTRACT(INREC,K))
End DoDot:1
+28 QUIT INREC1
DLMCNV(INREC,INDEL) ;;HL7 specifications to correct delimitor if in record
+1 ; Input: INREC - Portion of HL7 MSG to check
+2 ; INDEL(opt) = FSRET values - each position is critical
+3 ; ie S INDEL="^\|~&"
+4 ; or
+5 ; array of delimiters
+6 ; S INDEL("F")="^"
+7 ; S INDEL("S")="\"
+8 ; S INDEL("R")="|"
+9 ; S INDEL("E")="~"
+10 ; S INDEL("T")="&"
+11 ; Returns - Record with replace values
+12 ;
+13 NEW INF,I,J,K,E,R,S,F,T,INREC1,IND
+14 SET (INREC1,E,R,S,F,T)=""
SET IND="FSRET"
+15 IF $LENGTH($GET(INDEL))
FOR I=1:1:5
SET @$EXTRACT(IND,I)=$EXTRACT(INDEL,I)
+16 IF '$TEST
IF $DATA(INDEL)>1
SET I=""
FOR
SET I=$ORDER(INDEL(I))
IF I=""
QUIT
SET @I=INDEL(I)
+17 IF E=""
SET E=$$ESC^INHUT()
IF R=""
SET R=$$REP^INHUT()
IF S=""
SET S=$$COMP^INHUT()
+18 IF F=""
SET F=$$FIELD^INHUT()
IF T=""
SET T=$$SUBCOMP^INHUT()
+19 ;
+20 ;Set array of HL7 delimters to replacement value
+21 SET J("R")=R
SET J("S")=S
SET J("E")=E
SET J("F")=F
SET J("T")=T
+22 ;
+23 ;loop through record looking for HL7 delimters
+24 FOR
SET K=$FIND(INREC,E)
IF 'K!($EXTRACT(INREC,K+1)="")
QUIT
IF $EXTRACT(INREC,K+1)=E
Begin DoDot:1
+25 SET INREC1=INREC1_$EXTRACT(INREC,1,K-2)
+26 IF $DATA(J($EXTRACT(INREC,K)))
SET INREC1=INREC1_J($EXTRACT(INREC,K))
+27 IF '$TEST
SET INREC1=INREC1_$EXTRACT(INREC,K-1,K+1)
+28 SET INREC=$EXTRACT(INREC,K+2,$LENGTH(INREC))
End DoDot:1
+29 SET INREC1=INREC1_INREC
+30 QUIT INREC1
APPACK(INUIF,INAKMES,INASTAT,INERMSG) ;User API to ACKLOG^INHU
+1 ;
+2 ; Inputs:
+3 ; INUIF = UIF ien of ack message in Universal Interface file
+4 ; INAKMES = Acked message ID - Typically: @INV@("MSA2")
+5 ; INASTAT = Ack message status - Typically: @INV@("MSA1"), converted
+6 ; to 0=NAK or 1=ACK. ex: S INASTAT=("AA"=INASTAT)
+7 ; INERMSG = Message to store if NAK. Typically: @INV@("MSA6")
+8 ;
+9 ; Usage:
+10 ; D APPACK^INHUT(UIF,@INV@("MSA2"),@INV@("MSA1"),@INV@("MSA6"))
+11 ;
+12 SET INAKMES=$GET(INAKMES)
SET INASTAT=$GET(INASTAT)
SET INERMSG=$GET(INERMSG)
+13 NEW INFERR,INFMSG
+14 SET (INFERR,INFMSG)=""
+15 ;
+16 IF INAKMES=""
SET INFMSG="No message identified to acknowledge"
SET INFERR=2
+17 ;save the worst error
IF 'INFERR
Begin DoDot:1
+18 IF '$DATA(^INTHU("C",INAKMES))
SET INFMSG="Acknowledge for unknown message ID - "_INAKMES
SET INFERR=2
QUIT
+19 IF INASTAT
SET INASTAT=1
QUIT
+20 IF $EXTRACT(INASTAT,2)="A"
SET INASTAT=1
QUIT
+21 IF INASTAT=""
SET INERMSG=$SELECT($LENGTH(INERMSG):$EXTRACT(INERMSG,1,475)_" ",1:"")_"No ACK status"
+22 SET INASTAT=0
End DoDot:1
+23 IF INFERR
DO ERROR^INHS(INFMSG,INFERR)
QUIT
+24 DO ACKLOG^INHU(INUIF,INAKMES,INASTAT,INERMSG)
+25 QUIT
+26 ;
SETENV ;Set environment for GIS with DUZ postmaster array
+1 SET U="^"
SET DUZ=.5
SET DUZ(0)="@"
SET IO=""
SET DTIME=1
+2 ;If Postmaster has no default division, find one and set it.
+3 ;IHS logic
+4 IF '$$SC^INHUTIL1
DO SETDT^UTDT
KILL Z
QUIT
+5 ;CHCS logic
+6 IF '$PIECE(^DIC(3,DUZ,0),U,16)
DO SETDIV
+7 DO SETDT^UTDT
+8 ; set up agency codes, no user prompts
DO DUZAG^XUS1
+9 ; set up division. No user prompts since default div is set
DO ^XUDIV
+10 KILL Z
+11 QUIT
+12 ;
SETDIV ;Called from SETENV if needed to stuff the postmaster default division.
+1 NEW INDEF,INDIV
+2 SET (INDEF,INDIV)=0
FOR
SET INDIV=$ORDER(^DG(40.8,INDIV))
IF 'INDIV!INDEF
QUIT
Begin DoDot:1
+3 ;Set as default if a) an inpatient facility and b) not inactive
+4 IF $GET(^DG(40.8,INDIV,8100))
IF '$GET(^DG(40.8,INDIV,28))
SET INDEF=INDIV
End DoDot:1
+5 ;If no divisions meet criteria, look for first non active division
+6 IF 'INDEF
SET INDEV=0
FOR
SET INDIV=$ORDER(^DG(40.8,INDIV))
IF 'INDIV!INDEF
QUIT
Begin DoDot:1
+7 IF '$GET(^DG(40.8,INDIV,28))
SET INDEF=INDIV
End DoDot:1
+8 ;If still no INDEFault, set default to first entry in 40.8
+9 IF 'INDEF
SET INDEF=$ORDER(^DG(40.8,0))
+10 SET DIE="^DIC(3,"
SET DA=.5
SET DR="28.2///`"_INDEF
DO ^DIE
+11 QUIT
+12 ;