- IBCEOB1 ;ALB/TMP/PJH - 835 EDI EOB MSG PROCESSING ;Feb 09, 2018@10:11:43
- ;;2.0;INTEGRATED BILLING;**137,135,155,296,356,349,431,488,597,592**;21-MAR-94;Build 58
- ;;Per VA Directive 6402, this routine should not be modified.
- Q
- ;
- STORE(A,IB0,IBEOB,LEVEL) ;
- ; A = the string of data to extract and try to store
- ; each ^ piece is a field to store
- ; within each ^ piece, there are 5 ';' pieces:
- ; 1 = piece to extract from the data string;
- ; 2 = field to update;
- ; 3 = flag for dollar amt (1=YES);
- ; 4 = flag for 4-slash stuff without transform (1=YES);
- ; 5 = flag for numeric/non-dollar amt (1=Yes, 0=No,
- ; Dn = the field is numeric with 'n' decimal places
- ; IB0 = the record being processed
- ; IBEOB = the ien of the EOB entry in file 361.1
- ; LEVEL = the array that contains the DIE and DA values if stuffing at a
- ; level other than the top level
- ;
- N B,IBPC,IBFLD,DA,DR,DIE,X,Y
- S DR=";"
- ;
- I '$G(LEVEL) S DIE="^IBM(361.1,",DA=IBEOB
- ;
- I $G(LEVEL) D
- . N Q
- . S DIE=$G(LEVEL("DIE"))
- . S Q=0 F S Q=$O(LEVEL(Q)) Q:'Q S DA(Q)=LEVEL(Q)
- . S DA=LEVEL(0)
- ;
- I $G(DA) F B=1:1:$L(A,U) D
- . S IBPC=$P(A,U,B),IBFLD=$P(IBPC,";",2)
- . I $P(IB0,U,+IBPC)'="",IBFLD D
- .. N VAL
- .. ; For dollar amts, add full cents; For numerics, strip leading
- .. ; 0's; For non-numeric/non-dollar amts, make any ; in data into |
- .. S VAL=$S($P(IBPC,";",3):$$DOLLAR^IBCEOB($P(IB0,U,+IBPC)),$P(IBPC,";",5):+$P(IB0,U,+IBPC),$P($P(IBPC,";",5),"D",2):$P(IB0,U,+IBPC)/(10**$P($P(IBPC,";",5),"D",2)),1:$TR($P(IB0,U,+IBPC),";","|"))
- .. I $P(IBPC,";",3),VAL S VAL=$P(VAL,".")_"."_$E($P(VAL,".",2)_"00",1,2)
- .. S DR=DR_IBFLD_"///"_$S($P(IBPC,";",4):"/",1:"")_VAL_";"
- ;
- S DR=$P(DR,";",2,$L(DR,";")-1)
- I DR'="" D ^DIE
- Q ($D(Y)=0) ;Successfully stored all the data it was sent if $D(Y)=0
- ;
- HDR(IB0,IBEGBL,IBEOB,HIPAA) ; Store header data for EOB
- ; IB0 = the record being processed from the msg
- ; IBEOB = the ien of the EOB entry in file 361.1
- ;
- N IBDT,IBDTP,DA,DR,DIE,X,Y
- K IBXSAVE("XTRA"),IBZSAVE
- ;
- S HIPAA=+$P(IB0,U,16) ;HIPAA Version code
- S IBDT=$P(IB0,U,3),IBDT=$E(IBDT,1,4)-1700_$E(IBDT,5,8)_"."_$P(IB0,U,4)
- S IBDTP=$P(IB0,U,9)
- I IBDTP S IBDTP=$E(IBDTP,1,4)-1700_$E(IBDTP,5,8)
- S DR=$S($P(IB0,U,7)'="":".03////"_$P(IB0,U,7)_";",1:"")_".05////"_IBDT_";.04////"_($P(IB0,U,5)="Y")_";.15///"_$$COBN^IBCEF(+$G(^IBM(361.1,IBEOB,0)))_";.07///"_$P(IB0,U,8)_$S(IBDTP:";.06////"_IBDTP,1:"")
- S DIE="^IBM(361.1,",DA=IBEOB
- D ^DIE
- I $D(Y)'=0 D
- . S ^TMP(IBEGBL,$J,+$O(^TMP(IBEGBL,$J,""),-1)+1)="Bad header data"
- Q ($D(Y)=0)
- ;
- FINDLN(IB0,IBEOB,IBZDATA,PLREF,ERRCOD) ; Find corresponding billed line for the adj
- ; IB0 = the record being processed
- ; NOTE: pieces 3,4,16 are already reformatted
- ; IBEOB = the ien of the EOB entry in file 361.1
- ; IBZDATA = the array from the output formatter containing line
- ; items for the bill. This is passed in so this data only has
- ; to be extracted once for each bill (the first time in, it
- ; will be undefined)
- ; PLREF = Provider Line Reference
- ; OUTPUT = Line # in the original bill that this adjustment relates to
- ; ^ paid procedure code if different from original procedure OR
- ; paid rev code if different from original and no proc code
- ; ERRCOD = Contains any error condition that may have been encountered
- ; while conducting the field matching tests.
- ;
- N IBLN,IBLN1,IBBNDL,OCHG,OCHG2,OPROC,OREVCD,IBIFN,IBXARRAY,IBXARRY
- N IBXERR,UNITS,UNITS2,UNITS3,IBMOD,Z,Z0,EOBCHG,IBZVLA,IBAMIN,MATCHED,MOD837S
- ;
- S (IBLN,IBLN1)="",IBIFN=+$G(^IBM(361.1,IBEOB,0)),(ERRCOD,MATCHED)=0
- S EOBCHG=+$$DOLLAR^IBCEOB($P(IB0,U,15)) ; charges on EOB 40 record
- ;
- ; if original procedure exists and is different than the 835 procedure,
- ; the procedure or revenue code originally billed will be in piece 10
- ; of the '40' record of the 835 flat file. Otherwise, pc 10 is null.
- S IBBNDL=$S($P(IB0,U,10)'="":1,1:0)
- ;
- ; If this is a split MRA, build array of Vista line#'s from other split MRA's
- I $P($G(^IBM(361.1,IBEOB,0)),U,4)=1,$$SPLIT^IBCEMU1(IBEOB) D
- . N IEN S IEN=0
- . F S IEN=$O(^IBM(361.1,"B",IBIFN,IEN)) Q:'IEN I IEN'=IBEOB D
- .. I $P($G(^IBM(361.1,IEN,0)),U,4)'=1 Q ; not an MRA
- .. I '$$SPLIT^IBCEMU1(IEN) Q ; not a split EOB
- .. M IBZVLA=^IBM(361.1,IEN,15,"AC")
- .. Q
- . Q
- ;
- I $P($G(^DGCR(399,IBIFN,0)),U,19)=3 D G FINDLNX ; UB-04 format
- . I '$D(IBZDATA) D F^IBCEF("N-UB-04 SERVICE LINE (EDI)","IBZDATA",,IBIFN)
- . ; Quit if a Line Item CTRL # exist, skip mismatching process.
- . I +PLREF,$D(IBZDATA(+PLREF)) S IBLN=+PLREF_U_$P(IB0,U,10) Q
- . ;
- . S Z=0 F S Z=$O(IBZDATA(Z)) Q:'Z D Q:+MATCHED
- .. ; Quit if processing an MRA and this VistA line# has already been filed
- .. I $P($G(^IBM(361.1,IBEOB,0)),U,4)=1,$D(^IBM(361.1,IBEOB,15,"AC",Z)) Q
- .. ; Quit if split MRA and this VistA line# has already been filed
- .. I $D(IBZVLA(Z)) Q
- .. I $G(IBZDATA(Z))="" Q
- .. ;
- .. ; CHECKING FOR A MATCHING RECORD ON FIRST PASS.
- .. D GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z)) ; Get the Procedure Code values.
- .. ; if not bundled/unbundled
- .. I 'IBBNDL D Q
- ... I OPROC="",OREVCD,OREVCD'=$P(IB0,U,4) Q ; revenue code
- ... I OPROC'="",OPROC'=$P(IB0,U,3) Q ; procedure code
- ... S MATCHED=Z
- .. ;
- .. ; if bundled/unbundled
- .. I IBBNDL D Q
- ... I OPROC="",OREVCD,OREVCD'=+$P(IB0,U,10) Q ; revenue code
- ... I OPROC'="",OPROC'=$P(IB0,U,10) Q ; procedure code
- ... S MATCHED=Z
- .. Q
- . ;
- . I 'MATCHED D Q
- .. I $G(IBZDATA(1))="" Q ;if no data in IBZDATA(1) Quit to avoid undefined error - *597
- .. D GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(1)) ; Due to no matches, get the info from the 1st line item.
- .. I 'IBBNDL D Q
- ... I OPROC="",OREVCD,OREVCD'=$P(IB0,U,4) S ERRCOD=1 Q ; revenue code
- ... I OPROC'="",OPROC'=$P(IB0,U,3) S ERRCOD=2 Q ; procedure code
- .. I IBBNDL D Q
- ... I OPROC="",OREVCD,OREVCD'=+$P(IB0,U,10) S ERRCOD=1 Q ; revenue code
- ... I OPROC'="",OPROC'=$P(IB0,U,10) S ERRCOD=2 Q ; procedure code
- .. Q
- . ;
- . ; FOUND A MATCHING PROCEDURE CODE...SO LET'S SEE IF EVERYTHING ELSE MATCHES.
- . S Z=MATCHED
- . D GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z)) ; Get the Procedure Code values.
- . S OCHG=$P(IBZDATA(Z),U,3)*$P(IBZDATA(Z),U,4) ; Total charge from bill
- . S OCHG2=+$P(IBZDATA(Z),U,5)
- . I OCHG'=EOBCHG,OCHG2=EOBCHG S OCHG=OCHG2 ; update OCHG
- . ;
- . ; if not bundled/unbundled
- . I 'IBBNDL D Q
- .. I +$P(IBZDATA(Z),U,4)'=$P(IB0,U,16) S ERRCOD=3 Q ; original units
- .. I +OCHG'=EOBCHG S ERRCOD=4 Q ; original charges
- .. I '$$MODMATCH($P(IBZDATA(Z),U,9),$P(IB0,U,5,8),.MOD837S),'$$MODMATCH($P($P(IBZDATA(Z),U,9),",",1),$P(IB0,U,5),.MOD837S) S ERRCOD=5_U_MOD837S Q ; modifiers
- .. S IBLN=Z
- .. Q
- . ;
- . ; if bundled/unbundled
- . I IBBNDL D Q
- .. I +$P(IBZDATA(Z),U,4)'=$P(IB0,U,16) S ERRCOD=3 Q ; original units
- .. I +OCHG'=EOBCHG S ERRCOD=4 Q ; original charges
- .. I '$$MODMATCH($P(IBZDATA(Z),U,9),$P(IB0,U,11,14),.MOD837S),'$$MODMATCH($P($P(IBZDATA(Z),U,9),",",1),$P(IB0,U,11),.MOD837S) S ERRCOD=5_U_MOD837S Q ; modifiers
- .. S IBLN=Z_U_$S(OPROC'="":OPROC,1:OREVCD)
- .. Q
- . ; When dealing with Inpatient UB-04's, check for revenue code roll-ups
- . I 'IBLN,$$INPAT^IBCEF(IBIFN,1) D RCRU^IBCEOB00(.IBZDATA,IB0,.IBLN)
- . ; If only 1 rev code and charges are the same, assume a match
- . I 'IBLN,'$P($G(^IBM(361.1,IBEOB,0)),U,4),$O(IBZDATA(""),-1)=$O(IBZDATA("")),+OCHG=EOBCHG S IBLN=+$O(IBZDATA(""))_U_OREVCD
- ;
- ; At this point, we can assume the claim is CMS-1500 format
- ;JWS;IB*2.0*592;need to be form specific with line level data collection call using output formatter
- I '$D(IBZDATA) D
- . I $$FT^IBCEF(IBIFN)=2 D F^IBCEF("N-HCFA 1500 SERVICE LINE (EDI)","IBZDATA",,IBIFN) Q
- . I $$FT^IBCEF(IBIFN)=7 D F^IBCEF("N-HCFA SERVICE LINE CALLABLE","IBZDATA",,IBIFN)
- I +PLREF,$D(IBZDATA(+PLREF)) S IBLN=PLREF_U_$P(IB0,U,10) G FINDLNX ; If a Line Item CTRL # exist, skip mismatching process.
- ;
- S Z=0 F S Z=$O(IBZDATA(Z)) Q:'Z D Q:+MATCHED
- . ; Quit if processing an MRA and this VistA line# has already been filed
- . I $P($G(^IBM(361.1,IBEOB,0)),U,4)=1,$D(^IBM(361.1,IBEOB,15,"AC",Z)) Q
- . ; Quit if split MRA and this VistA line# has already been filed
- . I $D(IBZVLA(Z)) Q
- . I $G(IBZDATA(Z))="" Q
- . ;
- . ; CHECKING FOR A MATCHING RECORD ON FIRST PASS.
- . D GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z)) ; Get the Procedure Code values.
- . I OPROC'=$S('IBBNDL:$P(IB0,U,3),1:$P(IB0,U,10)) Q ;procedure code.
- . S MATCHED=Z
- . Q
- ;
- I 'MATCHED D G FINDLNX
- . I $G(IBZDATA(1))="" Q ;if no data in IBZDATA(1) Quit to avoid undefined error - *597
- . D GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(1)) ; Because no matches, get the information from the 1st line item.
- . I OPROC'=$S('IBBNDL:$P(IB0,U,3),1:$P(IB0,U,10)) S ERRCOD=2 ; Mis-matched Proc Code.
- ;
- ; FOUND A MATCHING PROCEDURE CODE...SO LET'S SEE IF EVERYTHING ELSE MATCHES.
- S Z=MATCHED
- ; Quit if processing an MRA and this VistA line# has already been filed
- I $P($G(^IBM(361.1,IBEOB,0)),U,4)=1,$D(^IBM(361.1,IBEOB,15,"AC",Z)) G FINDLNX
- ; Quit if split MRA and this VistA line# has already been filed
- I $D(IBZVLA(Z)) G FINDLNX
- I $G(IBZDATA(Z))="" G FINDLNX
- ;
- S OCHG=$P(IBZDATA(Z),U,8)*$P(IBZDATA(Z),U,9) ; charge from bill
- S IBAMIN=""
- I $P(IBZDATA(Z),U,12)'="" S IBAMIN=$P(IBZDATA(Z),U,12) ;anesthesia minutes
- S UNITS=$S('IBAMIN:$P(IBZDATA(Z),U,9),1:IBAMIN/15)
- ; original units from bill or anesthesia minutes calculation
- I $P(UNITS,".",2) S UNITS=$FN(UNITS,"",1) ; round to a single decimal place for fractional units
- I $P($P(IB0,U,16),".",2) S $P(IB0,U,16)=$FN($P(IB0,U,16),"",1)
- S UNITS2=$P(IBZDATA(Z),U,9) ; just the units
- ; UNITS3 is the number of anesthesia minutes divided by 10, or nil.
- ; Solution to get around the Trailblazers bug for MRAs
- S UNITS3=""
- I IBAMIN'=0 S UNITS3=IBAMIN/10
- ;
- I UNITS'=$P(IB0,U,16),UNITS2'=$P(IB0,U,16),UNITS3'=$P(IB0,U,16),IBAMIN'=$P(IB0,U,16) S ERRCOD=3 G FINDLNX ; Original units
- I $$DOLLAR^IBCEFG1(OCHG)'=+$P(IB0,U,15) S ERRCOD=4 G FINDLNX ; original charges.
- I $S($P(IB0,U,19):$P(IB0,U,19)=$P(IBZDATA(Z),U),1:1) D G:+ERRCOD FINDLNX
- . ;Original procedure/chg/units/date have matched in order to get here
- . ;Check matching original modifiers
- . I '$$MODMATCH($$MODLST^IBEFUNC2($P(IBZDATA(Z),U,10)),$S('IBBNDL:$P(IB0,U,5,8),1:$P(IB0,U,11,14)),.MOD837S) S ERRCOD=5_U_MOD837S Q ; modifiers.
- . S IBLN=Z_$S(IBBNDL:U_OPROC,1:"")
- I 'IBLN,IBLN1 S IBLN=IBLN1
- ;
- FINDLNX ;
- Q IBLN
- ;
- GTPRCD(IBBNDL,OPROC,OREVCD,IBZREC) ; Set up the Procedure Code/Revenue Code fields.
- N CPT
- ;
- I $P($G(^DGCR(399,IBIFN,0)),U,19)=3 D Q ; For UB-04s
- . S CPT=$P(IBZREC,U,2) ; proc from bill
- . I CPT'?.N,CPT'="" S CPT=$O(^ICPT("B",CPT,"")) ; non-numeric proc
- . S OPROC=$$PRCD^IBCEF1(+CPT_";ICPT(") ; ext proc code
- . S OREVCD=+$P($G(^DGCR(399.2,+IBZREC,0)),U) ; Rev cd from bill
- ;
- ; For CMS-1500s
- S CPT=$P(IBZREC,U,5) ; proc from bill
- I CPT'?.N,CPT'="" S CPT=$O(^ICPT("B",CPT,"")) ; non-numeric proc
- S OPROC=$$PRCD^IBCEF1(+CPT_";ICPT(") ; ext proc code
- Q
- ;
- MODMATCH(IB,MODLST,MOD837S) ; Match modifiers
- ; IB = the list of modifiers iens from the bill, comma delimited
- ; MODLST = the 4 '^' pieces of the reported modifiers
- ;
- N MODOK,Q,Z0,IBMOD,MMOD
- S MODOK=1,MOD837S=""
- I $TR(IB,",")'="" F Q=1:1:$L(IB,",") S Z0=$P(IB,",",Q) I Z0'="" D
- . S IBMOD(Z0)=$G(IBMOD(Z0))+1
- . I '$L(MOD837S) S MOD837S=Z0 Q
- . S MOD837S=MOD837S_","_Z0
- I $TR(MODLST,U)="",$O(IBMOD(""))="" G MODQ ; No modifiers used
- ;
- ; No match if no VistA modifiers, but there are MRA modifiers
- I $TR(MODLST,U)'="",$O(IBMOD(""))="" S MODOK=0 G MODQ
- ;
- ; Evaluate each MRA modifier
- F Z0=1:1:4 D
- . S MMOD=$P(MODLST,U,Z0) Q:MMOD="" ; individual MRA modifier
- . I '$D(IBMOD(MMOD)) Q ; not in array so just quit
- . S IBMOD(MMOD)=IBMOD(MMOD)-1 ; decrement array counter
- . I 'IBMOD(MMOD) KILL IBMOD(MMOD) ; if 0, then kill array entry
- . Q
- ;
- I $O(IBMOD(""))'="" S MODOK=0 ; All submitted mods not matched
- MODQ Q MODOK
- ;
- --- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HIBCEOB1 12465 printed Mar 13, 2025@21:16:11 Page 2
- IBCEOB1 ;ALB/TMP/PJH - 835 EDI EOB MSG PROCESSING ;Feb 09, 2018@10:11:43
- +1 ;;2.0;INTEGRATED BILLING;**137,135,155,296,356,349,431,488,597,592**;21-MAR-94;Build 58
- +2 ;;Per VA Directive 6402, this routine should not be modified.
- +3 QUIT
- +4 ;
- STORE(A,IB0,IBEOB,LEVEL) ;
- +1 ; A = the string of data to extract and try to store
- +2 ; each ^ piece is a field to store
- +3 ; within each ^ piece, there are 5 ';' pieces:
- +4 ; 1 = piece to extract from the data string;
- +5 ; 2 = field to update;
- +6 ; 3 = flag for dollar amt (1=YES);
- +7 ; 4 = flag for 4-slash stuff without transform (1=YES);
- +8 ; 5 = flag for numeric/non-dollar amt (1=Yes, 0=No,
- +9 ; Dn = the field is numeric with 'n' decimal places
- +10 ; IB0 = the record being processed
- +11 ; IBEOB = the ien of the EOB entry in file 361.1
- +12 ; LEVEL = the array that contains the DIE and DA values if stuffing at a
- +13 ; level other than the top level
- +14 ;
- +15 NEW B,IBPC,IBFLD,DA,DR,DIE,X,Y
- +16 SET DR=";"
- +17 ;
- +18 IF '$GET(LEVEL)
- SET DIE="^IBM(361.1,"
- SET DA=IBEOB
- +19 ;
- +20 IF $GET(LEVEL)
- Begin DoDot:1
- +21 NEW Q
- +22 SET DIE=$GET(LEVEL("DIE"))
- +23 SET Q=0
- FOR
- SET Q=$ORDER(LEVEL(Q))
- if 'Q
- QUIT
- SET DA(Q)=LEVEL(Q)
- +24 SET DA=LEVEL(0)
- End DoDot:1
- +25 ;
- +26 IF $GET(DA)
- FOR B=1:1:$LENGTH(A,U)
- Begin DoDot:1
- +27 SET IBPC=$PIECE(A,U,B)
- SET IBFLD=$PIECE(IBPC,";",2)
- +28 IF $PIECE(IB0,U,+IBPC)'=""
- IF IBFLD
- Begin DoDot:2
- +29 NEW VAL
- +30 ; For dollar amts, add full cents; For numerics, strip leading
- +31 ; 0's; For non-numeric/non-dollar amts, make any ; in data into |
- +32 SET VAL=$SELECT($PIECE(IBPC,";",3):$$DOLLAR^IBCEOB($PIECE(IB0,U,+IBPC)),$PIECE(IBPC,";",5):+$PIECE(IB0,U,+IBPC),$PIECE($PIECE(IBPC,";",5),"D",2):$PIECE(IB0,U,+IBPC)/(10**$PIECE($PIECE(IBPC,";",5),"D",2)),1:$TRANSLATE($PI
- ECE(IB0,U,+IBPC),";","|"))
- +33 IF $PIECE(IBPC,";",3)
- IF VAL
- SET VAL=$PIECE(VAL,".")_"."_$EXTRACT($PIECE(VAL,".",2)_"00",1,2)
- +34 SET DR=DR_IBFLD_"///"_$SELECT($PIECE(IBPC,";",4):"/",1:"")_VAL_";"
- End DoDot:2
- End DoDot:1
- +35 ;
- +36 SET DR=$PIECE(DR,";",2,$LENGTH(DR,";")-1)
- +37 IF DR'=""
- DO ^DIE
- +38 ;Successfully stored all the data it was sent if $D(Y)=0
- QUIT ($DATA(Y)=0)
- +39 ;
- HDR(IB0,IBEGBL,IBEOB,HIPAA) ; Store header data for EOB
- +1 ; IB0 = the record being processed from the msg
- +2 ; IBEOB = the ien of the EOB entry in file 361.1
- +3 ;
- +4 NEW IBDT,IBDTP,DA,DR,DIE,X,Y
- +5 KILL IBXSAVE("XTRA"),IBZSAVE
- +6 ;
- +7 ;HIPAA Version code
- SET HIPAA=+$PIECE(IB0,U,16)
- +8 SET IBDT=$PIECE(IB0,U,3)
- SET IBDT=$EXTRACT(IBDT,1,4)-1700_$EXTRACT(IBDT,5,8)_"."_$PIECE(IB0,U,4)
- +9 SET IBDTP=$PIECE(IB0,U,9)
- +10 IF IBDTP
- SET IBDTP=$EXTRACT(IBDTP,1,4)-1700_$EXTRACT(IBDTP,5,8)
- +11 SET DR=$SELECT($PIECE(IB0,U,7)'="":".03////"_$PIECE(IB0,U,7)_";",1:"")_".05////"_IBDT_";.04////"_($PIECE(IB0,U,5)="Y")_";.15///"_$$COBN^IBCEF(+$GET(^IBM(361.1,IBEOB,0)))_";.07///"_$PIECE(IB0,U,8)_$SELECT(IBDTP:";.06////"_IBDTP,1:"")
- +12 SET DIE="^IBM(361.1,"
- SET DA=IBEOB
- +13 DO ^DIE
- +14 IF $DATA(Y)'=0
- Begin DoDot:1
- +15 SET ^TMP(IBEGBL,$JOB,+$ORDER(^TMP(IBEGBL,$JOB,""),-1)+1)="Bad header data"
- End DoDot:1
- +16 QUIT ($DATA(Y)=0)
- +17 ;
- FINDLN(IB0,IBEOB,IBZDATA,PLREF,ERRCOD) ; Find corresponding billed line for the adj
- +1 ; IB0 = the record being processed
- +2 ; NOTE: pieces 3,4,16 are already reformatted
- +3 ; IBEOB = the ien of the EOB entry in file 361.1
- +4 ; IBZDATA = the array from the output formatter containing line
- +5 ; items for the bill. This is passed in so this data only has
- +6 ; to be extracted once for each bill (the first time in, it
- +7 ; will be undefined)
- +8 ; PLREF = Provider Line Reference
- +9 ; OUTPUT = Line # in the original bill that this adjustment relates to
- +10 ; ^ paid procedure code if different from original procedure OR
- +11 ; paid rev code if different from original and no proc code
- +12 ; ERRCOD = Contains any error condition that may have been encountered
- +13 ; while conducting the field matching tests.
- +14 ;
- +15 NEW IBLN,IBLN1,IBBNDL,OCHG,OCHG2,OPROC,OREVCD,IBIFN,IBXARRAY,IBXARRY
- +16 NEW IBXERR,UNITS,UNITS2,UNITS3,IBMOD,Z,Z0,EOBCHG,IBZVLA,IBAMIN,MATCHED,MOD837S
- +17 ;
- +18 SET (IBLN,IBLN1)=""
- SET IBIFN=+$GET(^IBM(361.1,IBEOB,0))
- SET (ERRCOD,MATCHED)=0
- +19 ; charges on EOB 40 record
- SET EOBCHG=+$$DOLLAR^IBCEOB($PIECE(IB0,U,15))
- +20 ;
- +21 ; if original procedure exists and is different than the 835 procedure,
- +22 ; the procedure or revenue code originally billed will be in piece 10
- +23 ; of the '40' record of the 835 flat file. Otherwise, pc 10 is null.
- +24 SET IBBNDL=$SELECT($PIECE(IB0,U,10)'="":1,1:0)
- +25 ;
- +26 ; If this is a split MRA, build array of Vista line#'s from other split MRA's
- +27 IF $PIECE($GET(^IBM(361.1,IBEOB,0)),U,4)=1
- IF $$SPLIT^IBCEMU1(IBEOB)
- Begin DoDot:1
- +28 NEW IEN
- SET IEN=0
- +29 FOR
- SET IEN=$ORDER(^IBM(361.1,"B",IBIFN,IEN))
- if 'IEN
- QUIT
- IF IEN'=IBEOB
- Begin DoDot:2
- +30 ; not an MRA
- IF $PIECE($GET(^IBM(361.1,IEN,0)),U,4)'=1
- QUIT
- +31 ; not a split EOB
- IF '$$SPLIT^IBCEMU1(IEN)
- QUIT
- +32 MERGE IBZVLA=^IBM(361.1,IEN,15,"AC")
- +33 QUIT
- End DoDot:2
- +34 QUIT
- End DoDot:1
- +35 ;
- +36 ; UB-04 format
- IF $PIECE($GET(^DGCR(399,IBIFN,0)),U,19)=3
- Begin DoDot:1
- +37 IF '$DATA(IBZDATA)
- DO F^IBCEF("N-UB-04 SERVICE LINE (EDI)","IBZDATA",,IBIFN)
- +38 ; Quit if a Line Item CTRL # exist, skip mismatching process.
- +39 IF +PLREF
- IF $DATA(IBZDATA(+PLREF))
- SET IBLN=+PLREF_U_$PIECE(IB0,U,10)
- QUIT
- +40 ;
- +41 SET Z=0
- FOR
- SET Z=$ORDER(IBZDATA(Z))
- if 'Z
- QUIT
- Begin DoDot:2
- +42 ; Quit if processing an MRA and this VistA line# has already been filed
- +43 IF $PIECE($GET(^IBM(361.1,IBEOB,0)),U,4)=1
- IF $DATA(^IBM(361.1,IBEOB,15,"AC",Z))
- QUIT
- +44 ; Quit if split MRA and this VistA line# has already been filed
- +45 IF $DATA(IBZVLA(Z))
- QUIT
- +46 IF $GET(IBZDATA(Z))=""
- QUIT
- +47 ;
- +48 ; CHECKING FOR A MATCHING RECORD ON FIRST PASS.
- +49 ; Get the Procedure Code values.
- DO GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z))
- +50 ; if not bundled/unbundled
- +51 IF 'IBBNDL
- Begin DoDot:3
- +52 ; revenue code
- IF OPROC=""
- IF OREVCD
- IF OREVCD'=$PIECE(IB0,U,4)
- QUIT
- +53 ; procedure code
- IF OPROC'=""
- IF OPROC'=$PIECE(IB0,U,3)
- QUIT
- +54 SET MATCHED=Z
- End DoDot:3
- QUIT
- +55 ;
- +56 ; if bundled/unbundled
- +57 IF IBBNDL
- Begin DoDot:3
- +58 ; revenue code
- IF OPROC=""
- IF OREVCD
- IF OREVCD'=+$PIECE(IB0,U,10)
- QUIT
- +59 ; procedure code
- IF OPROC'=""
- IF OPROC'=$PIECE(IB0,U,10)
- QUIT
- +60 SET MATCHED=Z
- End DoDot:3
- QUIT
- +61 QUIT
- End DoDot:2
- if +MATCHED
- QUIT
- +62 ;
- +63 IF 'MATCHED
- Begin DoDot:2
- +64 ;if no data in IBZDATA(1) Quit to avoid undefined error - *597
- IF $GET(IBZDATA(1))=""
- QUIT
- +65 ; Due to no matches, get the info from the 1st line item.
- DO GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(1))
- +66 IF 'IBBNDL
- Begin DoDot:3
- +67 ; revenue code
- IF OPROC=""
- IF OREVCD
- IF OREVCD'=$PIECE(IB0,U,4)
- SET ERRCOD=1
- QUIT
- +68 ; procedure code
- IF OPROC'=""
- IF OPROC'=$PIECE(IB0,U,3)
- SET ERRCOD=2
- QUIT
- End DoDot:3
- QUIT
- +69 IF IBBNDL
- Begin DoDot:3
- +70 ; revenue code
- IF OPROC=""
- IF OREVCD
- IF OREVCD'=+$PIECE(IB0,U,10)
- SET ERRCOD=1
- QUIT
- +71 ; procedure code
- IF OPROC'=""
- IF OPROC'=$PIECE(IB0,U,10)
- SET ERRCOD=2
- QUIT
- End DoDot:3
- QUIT
- +72 QUIT
- End DoDot:2
- QUIT
- +73 ;
- +74 ; FOUND A MATCHING PROCEDURE CODE...SO LET'S SEE IF EVERYTHING ELSE MATCHES.
- +75 SET Z=MATCHED
- +76 ; Get the Procedure Code values.
- DO GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z))
- +77 ; Total charge from bill
- SET OCHG=$PIECE(IBZDATA(Z),U,3)*$PIECE(IBZDATA(Z),U,4)
- +78 SET OCHG2=+$PIECE(IBZDATA(Z),U,5)
- +79 ; update OCHG
- IF OCHG'=EOBCHG
- IF OCHG2=EOBCHG
- SET OCHG=OCHG2
- +80 ;
- +81 ; if not bundled/unbundled
- +82 IF 'IBBNDL
- Begin DoDot:2
- +83 ; original units
- IF +$PIECE(IBZDATA(Z),U,4)'=$PIECE(IB0,U,16)
- SET ERRCOD=3
- QUIT
- +84 ; original charges
- IF +OCHG'=EOBCHG
- SET ERRCOD=4
- QUIT
- +85 ; modifiers
- IF '$$MODMATCH($PIECE(IBZDATA(Z),U,9),$PIECE(IB0,U,5,8),.MOD837S)
- IF '$$MODMATCH($PIECE($PIECE(IBZDATA(Z),U,9),",",1),$PIECE(IB0,U,5),.MOD837S)
- SET ERRCOD=5_U_MOD837S
- QUIT
- +86 SET IBLN=Z
- +87 QUIT
- End DoDot:2
- QUIT
- +88 ;
- +89 ; if bundled/unbundled
- +90 IF IBBNDL
- Begin DoDot:2
- +91 ; original units
- IF +$PIECE(IBZDATA(Z),U,4)'=$PIECE(IB0,U,16)
- SET ERRCOD=3
- QUIT
- +92 ; original charges
- IF +OCHG'=EOBCHG
- SET ERRCOD=4
- QUIT
- +93 ; modifiers
- IF '$$MODMATCH($PIECE(IBZDATA(Z),U,9),$PIECE(IB0,U,11,14),.MOD837S)
- IF '$$MODMATCH($PIECE($PIECE(IBZDATA(Z),U,9),",",1),$PIECE(IB0,U,11),.MOD837S)
- SET ERRCOD=5_U_MOD837S
- QUIT
- +94 SET IBLN=Z_U_$SELECT(OPROC'="":OPROC,1:OREVCD)
- +95 QUIT
- End DoDot:2
- QUIT
- +96 ; When dealing with Inpatient UB-04's, check for revenue code roll-ups
- +97 IF 'IBLN
- IF $$INPAT^IBCEF(IBIFN,1)
- DO RCRU^IBCEOB00(.IBZDATA,IB0,.IBLN)
- +98 ; If only 1 rev code and charges are the same, assume a match
- +99 IF 'IBLN
- IF '$PIECE($GET(^IBM(361.1,IBEOB,0)),U,4)
- IF $ORDER(IBZDATA(""),-1)=$ORDER(IBZDATA(""))
- IF +OCHG=EOBCHG
- SET IBLN=+$ORDER(IBZDATA(""))_U_OREVCD
- End DoDot:1
- GOTO FINDLNX
- +100 ;
- +101 ; At this point, we can assume the claim is CMS-1500 format
- +102 ;JWS;IB*2.0*592;need to be form specific with line level data collection call using output formatter
- +103 IF '$DATA(IBZDATA)
- Begin DoDot:1
- +104 IF $$FT^IBCEF(IBIFN)=2
- DO F^IBCEF("N-HCFA 1500 SERVICE LINE (EDI)","IBZDATA",,IBIFN)
- QUIT
- +105 IF $$FT^IBCEF(IBIFN)=7
- DO F^IBCEF("N-HCFA SERVICE LINE CALLABLE","IBZDATA",,IBIFN)
- End DoDot:1
- +106 ; If a Line Item CTRL # exist, skip mismatching process.
- IF +PLREF
- IF $DATA(IBZDATA(+PLREF))
- SET IBLN=PLREF_U_$PIECE(IB0,U,10)
- GOTO FINDLNX
- +107 ;
- +108 SET Z=0
- FOR
- SET Z=$ORDER(IBZDATA(Z))
- if 'Z
- QUIT
- Begin DoDot:1
- +109 ; Quit if processing an MRA and this VistA line# has already been filed
- +110 IF $PIECE($GET(^IBM(361.1,IBEOB,0)),U,4)=1
- IF $DATA(^IBM(361.1,IBEOB,15,"AC",Z))
- QUIT
- +111 ; Quit if split MRA and this VistA line# has already been filed
- +112 IF $DATA(IBZVLA(Z))
- QUIT
- +113 IF $GET(IBZDATA(Z))=""
- QUIT
- +114 ;
- +115 ; CHECKING FOR A MATCHING RECORD ON FIRST PASS.
- +116 ; Get the Procedure Code values.
- DO GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(Z))
- +117 ;procedure code.
- IF OPROC'=$SELECT('IBBNDL:$PIECE(IB0,U,3),1:$PIECE(IB0,U,10))
- QUIT
- +118 SET MATCHED=Z
- +119 QUIT
- End DoDot:1
- if +MATCHED
- QUIT
- +120 ;
- +121 IF 'MATCHED
- Begin DoDot:1
- +122 ;if no data in IBZDATA(1) Quit to avoid undefined error - *597
- IF $GET(IBZDATA(1))=""
- QUIT
- +123 ; Because no matches, get the information from the 1st line item.
- DO GTPRCD(IBBNDL,.OPROC,.OREVCD,IBZDATA(1))
- +124 ; Mis-matched Proc Code.
- IF OPROC'=$SELECT('IBBNDL:$PIECE(IB0,U,3),1:$PIECE(IB0,U,10))
- SET ERRCOD=2
- End DoDot:1
- GOTO FINDLNX
- +125 ;
- +126 ; FOUND A MATCHING PROCEDURE CODE...SO LET'S SEE IF EVERYTHING ELSE MATCHES.
- +127 SET Z=MATCHED
- +128 ; Quit if processing an MRA and this VistA line# has already been filed
- +129 IF $PIECE($GET(^IBM(361.1,IBEOB,0)),U,4)=1
- IF $DATA(^IBM(361.1,IBEOB,15,"AC",Z))
- GOTO FINDLNX
- +130 ; Quit if split MRA and this VistA line# has already been filed
- +131 IF $DATA(IBZVLA(Z))
- GOTO FINDLNX
- +132 IF $GET(IBZDATA(Z))=""
- GOTO FINDLNX
- +133 ;
- +134 ; charge from bill
- SET OCHG=$PIECE(IBZDATA(Z),U,8)*$PIECE(IBZDATA(Z),U,9)
- +135 SET IBAMIN=""
- +136 ;anesthesia minutes
- IF $PIECE(IBZDATA(Z),U,12)'=""
- SET IBAMIN=$PIECE(IBZDATA(Z),U,12)
- +137 SET UNITS=$SELECT('IBAMIN:$PIECE(IBZDATA(Z),U,9),1:IBAMIN/15)
- +138 ; original units from bill or anesthesia minutes calculation
- +139 ; round to a single decimal place for fractional units
- IF $PIECE(UNITS,".",2)
- SET UNITS=$FNUMBER(UNITS,"",1)
- +140 IF $PIECE($PIECE(IB0,U,16),".",2)
- SET $PIECE(IB0,U,16)=$FNUMBER($PIECE(IB0,U,16),"",1)
- +141 ; just the units
- SET UNITS2=$PIECE(IBZDATA(Z),U,9)
- +142 ; UNITS3 is the number of anesthesia minutes divided by 10, or nil.
- +143 ; Solution to get around the Trailblazers bug for MRAs
- +144 SET UNITS3=""
- +145 IF IBAMIN'=0
- SET UNITS3=IBAMIN/10
- +146 ;
- +147 ; Original units
- IF UNITS'=$PIECE(IB0,U,16)
- IF UNITS2'=$PIECE(IB0,U,16)
- IF UNITS3'=$PIECE(IB0,U,16)
- IF IBAMIN'=$PIECE(IB0,U,16)
- SET ERRCOD=3
- GOTO FINDLNX
- +148 ; original charges.
- IF $$DOLLAR^IBCEFG1(OCHG)'=+$PIECE(IB0,U,15)
- SET ERRCOD=4
- GOTO FINDLNX
- +149 IF $SELECT($PIECE(IB0,U,19):$PIECE(IB0,U,19)=$PIECE(IBZDATA(Z),U),1:1)
- Begin DoDot:1
- +150 ;Original procedure/chg/units/date have matched in order to get here
- +151 ;Check matching original modifiers
- +152 ; modifiers.
- IF '$$MODMATCH($$MODLST^IBEFUNC2($PIECE(IBZDATA(Z),U,10)),$SELECT('IBBNDL:$PIECE(IB0,U,5,8),1:$PIECE(IB0,U,11,14)),.MOD837S)
- SET ERRCOD=5_U_MOD837S
- QUIT
- +153 SET IBLN=Z_$SELECT(IBBNDL:U_OPROC,1:"")
- End DoDot:1
- if +ERRCOD
- GOTO FINDLNX
- +154 IF 'IBLN
- IF IBLN1
- SET IBLN=IBLN1
- +155 ;
- FINDLNX ;
- +1 QUIT IBLN
- +2 ;
- GTPRCD(IBBNDL,OPROC,OREVCD,IBZREC) ; Set up the Procedure Code/Revenue Code fields.
- +1 NEW CPT
- +2 ;
- +3 ; For UB-04s
- IF $PIECE($GET(^DGCR(399,IBIFN,0)),U,19)=3
- Begin DoDot:1
- +4 ; proc from bill
- SET CPT=$PIECE(IBZREC,U,2)
- +5 ; non-numeric proc
- IF CPT'?.N
- IF CPT'=""
- SET CPT=$ORDER(^ICPT("B",CPT,""))
- +6 ; ext proc code
- SET OPROC=$$PRCD^IBCEF1(+CPT_";ICPT(")
- +7 ; Rev cd from bill
- SET OREVCD=+$PIECE($GET(^DGCR(399.2,+IBZREC,0)),U)
- End DoDot:1
- QUIT
- +8 ;
- +9 ; For CMS-1500s
- +10 ; proc from bill
- SET CPT=$PIECE(IBZREC,U,5)
- +11 ; non-numeric proc
- IF CPT'?.N
- IF CPT'=""
- SET CPT=$ORDER(^ICPT("B",CPT,""))
- +12 ; ext proc code
- SET OPROC=$$PRCD^IBCEF1(+CPT_";ICPT(")
- +13 QUIT
- +14 ;
- MODMATCH(IB,MODLST,MOD837S) ; Match modifiers
- +1 ; IB = the list of modifiers iens from the bill, comma delimited
- +2 ; MODLST = the 4 '^' pieces of the reported modifiers
- +3 ;
- +4 NEW MODOK,Q,Z0,IBMOD,MMOD
- +5 SET MODOK=1
- SET MOD837S=""
- +6 IF $TRANSLATE(IB,",")'=""
- FOR Q=1:1:$LENGTH(IB,",")
- SET Z0=$PIECE(IB,",",Q)
- IF Z0'=""
- Begin DoDot:1
- +7 SET IBMOD(Z0)=$GET(IBMOD(Z0))+1
- +8 IF '$LENGTH(MOD837S)
- SET MOD837S=Z0
- QUIT
- +9 SET MOD837S=MOD837S_","_Z0
- End DoDot:1
- +10 ; No modifiers used
- IF $TRANSLATE(MODLST,U)=""
- IF $ORDER(IBMOD(""))=""
- GOTO MODQ
- +11 ;
- +12 ; No match if no VistA modifiers, but there are MRA modifiers
- +13 IF $TRANSLATE(MODLST,U)'=""
- IF $ORDER(IBMOD(""))=""
- SET MODOK=0
- GOTO MODQ
- +14 ;
- +15 ; Evaluate each MRA modifier
- +16 FOR Z0=1:1:4
- Begin DoDot:1
- +17 ; individual MRA modifier
- SET MMOD=$PIECE(MODLST,U,Z0)
- if MMOD=""
- QUIT
- +18 ; not in array so just quit
- IF '$DATA(IBMOD(MMOD))
- QUIT
- +19 ; decrement array counter
- SET IBMOD(MMOD)=IBMOD(MMOD)-1
- +20 ; if 0, then kill array entry
- IF 'IBMOD(MMOD)
- KILL IBMOD(MMOD)
- +21 QUIT
- End DoDot:1
- +22 ;
- +23 ; All submitted mods not matched
- IF $ORDER(IBMOD(""))'=""
- SET MODOK=0
- MODQ QUIT MODOK
- +1 ;