IBCNEHLU ;DAOU/ALA - HL7 Utilities ;10-JUN-2002 ; Compiled December 16, 2004 15:36:12
;;2.0;INTEGRATED BILLING;**184,300,416,438,497,549,702,752,771**;21-MAR-94;Build 26
;;Per VA Directive 6402, this routine should not be modified.
;
HLP(PROTOCOL) ; Find the Protocol IEN
Q +$O(^ORD(101,"B",PROTOCOL,0))
;
NAME(NM) ; Convert a name that isn't in standard VISTA format -
NEW LNM,FNM,MI
;
I NM?." " Q NM
; LastName,FirstName MI
I NM["," Q NM
;
; Remove double-spaces from name
F Q:$L(NM," ")<2 S NM=$P(NM," ",1)_" "_$P(NM," ",2,9999)
;
; Trim leading/trailing spaces
S NM=$$TRIM^XLFSTR(NM)
;
; Find number of spaces in name
S II=$L(NM," ")
;
I II>3 Q NM
I II=3 S FNM=$P(NM," ",1),MI=" "_$P(NM," ",2),LNM=$P(NM," ",3)
I II=2 S FNM=$P(NM," ",1),LNM=$P(NM," ",2),MI=""
I II<2 Q NM
Q LNM_","_FNM_MI
;
DODCK(DFN,DOD,MGRP,NAME,RIEN,SSN) ; Date of death check
;
; Input Variables
; DFN, DOD, MGRP, NAME, RIEN, SSN
;
N CDOD,CIDDSP,IDDSP,IDSSN,MSG,XMSUB
S CDOD=$P($G(^DPT(DFN,.35)),U,1),CIDDSP=$$FMTE^XLFDT(CDOD,"5Z")
S IDDSP=$$FMTE^XLFDT(DOD,"5Z")
S IDSSN=$E(SSN,$L(SSN)-3,$L(SSN))
;
; If the two dates of death are the same, quit
I CDOD=DOD G DODCKX
;
; If no current date of death but payer sent one
I CDOD="" D G DODCKX
. ; Send an email message
. S XMSUB="Date of Death Received"
. S MSG(1)="A Date of Death ("_IDDSP_") was received for patient: "_NAME_"/"_IDSSN_" "_$$GETDOB^IBCNEDEQ(DFN)_" from"
. S MSG(2)="payer "_$$GET1^DIQ(365,RIEN,.03,"E")_". There is no current Date of Death on file for "
. S MSG(3)="this patient."
. D TXT^IBCNEUT7("MSG")
. D MSG^IBCNEUT5(MGRP,XMSUB,"MSG(")
;
S XMSUB="Variant Date of Death"
S MSG(1)="A Date of Death ("_IDDSP_") was received for patient: "_NAME_"/"_IDSSN_" "_$$GETDOB^IBCNEDEQ(DFN)_" from payer "_$$GET1^DIQ(365,RIEN,.03,"E")_"."
S MSG(2)="This Date of Death does not currently match the Date of Death ("_CIDDSP_") on file for this patient. "
D TXT^IBCNEUT7("MSG")
D MSG^IBCNEUT5(MGRP,XMSUB,"MSG(")
DODCKX ;
Q
;
SPAR ; Segment Parsing
;
; This tag will parse the current segment referenced by the HCT index
; and place the results in the IBSEG array.
;
; Input Variables
; HCT
;
; Output Variables
; IBSEG (ARRAY of fields in segment)
;
N II,IJ,IK,IM,IS,ISBEG,ISCT,ISDATA,ISEND,ISPEC,LSDATA,NPC
;
;Reset IBSEG
K IBSEG
;
S ISCT="",II=0,IS=0
F S ISCT=$O(^TMP($J,"IBCNEHLI",HCT,ISCT)) Q:ISCT="" D
. S IS=IS+1
. S ISDATA(IS)=$G(^TMP($J,"IBCNEHLI",HCT,ISCT))
. I $O(^TMP($J,"IBCNEHLI",HCT,ISCT))="" S ISDATA(IS)=ISDATA(IS)_HLFS
. S ISPEC(IS)=$L(ISDATA(IS),HLFS)
;
S IM=0,LSDATA=""
LP S IM=IM+1 Q:IM>IS
S LSDATA=LSDATA_ISDATA(IM),NPC=ISPEC(IM)
F IJ=1:1:NPC-1 D
. S II=II+1,IBSEG(II)=$$CLNSTR($P(LSDATA,HLFS,IJ),$E(HL("ECH"),1,2)_$E(HL("ECH"),4),$E(HL("ECH")))
S LSDATA=$P(LSDATA,HLFS,NPC)
G LP
CLNSTR(STRING,CHARS,SUBSEP) ; Remove extra trailing components and subcomponents in the HL7 seg
;
N NUMPEC,PEC,RTSTRING
;
S RTSTRING=$$RTRIMCH(STRING,CHARS)
; Now we have string w/o trailing chars, remove from subs
S NUMPEC=$L(RTSTRING,SUBSEP)
F PEC=1:1:NUMPEC S $P(RTSTRING,SUBSEP,PEC)=$$RTRIMCH($P(RTSTRING,SUBSEP,PEC),CHARS)
Q RTSTRING
;
RTRIMCH(STR,CHRS) ; Remove the trailing chars from string
;
N R,L
;
S L=1,CHRS=$G(CHRS," ")
F R=$L(STR):-1:1 Q:CHRS'[$E(STR,R)
I L=R,(CHRS[$E(STR)) S STR=""
Q $E(STR,L,R)
;
;
GTICNM(ICN,NAME) ; Retrieve PID segment and set ICN and patient name
;
N HCT,ERFLG,SEG,IBSEG
S (HCT,ICN,NAME)="",ERFLG=0
F S HCT=$O(^TMP($J,"IBCNEHLI",HCT)) Q:HCT="" D Q:ERFLG
. D SPAR
. S SEG=$G(IBSEG(1)) Q:SEG'="PID"
. S ICN=$G(IBSEG(4)),NAME=$G(IBSEG(6)),ERFLG=1
Q
;
PATISSUB(IDATA0) ; check if patient is the subscriber
; IDATA0 - 0 node of file 2.312
;
; returns 1 if patient is the subscriber, 0 otherwise
;
N PREL,RES
S RES=0
; check field 2.312/16 first
S PREL=$P(IDATA0,U,16) I PREL'="" S:PREL="01" RES=1 Q RES
; if 2.312/16 is empty, try field 2.312/6
I $P(IDATA0,U,6)="v" S RES=1
Q RES
;
ONEPOL(PIEN,IEN2) ; check if patient has only one policy on file for a given payer
; PIEN - payer ien
; IEN2 - patient ien (file 2)
;
; returns 1 if only one policy is found, 0 otherwise
N CNT,DAYS,EXPDT,IEN36,IEN312,RES
S (CNT,RES)=0
I +$G(PIEN)'>0!(+$G(IEN2)'>0) Q RES
;IB*702/TAZ - Get EIV NO GRP NUM A/U
S DAYS=$$GET1^DIQ(350.9,"1,",51.34,"I")
S IEN36="" F S IEN36=$O(^DIC(36,"AC",PIEN,IEN36)) Q:IEN36="" D
. S IEN312="" F S IEN312=$O(^DPT(IEN2,.312,"B",IEN36,IEN312)) Q:IEN312="" D
.. ;IB*702/TAZ - Compare EIV NO GRP NUM A/U with current date
.. S EXPDT=$$GET1^DIQ(2.312,IEN312_","_IEN2_",",3,"I")
.. I +EXPDT,$$FMDIFF^XLFDT(DT,EXPDT)>DAYS Q ;don't count for auto-update purposes
.. S CNT=CNT+1
I CNT=1 S RES=1
Q RES
;
MCRDT(RIEN,EBIEN) ; find effective date for Medicare response
; RIEN - file 365 ien
; EBIEN - subfile 365.02 ien
;
; returns date in FM format or "" if effective date was not found
;
N DONE,DTIEN,IENS,RES,Z
S RES="",DONE=0
S Z="" F S Z=$O(^IBCN(365,RIEN,2,EBIEN,8,"B",Z)) Q:Z=""!DONE D
.S DTIEN=$O(^IBCN(365,RIEN,2,EBIEN,8,"B",Z,"")) I 'DTIEN Q
.S IENS=DTIEN_","_EBIEN_","_RIEN_","
.; effective date has "eligibility" qualifier
.I $$GET1^DIQ(365.28,IENS,.03)=307 S RES=$$FMDATE^HLFNC($$GET1^DIQ(365.28,IENS,.02)),DONE=1
.Q
Q RES
;
ISMCR(RIEN) ; Check if response is for Medicare part A/B
; Input: RIEN - Internal ien for file 365
; Returns A1^A2^A3^A4^A5 Where:
; A1 - 1 if response if for Medicare, 0 otherwise
; A2 - "MA" if response is for Medicare Part A
; "MB" if response is for Medicare Part B
; "B" if response is for both Part A and Part B
; "" if response if not for Medicare
; A3 - Effective date for Medicare Part A if response if for
; Part A or both parts, "" otherwise
; A4 - Effective date for Medicare Part B if response if for
; Part B or both parts, "" otherwise
; A5 - "MA" - Response is for active Medicare Part A only
; "MB" - Response is for active Medicare Part B only
; "B" - Response is for active Medicare Parts A and B
; "" - Response is not for active Medicare
; IB*2.0*549 - added return of A5
;
N ACTIVE,DONE,EBIEN,RES,TYPE,TYPEA,TYPEB,Z,ZZ ;IB*2.0*549 added ACTIVE,TYPEA,TYPEB,ZZ
S RES="0^",DONE=0,(TYPEA,TYPEB)=0 ;IB*2.0*549 added ,(TYPEA,TYPEB)=0
I +RIEN'>0 Q RES
I '$D(^IBCN(365,RIEN)) Q RES
S Z="" F S Z=$O(^IBCN(365,RIEN,2,"B",Z)) Q:Z=""!DONE D
. S EBIEN=$O(^IBCN(365,RIEN,2,"B",Z,""))
. S TYPE=$$GET1^DIQ(365.02,EBIEN_","_RIEN_",",.05)
. ;
. ; IB*2.0*549 added next two lines
. S ACTIVE=$$GET1^DIQ(365.02,EBIEN_","_RIEN_",",.02,"I")
. S ACTIVE=$S(ACTIVE=1:1,1:0)
. I TYPE="MA" D
. . S:ACTIVE TYPEA=1 ;IB*2.0*549 added line
. . S ZZ=$P(RES,U,2) ;IB*2.0*549 added line
. . S $P(RES,U)=1,$P(RES,U,2)=$S(ZZ="":"MA",ZZ="MA":"MA",1:"B")
. . S $P(RES,U,3)=$$MCRDT(RIEN,EBIEN)
. . ;
. . ; IB*2.0*549 added line
. . S:ACTIVE $P(RES,U,5)=$S((TYPEA&TYPEB):"B",1:"MA")
. I TYPE="MB" D
. . S:ACTIVE TYPEB=1 ;IB*2.0*549 added line
. . S ZZ=$P(RES,U,2) ;IB*2.0*549 added line
. . S $P(RES,U)=1,$P(RES,U,2)=$S(ZZ="":"MB",ZZ="MB":"MB",1:"B")
. . S $P(RES,U,4)=$$MCRDT(RIEN,EBIEN)
. . ;
. . ; IB*2.0*549 added line
. . S:ACTIVE $P(RES,U,5)=$S((TYPEA&TYPEB):"B",1:"MB")
. I $P(RES,U,2)="B" S DONE=1
Q RES
;
ERRACT(RIEN) ; Pick error action code to use for re-transmission
; Input: RIEN - IEN in file 365 (Transmission file)
; Returns: Error action^Error condition; "" if no error found
;
; If any of C,N,S,Y action codes are found, the first one encountered is returned.
; Otherwise, if W action code is found, it is returned.
; Otherwise, if X action code is found, it is returned.
; Otherwise, one of the P,R action codes is returned.
;
N ACODE,AIEN,ECCODE,ECIEN,DONE,IEN,RES,Z
S RES=""
I '+$G(RIEN) G ERRACTX
S DONE=0
S Z="" F S IEN=$O(^IBCN(365,RIEN,6,"B",Z)) Q:Z=""!DONE D
. S IEN=+$O(^IBCN(365,RIEN,6,"B",Z,""))
. Q:'IEN
. S ECIEN=+$P(^IBCN(365,RIEN,6,IEN,0),U,3)
. Q:'ECIEN
. S AIEN=+$P(^IBCN(365,RIEN,6,IEN,0),U,4)
. Q:'AIEN
. S ACODE=$P(^IBE(365.018,AIEN,0),U),ECCODE=$P(^IBE(365.017,ECIEN,0),U)
. ;
. ; One of "do not retransmit" codes
. I ".C.N.S.Y"[("."_ACODE_".") S RES=ACODE_U_ECCODE,DONE=1 Q
. ;
. ; Retransmit after 30 days code
. I ACODE="W" S RES=ACODE_U_ECCODE Q
. ;
. ; Retransmit after 10 days code
. I ACODE="X" S:RES'="W" RES=ACODE_U_ECCODE Q
. ;
. ; Retransmit whenever codes
. I RES'="W",RES'="X" S RES=ACODE_U_ECCODE
ERRACTX ;
Q RES
;
NAMECMP(NAME1,NAME2) ; check if 2 names have the same first name and last name components
; NAME1, NAME2 - names to compare, should be in "last,first [middle]" format
;
; returns 1 if both first name and last name are the same between two names, returns 0 otherwise
N NM1,NM2,RES
S RES=0
S NM1=$$HLNAME^HLFNC(NAME1),NM2=$$HLNAME^HLFNC(NAME2)
I $P(NM1,U)=$P(NM2,U),$P(NM1,U,2)=$P(NM2,U,2) S RES=1
Q RES
;
TRNCWARN(GNUM,TRACE) ; send group number truncation warning message
N MSG
S MSG(1)="WARNING: Group number in the Response Message from the EC has been truncated"
S MSG(2)="----------------------------------------------------------------------------"
S MSG(3)="Original group number (in the eIV response received): "_$G(GNUM)
S MSG(4)="Truncated group number (filed into response file): "_$E($G(GNUM),1,17)
S MSG(5)=" "
S MSG(6)="The associated Trace # is "_$S($G(TRACE)="":"Unknown",1:TRACE)
S MSG(7)=" "
D MSG^IBCNEUT5($G(MGRP),MSG(1),"MSG(")
Q
;
CODECHK(RSUPDT) ; IB*2*497
; need to determine if codes and qualifiers sent in the 271 HL7 message
; are new. If code/qualifier does not exist in table then file new code into table
; input -
; RSUPDT = FDA array that will be passed to the DBS filer to update the
; entry/subentry into the IIV RESPONSE file
; example: RSUPDT(365.02,IENS,".02") = data to be filed into 365.02 subfile at field .02
; order through the RSUPDT array and determine if pointer to file
; if pointer to file then pass file name and value of code/qualifier
;
; IB*752 Fix existing bug - only allow certain files to be updated. See array XXFILE.
;
N IBXMY,IENS,FLD,FILE,FSCMSG,RES,SITE,SITENUM,TOFILE,NEWARRY,XX,XXFILE,Z,ZIENS
S (IENS,FILE,FLD)="",Z=0
F XX=11:1:18,21 S XXFILE("365.0"_XX)="" ;IB*771/DW Add original set of tables
F XX=22:1:29,31:1:39,41:1:46 S XXFILE("365.0"_XX)=""
F S FILE=$O(RSUPDT(FILE)) Q:FILE="" F S IENS=$O(RSUPDT(FILE,IENS)) Q:IENS="" D
. F S FLD=$O(RSUPDT(FILE,IENS,FLD)) Q:FLD="" D
. . Q:RSUPDT(FILE,IENS,FLD)="" ; value was not sent by payer; no need to continue
. . D FIELD^DID(FILE,FLD,"","POINTER","RES") ; get the name of the file that is pointed to (if any)
. . Q:RES("POINTER")="" ; field is not defined as a pointer to a file
. . S TOFILE=$P($P(RES("POINTER"),","),"(",2) ; example: RES("POINTER")="IBE(365.011,"
. . Q:+TOFILE=0
. . I '$D(XXFILE(TOFILE)) Q ;IB*752
. . Q:$$FIND1^DIC(TOFILE,"","X",RSUPDT(FILE,IENS,FLD)) ; code is already in file. No need to update the pointed-to-file
. . S Z=Z+1,ZIENS="+"_Z_","
. . S NEWARRY(TOFILE,ZIENS,.01)=RSUPDT(FILE,IENS,FLD) ; code passed into VistA from 271 message
. . S NEWARRY(TOFILE,ZIENS,.02)="OTHER" ; Description of code
. . S NEWARRY(TOFILE,ZIENS,.03)=0 ; INACTIVE FLAG
. . S NEWARRY(TOFILE,ZIENS,.05)=0 ; FSC CONTROLLED ;IB*752 indicate not controlled
. . ;IB*752/CKB - notify FSC that a new code was learned on the fly
. . S SITE=$$SITE^VASITE,SITENUM=$P(SITE,U,3)
. . S FSCMSG=TOFILE_U_SITENUM_U_RSUPDT(FILE,IENS,FLD)_U_$$GET1^DIQ(365,$G(RIEN)_",",.09)
. . D MSG005^IBCNEMS1(FSCMSG)
. . ;IB*771/DW Corrected call to send to FSC outlook address (was sent in wrong parameter)
. . ;D MSG^IBCNEUT5("FSCECADMIN@domain.ext","X12 271 VistA tables, site #"_SITENUM_" new code added","MSG(")
. . S IBXMY="" I $$PROD^XUPROD(1) S IBXMY("FSCECADMIN@domain.ext")=""
. . D MSG^IBCNEUT5(,"X12 271 VistA tables, site #"_SITENUM_" new code added","MSG(",,.IBXMY)
I $D(NEWARRY) D UPDATE^DIE("","NEWARRY")
Q
;
PREL(FILE,FIELD,CODE) ; IB*2*497 code from x12 271 message may need to be converted to 'other' if there is no match. Refer to tag SETLST
;
; INPUT - FILE = file # of the file that will be evaluated
; FIELD = field # that is defined with the SET OF CODE values
; CODE = patient relationship code sent by the X12 271 message
; OUTPUT - = converted or non-converted coded value
N STRING,CODESTR,ARRAY,VAL,I,DEF
S CODE=$G(CODE)
I CODE="" Q CODE ; quit when code was not sent from payer
D FIELD^DID(FILE,FIELD,"","TYPE","DEF")
I DEF("TYPE")="SET" D
. S CODESTR=$P($G(^DD(FILE,FIELD,0)),U,3)
. F I=1:1 S VAL=$P($P(CODESTR,";",I),":") Q:VAL="" S ARRAY(VAL)=$P($P(CODESTR,";",I),":",2)
Q $S($D(ARRAY(CODE)):CODE,1:"G8") ; if coded value does not exist in the array of codes then this is a new code sent by X12 271 message and will default to OTHER
;
SETLST ; SET OF CODES defined to 355.33,60.14 and 2.312,4.03; this tag is not referenced in any procedure. It's here for documentation purposes.
;;01^SPOUSE
;;18^SELF
;;19^CHILD
;;20^EMPLOYEE
;;29^SIGNIFICANT OTHER
;;32^MOTHER
;;33^FATHER
;;39^ORGAN DONOR
;;41^INJURED PLAINTIFF
;;53^LIFE PARTNER
;;G8^OTHER RELATIONSHIP
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HIBCNEHLU 13947 printed Oct 16, 2024@18:15:28 Page 2
IBCNEHLU ;DAOU/ALA - HL7 Utilities ;10-JUN-2002 ; Compiled December 16, 2004 15:36:12
+1 ;;2.0;INTEGRATED BILLING;**184,300,416,438,497,549,702,752,771**;21-MAR-94;Build 26
+2 ;;Per VA Directive 6402, this routine should not be modified.
+3 ;
HLP(PROTOCOL) ; Find the Protocol IEN
+1 QUIT +$ORDER(^ORD(101,"B",PROTOCOL,0))
+2 ;
NAME(NM) ; Convert a name that isn't in standard VISTA format -
+1 NEW LNM,FNM,MI
+2 ;
+3 IF NM?." "
QUIT NM
+4 ; LastName,FirstName MI
+5 IF NM[","
QUIT NM
+6 ;
+7 ; Remove double-spaces from name
+8 FOR
if $LENGTH(NM," ")<2
QUIT
SET NM=$PIECE(NM," ",1)_" "_$PIECE(NM," ",2,9999)
+9 ;
+10 ; Trim leading/trailing spaces
+11 SET NM=$$TRIM^XLFSTR(NM)
+12 ;
+13 ; Find number of spaces in name
+14 SET II=$LENGTH(NM," ")
+15 ;
+16 IF II>3
QUIT NM
+17 IF II=3
SET FNM=$PIECE(NM," ",1)
SET MI=" "_$PIECE(NM," ",2)
SET LNM=$PIECE(NM," ",3)
+18 IF II=2
SET FNM=$PIECE(NM," ",1)
SET LNM=$PIECE(NM," ",2)
SET MI=""
+19 IF II<2
QUIT NM
+20 QUIT LNM_","_FNM_MI
+21 ;
DODCK(DFN,DOD,MGRP,NAME,RIEN,SSN) ; Date of death check
+1 ;
+2 ; Input Variables
+3 ; DFN, DOD, MGRP, NAME, RIEN, SSN
+4 ;
+5 NEW CDOD,CIDDSP,IDDSP,IDSSN,MSG,XMSUB
+6 SET CDOD=$PIECE($GET(^DPT(DFN,.35)),U,1)
SET CIDDSP=$$FMTE^XLFDT(CDOD,"5Z")
+7 SET IDDSP=$$FMTE^XLFDT(DOD,"5Z")
+8 SET IDSSN=$EXTRACT(SSN,$LENGTH(SSN)-3,$LENGTH(SSN))
+9 ;
+10 ; If the two dates of death are the same, quit
+11 IF CDOD=DOD
GOTO DODCKX
+12 ;
+13 ; If no current date of death but payer sent one
+14 IF CDOD=""
Begin DoDot:1
+15 ; Send an email message
+16 SET XMSUB="Date of Death Received"
+17 SET MSG(1)="A Date of Death ("_IDDSP_") was received for patient: "_NAME_"/"_IDSSN_" "_$$GETDOB^IBCNEDEQ(DFN)_" from"
+18 SET MSG(2)="payer "_$$GET1^DIQ(365,RIEN,.03,"E")_". There is no current Date of Death on file for "
+19 SET MSG(3)="this patient."
+20 DO TXT^IBCNEUT7("MSG")
+21 DO MSG^IBCNEUT5(MGRP,XMSUB,"MSG(")
End DoDot:1
GOTO DODCKX
+22 ;
+23 SET XMSUB="Variant Date of Death"
+24 SET MSG(1)="A Date of Death ("_IDDSP_") was received for patient: "_NAME_"/"_IDSSN_" "_$$GETDOB^IBCNEDEQ(DFN)_" from payer "_$$GET1^DIQ(365,RIEN,.03,"E")_"."
+25 SET MSG(2)="This Date of Death does not currently match the Date of Death ("_CIDDSP_") on file for this patient. "
+26 DO TXT^IBCNEUT7("MSG")
+27 DO MSG^IBCNEUT5(MGRP,XMSUB,"MSG(")
DODCKX ;
+1 QUIT
+2 ;
SPAR ; Segment Parsing
+1 ;
+2 ; This tag will parse the current segment referenced by the HCT index
+3 ; and place the results in the IBSEG array.
+4 ;
+5 ; Input Variables
+6 ; HCT
+7 ;
+8 ; Output Variables
+9 ; IBSEG (ARRAY of fields in segment)
+10 ;
+11 NEW II,IJ,IK,IM,IS,ISBEG,ISCT,ISDATA,ISEND,ISPEC,LSDATA,NPC
+12 ;
+13 ;Reset IBSEG
+14 KILL IBSEG
+15 ;
+16 SET ISCT=""
SET II=0
SET IS=0
+17 FOR
SET ISCT=$ORDER(^TMP($JOB,"IBCNEHLI",HCT,ISCT))
if ISCT=""
QUIT
Begin DoDot:1
+18 SET IS=IS+1
+19 SET ISDATA(IS)=$GET(^TMP($JOB,"IBCNEHLI",HCT,ISCT))
+20 IF $ORDER(^TMP($JOB,"IBCNEHLI",HCT,ISCT))=""
SET ISDATA(IS)=ISDATA(IS)_HLFS
+21 SET ISPEC(IS)=$LENGTH(ISDATA(IS),HLFS)
End DoDot:1
+22 ;
+23 SET IM=0
SET LSDATA=""
LP SET IM=IM+1
if IM>IS
QUIT
+1 SET LSDATA=LSDATA_ISDATA(IM)
SET NPC=ISPEC(IM)
+2 FOR IJ=1:1:NPC-1
Begin DoDot:1
+3 SET II=II+1
SET IBSEG(II)=$$CLNSTR($PIECE(LSDATA,HLFS,IJ),$EXTRACT(HL("ECH"),1,2)_$EXTRACT(HL("ECH"),4),$EXTRACT(HL("ECH")))
End DoDot:1
+4 SET LSDATA=$PIECE(LSDATA,HLFS,NPC)
+5 GOTO LP
CLNSTR(STRING,CHARS,SUBSEP) ; Remove extra trailing components and subcomponents in the HL7 seg
+1 ;
+2 NEW NUMPEC,PEC,RTSTRING
+3 ;
+4 SET RTSTRING=$$RTRIMCH(STRING,CHARS)
+5 ; Now we have string w/o trailing chars, remove from subs
+6 SET NUMPEC=$LENGTH(RTSTRING,SUBSEP)
+7 FOR PEC=1:1:NUMPEC
SET $PIECE(RTSTRING,SUBSEP,PEC)=$$RTRIMCH($PIECE(RTSTRING,SUBSEP,PEC),CHARS)
+8 QUIT RTSTRING
+9 ;
RTRIMCH(STR,CHRS) ; Remove the trailing chars from string
+1 ;
+2 NEW R,L
+3 ;
+4 SET L=1
SET CHRS=$GET(CHRS," ")
+5 FOR R=$LENGTH(STR):-1:1
if CHRS'[$EXTRACT(STR,R)
QUIT
+6 IF L=R
IF (CHRS[$EXTRACT(STR))
SET STR=""
+7 QUIT $EXTRACT(STR,L,R)
+8 ;
+9 ;
GTICNM(ICN,NAME) ; Retrieve PID segment and set ICN and patient name
+1 ;
+2 NEW HCT,ERFLG,SEG,IBSEG
+3 SET (HCT,ICN,NAME)=""
SET ERFLG=0
+4 FOR
SET HCT=$ORDER(^TMP($JOB,"IBCNEHLI",HCT))
if HCT=""
QUIT
Begin DoDot:1
+5 DO SPAR
+6 SET SEG=$GET(IBSEG(1))
if SEG'="PID"
QUIT
+7 SET ICN=$GET(IBSEG(4))
SET NAME=$GET(IBSEG(6))
SET ERFLG=1
End DoDot:1
if ERFLG
QUIT
+8 QUIT
+9 ;
PATISSUB(IDATA0) ; check if patient is the subscriber
+1 ; IDATA0 - 0 node of file 2.312
+2 ;
+3 ; returns 1 if patient is the subscriber, 0 otherwise
+4 ;
+5 NEW PREL,RES
+6 SET RES=0
+7 ; check field 2.312/16 first
+8 SET PREL=$PIECE(IDATA0,U,16)
IF PREL'=""
if PREL="01"
SET RES=1
QUIT RES
+9 ; if 2.312/16 is empty, try field 2.312/6
+10 IF $PIECE(IDATA0,U,6)="v"
SET RES=1
+11 QUIT RES
+12 ;
ONEPOL(PIEN,IEN2) ; check if patient has only one policy on file for a given payer
+1 ; PIEN - payer ien
+2 ; IEN2 - patient ien (file 2)
+3 ;
+4 ; returns 1 if only one policy is found, 0 otherwise
+5 NEW CNT,DAYS,EXPDT,IEN36,IEN312,RES
+6 SET (CNT,RES)=0
+7 IF +$GET(PIEN)'>0!(+$GET(IEN2)'>0)
QUIT RES
+8 ;IB*702/TAZ - Get EIV NO GRP NUM A/U
+9 SET DAYS=$$GET1^DIQ(350.9,"1,",51.34,"I")
+10 SET IEN36=""
FOR
SET IEN36=$ORDER(^DIC(36,"AC",PIEN,IEN36))
if IEN36=""
QUIT
Begin DoDot:1
+11 SET IEN312=""
FOR
SET IEN312=$ORDER(^DPT(IEN2,.312,"B",IEN36,IEN312))
if IEN312=""
QUIT
Begin DoDot:2
+12 ;IB*702/TAZ - Compare EIV NO GRP NUM A/U with current date
+13 SET EXPDT=$$GET1^DIQ(2.312,IEN312_","_IEN2_",",3,"I")
+14 ;don't count for auto-update purposes
IF +EXPDT
IF $$FMDIFF^XLFDT(DT,EXPDT)>DAYS
QUIT
+15 SET CNT=CNT+1
End DoDot:2
End DoDot:1
+16 IF CNT=1
SET RES=1
+17 QUIT RES
+18 ;
MCRDT(RIEN,EBIEN) ; find effective date for Medicare response
+1 ; RIEN - file 365 ien
+2 ; EBIEN - subfile 365.02 ien
+3 ;
+4 ; returns date in FM format or "" if effective date was not found
+5 ;
+6 NEW DONE,DTIEN,IENS,RES,Z
+7 SET RES=""
SET DONE=0
+8 SET Z=""
FOR
SET Z=$ORDER(^IBCN(365,RIEN,2,EBIEN,8,"B",Z))
if Z=""!DONE
QUIT
Begin DoDot:1
+9 SET DTIEN=$ORDER(^IBCN(365,RIEN,2,EBIEN,8,"B",Z,""))
IF 'DTIEN
QUIT
+10 SET IENS=DTIEN_","_EBIEN_","_RIEN_","
+11 ; effective date has "eligibility" qualifier
+12 IF $$GET1^DIQ(365.28,IENS,.03)=307
SET RES=$$FMDATE^HLFNC($$GET1^DIQ(365.28,IENS,.02))
SET DONE=1
+13 QUIT
End DoDot:1
+14 QUIT RES
+15 ;
ISMCR(RIEN) ; Check if response is for Medicare part A/B
+1 ; Input: RIEN - Internal ien for file 365
+2 ; Returns A1^A2^A3^A4^A5 Where:
+3 ; A1 - 1 if response if for Medicare, 0 otherwise
+4 ; A2 - "MA" if response is for Medicare Part A
+5 ; "MB" if response is for Medicare Part B
+6 ; "B" if response is for both Part A and Part B
+7 ; "" if response if not for Medicare
+8 ; A3 - Effective date for Medicare Part A if response if for
+9 ; Part A or both parts, "" otherwise
+10 ; A4 - Effective date for Medicare Part B if response if for
+11 ; Part B or both parts, "" otherwise
+12 ; A5 - "MA" - Response is for active Medicare Part A only
+13 ; "MB" - Response is for active Medicare Part B only
+14 ; "B" - Response is for active Medicare Parts A and B
+15 ; "" - Response is not for active Medicare
+16 ; IB*2.0*549 - added return of A5
+17 ;
+18 ;IB*2.0*549 added ACTIVE,TYPEA,TYPEB,ZZ
NEW ACTIVE,DONE,EBIEN,RES,TYPE,TYPEA,TYPEB,Z,ZZ
+19 ;IB*2.0*549 added ,(TYPEA,TYPEB)=0
SET RES="0^"
SET DONE=0
SET (TYPEA,TYPEB)=0
+20 IF +RIEN'>0
QUIT RES
+21 IF '$DATA(^IBCN(365,RIEN))
QUIT RES
+22 SET Z=""
FOR
SET Z=$ORDER(^IBCN(365,RIEN,2,"B",Z))
if Z=""!DONE
QUIT
Begin DoDot:1
+23 SET EBIEN=$ORDER(^IBCN(365,RIEN,2,"B",Z,""))
+24 SET TYPE=$$GET1^DIQ(365.02,EBIEN_","_RIEN_",",.05)
+25 ;
+26 ; IB*2.0*549 added next two lines
+27 SET ACTIVE=$$GET1^DIQ(365.02,EBIEN_","_RIEN_",",.02,"I")
+28 SET ACTIVE=$SELECT(ACTIVE=1:1,1:0)
+29 IF TYPE="MA"
Begin DoDot:2
+30 ;IB*2.0*549 added line
if ACTIVE
SET TYPEA=1
+31 ;IB*2.0*549 added line
SET ZZ=$PIECE(RES,U,2)
+32 SET $PIECE(RES,U)=1
SET $PIECE(RES,U,2)=$SELECT(ZZ="":"MA",ZZ="MA":"MA",1:"B")
+33 SET $PIECE(RES,U,3)=$$MCRDT(RIEN,EBIEN)
+34 ;
+35 ; IB*2.0*549 added line
+36 if ACTIVE
SET $PIECE(RES,U,5)=$SELECT((TYPEA&TYPEB):"B",1:"MA")
End DoDot:2
+37 IF TYPE="MB"
Begin DoDot:2
+38 ;IB*2.0*549 added line
if ACTIVE
SET TYPEB=1
+39 ;IB*2.0*549 added line
SET ZZ=$PIECE(RES,U,2)
+40 SET $PIECE(RES,U)=1
SET $PIECE(RES,U,2)=$SELECT(ZZ="":"MB",ZZ="MB":"MB",1:"B")
+41 SET $PIECE(RES,U,4)=$$MCRDT(RIEN,EBIEN)
+42 ;
+43 ; IB*2.0*549 added line
+44 if ACTIVE
SET $PIECE(RES,U,5)=$SELECT((TYPEA&TYPEB):"B",1:"MB")
End DoDot:2
+45 IF $PIECE(RES,U,2)="B"
SET DONE=1
End DoDot:1
+46 QUIT RES
+47 ;
ERRACT(RIEN) ; Pick error action code to use for re-transmission
+1 ; Input: RIEN - IEN in file 365 (Transmission file)
+2 ; Returns: Error action^Error condition; "" if no error found
+3 ;
+4 ; If any of C,N,S,Y action codes are found, the first one encountered is returned.
+5 ; Otherwise, if W action code is found, it is returned.
+6 ; Otherwise, if X action code is found, it is returned.
+7 ; Otherwise, one of the P,R action codes is returned.
+8 ;
+9 NEW ACODE,AIEN,ECCODE,ECIEN,DONE,IEN,RES,Z
+10 SET RES=""
+11 IF '+$GET(RIEN)
GOTO ERRACTX
+12 SET DONE=0
+13 SET Z=""
FOR
SET IEN=$ORDER(^IBCN(365,RIEN,6,"B",Z))
if Z=""!DONE
QUIT
Begin DoDot:1
+14 SET IEN=+$ORDER(^IBCN(365,RIEN,6,"B",Z,""))
+15 if 'IEN
QUIT
+16 SET ECIEN=+$PIECE(^IBCN(365,RIEN,6,IEN,0),U,3)
+17 if 'ECIEN
QUIT
+18 SET AIEN=+$PIECE(^IBCN(365,RIEN,6,IEN,0),U,4)
+19 if 'AIEN
QUIT
+20 SET ACODE=$PIECE(^IBE(365.018,AIEN,0),U)
SET ECCODE=$PIECE(^IBE(365.017,ECIEN,0),U)
+21 ;
+22 ; One of "do not retransmit" codes
+23 IF ".C.N.S.Y"[("."_ACODE_".")
SET RES=ACODE_U_ECCODE
SET DONE=1
QUIT
+24 ;
+25 ; Retransmit after 30 days code
+26 IF ACODE="W"
SET RES=ACODE_U_ECCODE
QUIT
+27 ;
+28 ; Retransmit after 10 days code
+29 IF ACODE="X"
if RES'="W"
SET RES=ACODE_U_ECCODE
QUIT
+30 ;
+31 ; Retransmit whenever codes
+32 IF RES'="W"
IF RES'="X"
SET RES=ACODE_U_ECCODE
End DoDot:1
ERRACTX ;
+1 QUIT RES
+2 ;
NAMECMP(NAME1,NAME2) ; check if 2 names have the same first name and last name components
+1 ; NAME1, NAME2 - names to compare, should be in "last,first [middle]" format
+2 ;
+3 ; returns 1 if both first name and last name are the same between two names, returns 0 otherwise
+4 NEW NM1,NM2,RES
+5 SET RES=0
+6 SET NM1=$$HLNAME^HLFNC(NAME1)
SET NM2=$$HLNAME^HLFNC(NAME2)
+7 IF $PIECE(NM1,U)=$PIECE(NM2,U)
IF $PIECE(NM1,U,2)=$PIECE(NM2,U,2)
SET RES=1
+8 QUIT RES
+9 ;
TRNCWARN(GNUM,TRACE) ; send group number truncation warning message
+1 NEW MSG
+2 SET MSG(1)="WARNING: Group number in the Response Message from the EC has been truncated"
+3 SET MSG(2)="----------------------------------------------------------------------------"
+4 SET MSG(3)="Original group number (in the eIV response received): "_$GET(GNUM)
+5 SET MSG(4)="Truncated group number (filed into response file): "_$EXTRACT($GET(GNUM),1,17)
+6 SET MSG(5)=" "
+7 SET MSG(6)="The associated Trace # is "_$SELECT($GET(TRACE)="":"Unknown",1:TRACE)
+8 SET MSG(7)=" "
+9 DO MSG^IBCNEUT5($GET(MGRP),MSG(1),"MSG(")
+10 QUIT
+11 ;
CODECHK(RSUPDT) ; IB*2*497
+1 ; need to determine if codes and qualifiers sent in the 271 HL7 message
+2 ; are new. If code/qualifier does not exist in table then file new code into table
+3 ; input -
+4 ; RSUPDT = FDA array that will be passed to the DBS filer to update the
+5 ; entry/subentry into the IIV RESPONSE file
+6 ; example: RSUPDT(365.02,IENS,".02") = data to be filed into 365.02 subfile at field .02
+7 ; order through the RSUPDT array and determine if pointer to file
+8 ; if pointer to file then pass file name and value of code/qualifier
+9 ;
+10 ; IB*752 Fix existing bug - only allow certain files to be updated. See array XXFILE.
+11 ;
+12 NEW IBXMY,IENS,FLD,FILE,FSCMSG,RES,SITE,SITENUM,TOFILE,NEWARRY,XX,XXFILE,Z,ZIENS
+13 SET (IENS,FILE,FLD)=""
SET Z=0
+14 ;IB*771/DW Add original set of tables
FOR XX=11:1:18,21
SET XXFILE("365.0"_XX)=""
+15 FOR XX=22:1:29,31:1:39,41:1:46
SET XXFILE("365.0"_XX)=""
+16 FOR
SET FILE=$ORDER(RSUPDT(FILE))
if FILE=""
QUIT
FOR
SET IENS=$ORDER(RSUPDT(FILE,IENS))
if IENS=""
QUIT
Begin DoDot:1
+17 FOR
SET FLD=$ORDER(RSUPDT(FILE,IENS,FLD))
if FLD=""
QUIT
Begin DoDot:2
+18 ; value was not sent by payer; no need to continue
if RSUPDT(FILE,IENS,FLD)=""
QUIT
+19 ; get the name of the file that is pointed to (if any)
DO FIELD^DID(FILE,FLD,"","POINTER","RES")
+20 ; field is not defined as a pointer to a file
if RES("POINTER")=""
QUIT
+21 ; example: RES("POINTER")="IBE(365.011,"
SET TOFILE=$PIECE($PIECE(RES("POINTER"),","),"(",2)
+22 if +TOFILE=0
QUIT
+23 ;IB*752
IF '$DATA(XXFILE(TOFILE))
QUIT
+24 ; code is already in file. No need to update the pointed-to-file
if $$FIND1^DIC(TOFILE,"","X",RSUPDT(FILE,IENS,FLD))
QUIT
+25 SET Z=Z+1
SET ZIENS="+"_Z_","
+26 ; code passed into VistA from 271 message
SET NEWARRY(TOFILE,ZIENS,.01)=RSUPDT(FILE,IENS,FLD)
+27 ; Description of code
SET NEWARRY(TOFILE,ZIENS,.02)="OTHER"
+28 ; INACTIVE FLAG
SET NEWARRY(TOFILE,ZIENS,.03)=0
+29 ; FSC CONTROLLED ;IB*752 indicate not controlled
SET NEWARRY(TOFILE,ZIENS,.05)=0
+30 ;IB*752/CKB - notify FSC that a new code was learned on the fly
+31 SET SITE=$$SITE^VASITE
SET SITENUM=$PIECE(SITE,U,3)
+32 SET FSCMSG=TOFILE_U_SITENUM_U_RSUPDT(FILE,IENS,FLD)_U_$$GET1^DIQ(365,$GET(RIEN)_",",.09)
+33 DO MSG005^IBCNEMS1(FSCMSG)
+34 ;IB*771/DW Corrected call to send to FSC outlook address (was sent in wrong parameter)
+35 ;D MSG^IBCNEUT5("FSCECADMIN@domain.ext","X12 271 VistA tables, site #"_SITENUM_" new code added","MSG(")
+36 SET IBXMY=""
IF $$PROD^XUPROD(1)
SET IBXMY("FSCECADMIN@domain.ext")=""
+37 DO MSG^IBCNEUT5(,"X12 271 VistA tables, site #"_SITENUM_" new code added","MSG(",,.IBXMY)
End DoDot:2
End DoDot:1
+38 IF $DATA(NEWARRY)
DO UPDATE^DIE("","NEWARRY")
+39 QUIT
+40 ;
PREL(FILE,FIELD,CODE) ; IB*2*497 code from x12 271 message may need to be converted to 'other' if there is no match. Refer to tag SETLST
+1 ;
+2 ; INPUT - FILE = file # of the file that will be evaluated
+3 ; FIELD = field # that is defined with the SET OF CODE values
+4 ; CODE = patient relationship code sent by the X12 271 message
+5 ; OUTPUT - = converted or non-converted coded value
+6 NEW STRING,CODESTR,ARRAY,VAL,I,DEF
+7 SET CODE=$GET(CODE)
+8 ; quit when code was not sent from payer
IF CODE=""
QUIT CODE
+9 DO FIELD^DID(FILE,FIELD,"","TYPE","DEF")
+10 IF DEF("TYPE")="SET"
Begin DoDot:1
+11 SET CODESTR=$PIECE($GET(^DD(FILE,FIELD,0)),U,3)
+12 FOR I=1:1
SET VAL=$PIECE($PIECE(CODESTR,";",I),":")
if VAL=""
QUIT
SET ARRAY(VAL)=$PIECE($PIECE(CODESTR,";",I),":",2)
End DoDot:1
+13 ; if coded value does not exist in the array of codes then this is a new code sent by X12 271 message and will default to OTHER
QUIT $SELECT($DATA(ARRAY(CODE)):CODE,1:"G8")
+14 ;
SETLST ; SET OF CODES defined to 355.33,60.14 and 2.312,4.03; this tag is not referenced in any procedure. It's here for documentation purposes.
+1 ;;01^SPOUSE
+2 ;;18^SELF
+3 ;;19^CHILD
+4 ;;20^EMPLOYEE
+5 ;;29^SIGNIFICANT OTHER
+6 ;;32^MOTHER
+7 ;;33^FATHER
+8 ;;39^ORGAN DONOR
+9 ;;41^INJURED PLAINTIFF
+10 ;;53^LIFE PARTNER
+11 ;;G8^OTHER RELATIONSHIP