- INHUSEN7 ;KN,DGH; 11 Nov 1999 16:52 ; X12 verification logic
- ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
- ;COPYRIGHT 1991-2000 SAIC
- ;CHCS TOOLS_460; GEN 5; 21-MAY-1997
- ;COPYRIGHT 1994 SAIC
- ;
- VERIF(INGBL,INTYP,INTA,ORIGID,INLINK,INSTAT,INERR) ;12/6/98
- ; Description:
- ; The function VERIF is used to verify and evaluate X12 headers
- ; such as ISA, GS or TA1 and X12 Trailers such as GE, IEA.
- ; It returns values such as message type, control numbers, etc.
- ;
- ; Parameters:
- ; Input:
- ; INGBL = May be a local or global array of X12 message lines
- ; If numeric, assumed to be IEN for ^INTHU
- ; If non-numeric, assumed to be variable array
- ; INTYP = (PRB) Variable to contain X12 Functional Identifier (msg type)
- ; INTA = (PBR) Variable array contains fields of interest
- ; ORIGID = (PBR) Message ID of incoming message
- ; INLINK = (PBR) ID of original message such as a query.
- ; This will be stored in CHCS as a sequence number because
- ; alpha characters are not allowed by X12.
- ; INSTAT = (PBR) Variable to contain status of original message.
- ; (INLINK & INSTAT are only populated for FA and TA1 message types)
- ; kim is including following in INTA, not sure if this is needed
- ; INTA = array of value for interchange ack (PBR)
- ; INTA("ORGICNUM") = Original Interchange Control Number
- ; INTA("ORGDATE") = Original Date
- ; INTA("ORGTIME") = Original Time
- ; INTA("ACKCODE") = Interchange Ack Code
- ; INTA("NOTECODE") = Interchange Note Code
- ; INORGID = Original message ID (PBR)
- ; the Transaction Set Control Number (ST02) is the original ID.
- ;
- ; Returns:
- ; 0 = Success
- ; 1 = Non-Fatal Error
- ; 2 = Fatal Error
- ;
- N LCT,INDOCNT,INISA,INGST,INGE,INIEA,INER,INGS2,LINE,MSG,INACK
- N INFROM,INSTCNT,INTEREST,LINE,SEGID
- ;Initialize
- S INVL=0 K INACK
- ;Get Interchnage Control Header ISA
- I +INGBL D GETLINE^INHOU(INGBL,.LCT,.LINE)
- I 'INGBL S LINE=$G(@INGBL@(1))
- I $E(LINE,1,3)'="ISA" W !,"Message from receiver "_$P(^INTHPC(INBPN,0),U)_" does not have the ISA segment in the correct location",MSG(2)=$E(LINE,1,250) D ERRADD^INHUSEN3(.INERR,.MSG) Q 2
- S INDELIM=$E(LINE,4),INSUBDEL=$E(LINE,105)
- ;Set ORIGID of the ISA. If incoming is TA1, this must be used.
- ;If not a TA1, ORIGID will be overwritten with id in the ST segment.
- S ORIGID=$P(LINE,INDELIM,13)
- ; Default value is good transmission
- ;Get next line, INGST=GS or TA1
- I +INGBL D GETLINE^INHOU(INGBL,.LCT,.LINE)
- I 'INGBL S LINE=$G(@INGBL@(2))
- ;Second segment must be either GS or TA1
- S SEGID=$P(LINE,INDELIM)
- I ",TA1,GS,"'[(","_SEGID_",") S MSG(1)="Second segment is not GS nor TA1",MSG(2)=$E(LINE,1,250) D ERRADD^INHUSEN3(.INERR,.MSG) Q 2
- ;--TA1 not planned for DEERS use, but needed for generic X12 processing.
- I SEGID="TA1" D Q INVL
- .S INTYP="TA1"
- .S INLINK=$P(LINE,INDELIM,2),INSTAT=$P(LINE,INDELIM,4)
- .I ",A,E,R,"'[(","_INSTAT_",") D ERRADD^INHUSEN3(.INERR,"Missing or invalid acknowledge code "_LINE) S INVL=2 Q
- .I INSTAT'="A" D ERRADD^INHUSEN3(.INERR,LINE)
- ;
- ;--Else next segment is a GS.
- S (INTYP,INTA("GS01"))=$P(LINE,INDELIM,2)
- S INTA("GS06")=$P(LINE,INDELIM,7)
- I '$L(INTYP) S MSG(1)="Message from receiver "_$P(^INTHPC(INBPN,0),U)_" does not have a type.",MSG(2)=$E(LINE,1,250),INVL=2 D ERRADD^INHUSEN3(.INERR,.MSG)
- Q:INVL INVL
- ;$Order through remainder lines to obtain needed control data.
- S INTEREST=",ISA,GS,ST,SE,GE,ISE,TA1,AK1,AK2,AK3,AK4,AK5,AK9,BHT,BGN,BGF,",INDOCNT=0
- I +INGBL D Q:'INVL
- .D GETLINE^INHOU(INGBL,.LCT,.LINE)
- .S SEGID=$P(LINE,INDELIM)
- .;count segments beteween ST and SE if "do count" flag is set.
- .I INDOCNT S INSTCNT=$G(INSTCNT)+1
- .D:INTEREST[SEGID INCNTL
- I 'INGBL S LCT=2 F S LCT=$O(@INGBL@(LCT)) Q:'LCT D
- .S LINE=$G(@INGBL@(LCT))
- .S SEGID=$P(LINE,INDELIM)
- .;Count segments between ST and SE. Note: Overflow nodes will be
- .;in @INGBL@(LCT,I), so LINE is an accurate counte of segments.
- .I INDOCNT S INSTCNT=$G(INSTCNT)+1
- .D:INTEREST[SEGID INCNTL
- ;
- ;---Miscellaneous error checking section--
- I $G(INTA("ST02"))'=$G(INTA("SE02")) S MSG(1)="ST02 "_$G(INTA("ST02"))_" does not match SE02 "_$G(INTA("SE02"))_" transaction set control numbers",INVL=2 D ERRADD^INHUSEN3(.INERR,.MSG) Q INVL
- ;---Set other needed variables. INLINK value differs by message type--
- S ORIGID=$G(INTA("ST02"))
- S:INTYP="HB" INLINK=$G(INTA("BHT03")) ;271
- S:INTYP="AG" INLINK=$G(INTA("BGN02")) ;824
- S:INTYP="BE" INLINK=$G(INTA("BGN02")) ;834
- S:INTYP="HI" INLINK=$G(INTA("BHT03")) ;278
- Q INVL
- ;
- INCNTL ;Get control segment field values for segments of interest
- ;This assumes that needed variables are within the first 240
- ;characters of LINE (e.g. there are no overflow nodes). If INGBL
- ;is a local array (most likely), any overflow of a segment would
- ;not reach this call because the calling logic is doing a $O of
- ;the first subscript and overflow beyond 240 chars are in subsequent.
- ;Input
- ; LINE=first line of segment if global; first 240 characters if local
- ; SEGID
- ;Return
- ; fields needed to process
- Q:SEGID=""
- I SEGID="ISA" S MSG(1)="Second ISA found in message",MSG(2)=LINE,INVL=2 D ERRADD^INHUSEN3(.INERR,.MSG) Q
- I SEGID="GS" S MSG(1)="Multiple GS loops not supported",MSG(2)=LINE,INVL=2 D ERRADD^INHUSEN3(.INERR,.MSG) Q
- I SEGID="IEA" S INTA("IEA1")=$P(LINE,INDELIM,2),INTA("IEA2")=$P(LINE,INDELIM,2) Q
- I SEGID="TA1" S ORIGID=$P(LINE,INDELIM,2),INTA("ACKCODE")=$P(LINE,INDELIM,3),INTA("NOTECODE")=$P(LINE,INDELIM,4) Q
- I SEGID="ST" D Q
- .;Turn "do count" on and initialize ST-SE segment counter to 1.
- .S (INSTCNT,INDOCNT)=1
- .I $D(INTA("ST01")) S MSG(1)="Multiple ST loops not supported",INVL=2 D ERRADD^INHUSEN3(.INERR,.MSG)
- .S INTA("ST01")=$P(LINE,INDELIM,2),INTA("ST02")=$P(LINE,INDELIM,3) Q
- I SEGID="SE" D Q
- .S INTA("SE01")=$P(LINE,INDELIM,2),INTA("SE02")=$P(LINE,INDELIM,3)
- .;Turn "do count" flag off and compare count in SE01 with INSTCNT
- .S INDOCNT=0
- .I INTA("SE01")'=INSTCNT S MSG(1)="Segment count "_INSTCNT_" does not match specified count "_INTA("SE01"),INVL=1 D ERRADD^INHUSEN3(.INERR,.MSG)
- I SEGID="GE" S INTA("GE01")=$P(LINE,INDELIM,2),INTA("GE02")=$P(LINE,INDELIM,3) Q
- I SEGID="BHT" S INTA("BHT03")=$P(LINE,INDELIM,4)
- I SEGID="BGN" S INTA("BGN01")=$P(LINE,INDELIM,2),INTA("BGN02")=$P(LINE,INDELIM,3) Q
- I SEGID="BGF" S INTA("BGF01")=$P(LINE,INDELIM,2),INTA("BGF02")=$P(LINE,INDELIM,3) Q
- ;Following should only exist if INTYP=FA (Functional Acknowledge).
- Q:INTYP'="FA"
- ;Logic will add each AKn segment to temp array. Only roll it into
- ;error log if status is in error. But we don't know that till the end.
- ;Don't set INSTAT flag until the last segment--AK9
- I SEGID="AK2" S INLINK=$P(LINE,INDELIM,3)
- I ",AK1,AK2,AK3,AK4,AK5,"[(","_SEGID_",") D ERRADD^INHUSEN3(.INACK,LINE) Q
- ;AK9-1 has value of X12's INSTAT, the equivalent of HL7's MSASTAT.
- I SEGID="AK9" D
- .S INSTAT=$P(LINE,INDELIM,2)
- .I ",A,E,R,"'[(","_INSTAT_",") D ERRADD^INHUSEN3(.INERR,"Missing or invalid acknowledge code "_LINE) S INVL=2 Q
- .I INSTAT'="A" D ERRADD^INHUSEN3(.INACK,LINE),ERRADD^INHUSEN3(.INERR,.INACK)
- Q
- ;
- ;
- INHUSEN7 ;KN,DGH; 11 Nov 1999 16:52 ; X12 verification logic
- +1 ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
- +2 ;COPYRIGHT 1991-2000 SAIC
- +3 ;CHCS TOOLS_460; GEN 5; 21-MAY-1997
- +4 ;COPYRIGHT 1994 SAIC
- +5 ;
- VERIF(INGBL,INTYP,INTA,ORIGID,INLINK,INSTAT,INERR) ;12/6/98
- +1 ; Description:
- +2 ; The function VERIF is used to verify and evaluate X12 headers
- +3 ; such as ISA, GS or TA1 and X12 Trailers such as GE, IEA.
- +4 ; It returns values such as message type, control numbers, etc.
- +5 ;
- +6 ; Parameters:
- +7 ; Input:
- +8 ; INGBL = May be a local or global array of X12 message lines
- +9 ; If numeric, assumed to be IEN for ^INTHU
- +10 ; If non-numeric, assumed to be variable array
- +11 ; INTYP = (PRB) Variable to contain X12 Functional Identifier (msg type)
- +12 ; INTA = (PBR) Variable array contains fields of interest
- +13 ; ORIGID = (PBR) Message ID of incoming message
- +14 ; INLINK = (PBR) ID of original message such as a query.
- +15 ; This will be stored in CHCS as a sequence number because
- +16 ; alpha characters are not allowed by X12.
- +17 ; INSTAT = (PBR) Variable to contain status of original message.
- +18 ; (INLINK & INSTAT are only populated for FA and TA1 message types)
- +19 ; kim is including following in INTA, not sure if this is needed
- +20 ; INTA = array of value for interchange ack (PBR)
- +21 ; INTA("ORGICNUM") = Original Interchange Control Number
- +22 ; INTA("ORGDATE") = Original Date
- +23 ; INTA("ORGTIME") = Original Time
- +24 ; INTA("ACKCODE") = Interchange Ack Code
- +25 ; INTA("NOTECODE") = Interchange Note Code
- +26 ; INORGID = Original message ID (PBR)
- +27 ; the Transaction Set Control Number (ST02) is the original ID.
- +28 ;
- +29 ; Returns:
- +30 ; 0 = Success
- +31 ; 1 = Non-Fatal Error
- +32 ; 2 = Fatal Error
- +33 ;
- +34 NEW LCT,INDOCNT,INISA,INGST,INGE,INIEA,INER,INGS2,LINE,MSG,INACK
- +35 NEW INFROM,INSTCNT,INTEREST,LINE,SEGID
- +36 ;Initialize
- +37 SET INVL=0
- KILL INACK
- +38 ;Get Interchnage Control Header ISA
- +39 IF +INGBL
- DO GETLINE^INHOU(INGBL,.LCT,.LINE)
- +40 IF 'INGBL
- SET LINE=$GET(@INGBL@(1))
- +41 IF $EXTRACT(LINE,1,3)'="ISA"
- WRITE !,"Message from receiver "_$PIECE(^INTHPC(INBPN,0),U)_" does not have the ISA segment in the correct location",MSG(2)=$EXTRACT(LINE,1,250)
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- QUIT 2
- +42 SET INDELIM=$EXTRACT(LINE,4)
- SET INSUBDEL=$EXTRACT(LINE,105)
- +43 ;Set ORIGID of the ISA. If incoming is TA1, this must be used.
- +44 ;If not a TA1, ORIGID will be overwritten with id in the ST segment.
- +45 SET ORIGID=$PIECE(LINE,INDELIM,13)
- +46 ; Default value is good transmission
- +47 ;Get next line, INGST=GS or TA1
- +48 IF +INGBL
- DO GETLINE^INHOU(INGBL,.LCT,.LINE)
- +49 IF 'INGBL
- SET LINE=$GET(@INGBL@(2))
- +50 ;Second segment must be either GS or TA1
- +51 SET SEGID=$PIECE(LINE,INDELIM)
- +52 IF ",TA1,GS,"'[(","_SEGID_",")
- SET MSG(1)="Second segment is not GS nor TA1"
- SET MSG(2)=$EXTRACT(LINE,1,250)
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- QUIT 2
- +53 ;--TA1 not planned for DEERS use, but needed for generic X12 processing.
- +54 IF SEGID="TA1"
- Begin DoDot:1
- +55 SET INTYP="TA1"
- +56 SET INLINK=$PIECE(LINE,INDELIM,2)
- SET INSTAT=$PIECE(LINE,INDELIM,4)
- +57 IF ",A,E,R,"'[(","_INSTAT_",")
- DO ERRADD^INHUSEN3(.INERR,"Missing or invalid acknowledge code "_LINE)
- SET INVL=2
- QUIT
- +58 IF INSTAT'="A"
- DO ERRADD^INHUSEN3(.INERR,LINE)
- End DoDot:1
- QUIT INVL
- +59 ;
- +60 ;--Else next segment is a GS.
- +61 SET (INTYP,INTA("GS01"))=$PIECE(LINE,INDELIM,2)
- +62 SET INTA("GS06")=$PIECE(LINE,INDELIM,7)
- +63 IF '$LENGTH(INTYP)
- SET MSG(1)="Message from receiver "_$PIECE(^INTHPC(INBPN,0),U)_" does not have a type."
- SET MSG(2)=$EXTRACT(LINE,1,250)
- SET INVL=2
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- +64 IF INVL
- QUIT INVL
- +65 ;$Order through remainder lines to obtain needed control data.
- +66 SET INTEREST=",ISA,GS,ST,SE,GE,ISE,TA1,AK1,AK2,AK3,AK4,AK5,AK9,BHT,BGN,BGF,"
- SET INDOCNT=0
- +67 IF +INGBL
- Begin DoDot:1
- +68 DO GETLINE^INHOU(INGBL,.LCT,.LINE)
- +69 SET SEGID=$PIECE(LINE,INDELIM)
- +70 ;count segments beteween ST and SE if "do count" flag is set.
- +71 IF INDOCNT
- SET INSTCNT=$GET(INSTCNT)+1
- +72 IF INTEREST[SEGID
- DO INCNTL
- End DoDot:1
- IF 'INVL
- QUIT
- +73 IF 'INGBL
- SET LCT=2
- FOR
- SET LCT=$ORDER(@INGBL@(LCT))
- IF 'LCT
- QUIT
- Begin DoDot:1
- +74 SET LINE=$GET(@INGBL@(LCT))
- +75 SET SEGID=$PIECE(LINE,INDELIM)
- +76 ;Count segments between ST and SE. Note: Overflow nodes will be
- +77 ;in @INGBL@(LCT,I), so LINE is an accurate counte of segments.
- +78 IF INDOCNT
- SET INSTCNT=$GET(INSTCNT)+1
- +79 IF INTEREST[SEGID
- DO INCNTL
- End DoDot:1
- +80 ;
- +81 ;---Miscellaneous error checking section--
- +82 IF $GET(INTA("ST02"))'=$GET(INTA("SE02"))
- SET MSG(1)="ST02 "_$GET(INTA("ST02"))_" does not match SE02 "_$GET(INTA("SE02"))_" transaction set control numbers"
- SET INVL=2
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- QUIT INVL
- +83 ;---Set other needed variables. INLINK value differs by message type--
- +84 SET ORIGID=$GET(INTA("ST02"))
- +85 ;271
- IF INTYP="HB"
- SET INLINK=$GET(INTA("BHT03"))
- +86 ;824
- IF INTYP="AG"
- SET INLINK=$GET(INTA("BGN02"))
- +87 ;834
- IF INTYP="BE"
- SET INLINK=$GET(INTA("BGN02"))
- +88 ;278
- IF INTYP="HI"
- SET INLINK=$GET(INTA("BHT03"))
- +89 QUIT INVL
- +90 ;
- INCNTL ;Get control segment field values for segments of interest
- +1 ;This assumes that needed variables are within the first 240
- +2 ;characters of LINE (e.g. there are no overflow nodes). If INGBL
- +3 ;is a local array (most likely), any overflow of a segment would
- +4 ;not reach this call because the calling logic is doing a $O of
- +5 ;the first subscript and overflow beyond 240 chars are in subsequent.
- +6 ;Input
- +7 ; LINE=first line of segment if global; first 240 characters if local
- +8 ; SEGID
- +9 ;Return
- +10 ; fields needed to process
- +11 IF SEGID=""
- QUIT
- +12 IF SEGID="ISA"
- SET MSG(1)="Second ISA found in message"
- SET MSG(2)=LINE
- SET INVL=2
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- QUIT
- +13 IF SEGID="GS"
- SET MSG(1)="Multiple GS loops not supported"
- SET MSG(2)=LINE
- SET INVL=2
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- QUIT
- +14 IF SEGID="IEA"
- SET INTA("IEA1")=$PIECE(LINE,INDELIM,2)
- SET INTA("IEA2")=$PIECE(LINE,INDELIM,2)
- QUIT
- +15 IF SEGID="TA1"
- SET ORIGID=$PIECE(LINE,INDELIM,2)
- SET INTA("ACKCODE")=$PIECE(LINE,INDELIM,3)
- SET INTA("NOTECODE")=$PIECE(LINE,INDELIM,4)
- QUIT
- +16 IF SEGID="ST"
- Begin DoDot:1
- +17 ;Turn "do count" on and initialize ST-SE segment counter to 1.
- +18 SET (INSTCNT,INDOCNT)=1
- +19 IF $DATA(INTA("ST01"))
- SET MSG(1)="Multiple ST loops not supported"
- SET INVL=2
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- +20 SET INTA("ST01")=$PIECE(LINE,INDELIM,2)
- SET INTA("ST02")=$PIECE(LINE,INDELIM,3)
- QUIT
- End DoDot:1
- QUIT
- +21 IF SEGID="SE"
- Begin DoDot:1
- +22 SET INTA("SE01")=$PIECE(LINE,INDELIM,2)
- SET INTA("SE02")=$PIECE(LINE,INDELIM,3)
- +23 ;Turn "do count" flag off and compare count in SE01 with INSTCNT
- +24 SET INDOCNT=0
- +25 IF INTA("SE01")'=INSTCNT
- SET MSG(1)="Segment count "_INSTCNT_" does not match specified count "_INTA("SE01")
- SET INVL=1
- DO ERRADD^INHUSEN3(.INERR,.MSG)
- End DoDot:1
- QUIT
- +26 IF SEGID="GE"
- SET INTA("GE01")=$PIECE(LINE,INDELIM,2)
- SET INTA("GE02")=$PIECE(LINE,INDELIM,3)
- QUIT
- +27 IF SEGID="BHT"
- SET INTA("BHT03")=$PIECE(LINE,INDELIM,4)
- +28 IF SEGID="BGN"
- SET INTA("BGN01")=$PIECE(LINE,INDELIM,2)
- SET INTA("BGN02")=$PIECE(LINE,INDELIM,3)
- QUIT
- +29 IF SEGID="BGF"
- SET INTA("BGF01")=$PIECE(LINE,INDELIM,2)
- SET INTA("BGF02")=$PIECE(LINE,INDELIM,3)
- QUIT
- +30 ;Following should only exist if INTYP=FA (Functional Acknowledge).
- +31 IF INTYP'="FA"
- QUIT
- +32 ;Logic will add each AKn segment to temp array. Only roll it into
- +33 ;error log if status is in error. But we don't know that till the end.
- +34 ;Don't set INSTAT flag until the last segment--AK9
- +35 IF SEGID="AK2"
- SET INLINK=$PIECE(LINE,INDELIM,3)
- +36 IF ",AK1,AK2,AK3,AK4,AK5,"[(","_SEGID_",")
- DO ERRADD^INHUSEN3(.INACK,LINE)
- QUIT
- +37 ;AK9-1 has value of X12's INSTAT, the equivalent of HL7's MSASTAT.
- +38 IF SEGID="AK9"
- Begin DoDot:1
- +39 SET INSTAT=$PIECE(LINE,INDELIM,2)
- +40 IF ",A,E,R,"'[(","_INSTAT_",")
- DO ERRADD^INHUSEN3(.INERR,"Missing or invalid acknowledge code "_LINE)
- SET INVL=2
- QUIT
- +41 IF INSTAT'="A"
- DO ERRADD^INHUSEN3(.INACK,LINE)
- DO ERRADD^INHUSEN3(.INERR,.INACK)
- End DoDot:1
- +42 QUIT
- +43 ;
- +44 ;