IBECECU1 ;BSL/DVA-BILLING SEND/RECEIVE DFT HL7 MESSAGES PATIENT ACCUMULATOR INTERFACE - SEND/RECEIVE A DFT UPDATE TO/FROM OTHER SITES ; 08 Jul 2022 9:21 AM
;;2.0;INTEGRATED BILLING;**704,769**;21-MAR-94;Build 42
;Per VA Directive 6402, this routine should not be modified.
; This routine will manage the 365 Inpatient stay clock
;
;IA# Supports
;------ -------------------------------------------------
; Reference to $STARTMSG^HLOPRS,$$NEXTSEG^HLOPRS,$$GET^HLOPRS in ICR #4718
; Reference to $$ADDSEG^HLOAPI,SET^HLOAPI in ICR #4722
; Reference to $$SENDONE^HLOAPI1 in ICR #4717
; Reference to $$GETDFN^MPIF001 in ICR #2701
;
; ; ; This will fire off an update (active 365 day clock) entry in file #351,
; - First when a new entry (clock) is started
; - Every quarter when the income amounts are entered
; - then when the Pt is discharged.
;Sample message:
; MSH|^~\&|IBECEAC-SEND|537^HL7.CHICAGO-WEST.DOMAIN.EXT:5591^DNS|IBECEAC-RCV|200VDIF^:^DNS|20250507123217-0400||DFT^P03^DFT_P03|537 12661900|T^|2.3|||AL|NE|USA
; EVN|P03|20250507123217-0400
; PID|1||1013742761V568744||LNAME^FNAME
; FT1|537&4|20250201|1|100|15|0|0|100|20260131||||corrected
;
Q ;No direct routine calls
;
EN(DFN,IBCLDA,IBUPVRSN) ; OUTGOING DFT PRIMARY ENTRY POINT
; IBCLDA - IEN FROM 351
;CALLED FROM ^IBAUTL3 (CLADD [new] AND CLUPD [updates])
;IBCLDA = 351 ien
;IBUPVRSN = flag to determine if process should update clock version
N X,PARMS,SEG,MSG,VALUE,FIELD,QRYNUM,NAME,ERROR,XXX,WHOTO,IBACBCLK,IBADM,IBDISCH,IBADMIT,IBICN,IBQIEN,IBIEN
N IBCLDT,IBSTAT,IB901,IB902,IB903,IB904,IBCLDAY,IBCLNDT,IBNADM,IBNAME,IBSITE,IBSOC,IBECVRSN,IBVNUM,IBVRSN,IBTFL
;
S IBTFL=$$TFL^IBARXMU(DFN,.IBTFL,2) Q:'IBTFL ;Do not send DFT if patient is not in any other Treating Facilities, IB*2*769
I $P($G(^IBE(351,IBCLDA,1)),U,5)="" Q
I $$GET1^DIQ(351,IBCLDA_",",18,"I") Q ;Don't send DFT if clock is out of sync - IB*2*769
D INPT^IBECECX1(DFN) ;Get admit/discharge dates
S IBECVRSN=$$GET1^DIQ(351,IBCLDA_",",17) I IBECVRSN S IBVNUM=$P(IBECVRSN," ",2) D
.I $G(IBUPVRSN) S IBECVRSN=IBSTATION_" "_(IBVNUM+1),DA=IBCLDA,DIE="^IBE(351,",DR="17///^S X=IBECVRSN" D ^DIE ;Set version number - IB*2.0*769
I 'IBECVRSN S IBECVRSN=IBSTATION_" 1",DA=IBCLDA,DIE="^IBE(351,",DR="17///^S X=IBECVRSN" D ^DIE ;Set version number - IB*2.0*769
S NAME=$$GET1^DIQ(2,DFN_",",.01)
;S IBCORRECT=$S($D(IBCORRECT):IBCORRECT,1:"null")
D MSH,PARSE,EVN,PID Q:'IBICN ;Do not send Message if no Patient ICN
D FT1,SEND
Q
;
;
MSH ; Build outgoing MSH Segment
N PARMS K ^TMP("DFT")
S PARMS("COUNTRY")="USA"
S PARMS("MESSAGE TYPE")="DFT"
S PARMS("EVENT")="P03"
S PARMS("SENDING APPLICATION")="IBECEAC-SEND"
S PARMS("VERSION")="2.3"
S PARMS("MESSAGE STRUCTURE")="DFT_P03" ;IB*20*769 - Add message structure per VDIF request
S MSG="^TMP(DFT"
S X=$$NEWMSG^HLOAPI(.PARMS,.MSG,.ERROR)
Q
EVN ;
S VALUE="EVN",FIELD=0 D SET^HLOAPI(.SEG,VALUE,FIELD)
S VALUE="P03",FIELD=1 D SET^HLOAPI(.SEG,VALUE,FIELD)
D NOW^%DTC S %P1=% S VALUE=$$FMTHL7^XLFDT(%P1),FIELD=2
D SET^HLOAPI(.SEG,VALUE,FIELD)
S X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
Q
PID ; Build outgoing PID Segment
S VALUE="PID",FIELD=0 D SET^HLOAPI(.SEG,VALUE,FIELD)
D SET^HLOAPI(.SEG,1,1)
;Set ICN field
S IBICN=$$ICN^IBARXMU(DFN) Q:'IBICN ;Do not send Message if no Patient ICN
S VALUE=IBICN,FIELD=3
D SET^HLOAPI(.SEG,VALUE,FIELD)
;;Set Name
S NAME=$$GET1^DIQ(2,DFN_",",.01)
S VALUE=$P(NAME,",",1),FIELD=5 D SET^HLOAPI(.SEG,VALUE,FIELD,1)
S VALUE=$P(NAME,",",2),FIELD=5 D SET^HLOAPI(.SEG,VALUE,FIELD,2)
S X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
Q
;
FT1 ; Build FT1 Outgoing segment
D SET^HLOAPI(.SEG,"FT1",0)
I $G(IBSTN) D
.D SET^HLOAPI(.SEG,IBSTN,1,0) ;STATION # for Clock Version
.D SET^HLOAPI(.SEG,IBVRSN,1,0,2) ;incremental Clock Version
D SET^HLOAPI(.SEG,+IBCLDT,2) ;Billing clock begin date
D SET^HLOAPI(.SEG,+IBSTAT,3) ;Billing clock Status
D SET^HLOAPI(.SEG,+IB901,4) ;1ST QTR CHARGES
D SET^HLOAPI(.SEG,+IB902,5) ;2ND QTR CHARGES
D SET^HLOAPI(.SEG,+IB903,6) ;3RD QTR CHARGES
D SET^HLOAPI(.SEG,+IB904,7) ;4TH QTR CHARGES
D SET^HLOAPI(.SEG,+IBCLDAY,8) ;Number of Inpatient days
D SET^HLOAPI(.SEG,+IBCLNDT,9) ;End of 365 day clock
I $D(IBCORRECT) D SET^HLOAPI(.SEG,IBCORRECT,16) ;Corrected status
S X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
Q
SEND ;SEND MESSAGE AND QUIT
S WHOTO("RECEIVING APPLICATION")="IBECEAC-RCV"
S WHOTO("STATION NUMBER")="200VDIF"
S WHOTO("MIDDLEWARE LINK NAME")="IBECEC-DFT"
S PARMS("SENDING APPLICATION")="IBECEAC-SEND"
S PARMS("APP ACK RESPONSE")="DFTACK^IBECECU1"
S XXX=$$SENDONE^HLOAPI1(.MSG,.PARMS,.WHOTO,.ERROR)
Q
;
;-----------------------------------------------INCOMING DFT ------------------
RECV ; INCOMING DFT PRIMARY ENTRY POINT
N DFN,IBHDR,IBMSG,SEG,IBSEGT,IBSTAT,IBWHAT,ICN,MSGTYPE,IBIEN,DATEQ,ERR,IBAEVNT,IBEVOCC,IBQRYS,IBUPDT,IBISTN,IBIVRSN
N IBI901,IBI902,IBI903,IBI904,IBICKDT,IBICLDAY,IBICLDT,IBICNAL,IBISTAT,IBACTC,IBICNUM,IBDA,IBCBDT,IBSNDST,IBDA1,IBERROR
N IBFVRSN,IB351IEN
S ERR=0,IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,HLMSGIEN,.IBHDR)
S IBIEN=HLMSGIEN
I 'IBSTAT S IBERROR="Unable to start parse of message" D MSA Q
I "DFT"'[IBHDR("MESSAGE TYPE") S IBERROR="Incorrect message type" D MSA Q
;
F Q:'$$NEXTSEG^HLOPRS(.IBMSG,.SEG) S IBSEGT=$G(SEG("SEGMENT TYPE")) Q:IBSEGT="" D
. I IBSEGT="PID" D PIDI
. I IBSEGT="FT1" D FT1I
I 'DFN S IBERROR="Unable to find patient" D MSA Q
I '$G(IBICLDT) S IBERROR="DFT missing clock data" D MSA Q ;Quit if no billing clocks returned
S IBSNDST=$G(IBMSG("HDR","SENDING FACILITY",1))
S IBDA=";" F S IBDA=$O(^IBE(351,"AIVDT",DFN,-IBICLDT,IBDA),-1) Q:'IBDA Q:$G(IBCBDT) D
.Q:$$GET1^DIQ(351,IBDA_",",.04,"I")=3 ;IB*2.0*769 - Quit if clock found is Canceled
.S IBCBDT=$$GET1^DIQ(351,IBDA_",",.03,"I")
.S IBQRYS=$$GET1^DIQ(351,IBDA_",",16,"I")
.S IBDA1=IBDA
S IBUPDT=0
I $G(IBCBDT)=IBICLDT D Q ;Update record and send app ack if current Billing Clock Start Date matches incoming Billing Clock Start Date
.D UPDATE(IBDA1)
.I 'IBUPDT S IBERROR="Unable to update existing MEANS TEST BILLING CLOCK at remote site"
.D MSA
.Q
I $G(IBCBDT)'=IBICLDT D ;File data in 351 and send app ack
.D NEWREC
.I 'IBUPDT S IBERROR="Unable to create new MEANS TEST BILLING CLOCK at remote site"
.D MSA
Q
;
PIDI ;Parse Incoming PID Segment
;S IBICN=$$GET^HLOPRS(.SEG,1,1) ;Alternate Patient ID (DFN)
S IBICNAL=$$GET^HLOPRS(.SEG,3,1) ;Patient ICN
S DFN=$$DFN^IBARXMU(IBICNAL) ;Patient DFN
S IBNAME=$$GET^HLOPRS(.SEG,5,1) ;Pt name
Q
;Get data from HL7 message from QRD and DSP
FT1I ;Parse Incoming FT1 Segment, assumes one record only
; Get new 365 day clock data
S IBISTN=$$GET^HLOPRS(.SEG,1,0) ;Clock Version - Station Number
S IBIVRSN=$$GET^HLOPRS(.SEG,1,0,2) ;Clock Version #
S IBFVRSN=IBISTN_" "_IBIVRSN ;Full billing clock version
S IBICLDT=$$GET^HLOPRS(.SEG,2,1) ;Billing clock start date
S IBICLDT=$$HL7TFM^XLFDT(IBICLDT) ;convert HL7 date to FM
S IBISTAT=$$GET^HLOPRS(.SEG,3,1) ;Status of clock
S IBI901=$$GET^HLOPRS(.SEG,4,1) ;1ST QTR CHARGES
S IBI902=$$GET^HLOPRS(.SEG,5,1) ;2ND QTR CHARGES
S IBI903=$$GET^HLOPRS(.SEG,6,1) ;3RD QTR CHARGES
S IBI904=$$GET^HLOPRS(.SEG,7,1) ;4TH QTR CHARGES
S IBICLDAY=$$GET^HLOPRS(.SEG,8,1) ;Inpatient Days on the received clock
S IBICKDT=$$GET^HLOPRS(.SEG,9,1) ;Clock end date
S:IBICKDT IBICKDT=$$HL7TFM^XLFDT(IBICKDT) ;convert HL7 date to FM
I IBISTAT=1,IBICKDT,IBICKDT<DT S IBISTAT=2 ;IB*2.0*769 - Update Status to closed if clock end date is in the past
Q
PARSE ; Get the updated clock data to send via DFT
N IBARRAY,IBERR
; Get the values of the new IBE(351) entry
D GETS^DIQ(351,IBCLDA_",","**","I","IBARRAY","IBERR")
S IBSITE=$$SITE^IBATUTL ;Site number
S IBCLDT=IBARRAY(351,IBCLDA_",",.03,"I") ;Clock start date
S IBCLDT=$$FMTHL7^XLFDT(IBCLDT) ;convert HL7 date to FM
S IBSTAT=IBARRAY(351,IBCLDA_",",.04,"I") ;Status
S IB901=IBARRAY(351,IBCLDA_",",.05,"I") ;1st QTR CHARGES
S IB902=IBARRAY(351,IBCLDA_",",.06,"I") ;2nd QTR CHARGES
S IB903=IBARRAY(351,IBCLDA_",",.07,"I") ;3rd QTR CHARGES
S IB904=IBARRAY(351,IBCLDA_",",.08,"I") ;4th QTR CHARGES
S IBCLDAY=IBARRAY(351,IBCLDA_",",.09,"I") ;Number of inpatient days
S IBCLNDT=IBARRAY(351,IBCLDA_",",.1,"I") ;End date of the clock
I 'IBCLNDT S IBCLNDT=$$FMADD^XLFDT($$HL7TFM^XLFDT(IBCLDT),364) ;Calc Billing Clock end date when null
S IBCLNDT=$$FMTHL7^XLFDT(IBCLNDT) ;convert HL7 date to FM
S IBSTN=$P($$GET1^DIQ(351,IBCLDA_",",17)," ") ;Station Number
S IBVRSN=+$P($$GET1^DIQ(351,IBCLDA_",",17)," ",2) ;Billing Clock version number
Q
;
NEWREC ;Create a new entry in file 351
L +^IBE(351,0):$G(DILOCKTM,5) Q:'$T
N DIC,IBFDA,IEN,IENS,X,Y,IEN351,IBDUZ,IBDTUP,IBREASON,DIE,DA,DR,IBBEGDT
S DIC="^IBE(351,",DIC(0)=""
S X=$P($G(^IBE(351,+$P($G(^IBE(351,0)),U,3),0)),U,1)+1 ;IB*2.0*769 - Protect global for 1st entry into file
;IB*769 - IBECNIEN used in DSR response processing to update Clock Version if one doesn't currently exist
D FILE^DICN S (IENS,IEN)=$P(Y,U,1),(DA,IBECNIEN)=$P(Y,U,1) S IENS=IENS_","
;IBFDA(FILE#,"IENS",FIELD#)="VALUE"
I $G(IBICNAL)'="" S DFN=$$GETDFN^MPIF001(IBICNAL)
I DFN="" L -^IBE(351,0) Q
S IBFDA(351,IENS,.02)=DFN
;
;Need to do aggregation of incoming clock with local data on Query Responses (DSR)
I $G(IBAGG)=1 D AGGR ;Has this data been aggregated with local data
S IBBEGDT=IBICLDT S:$G(IBCBDT) IBBEGDT=$S(IBICLDT>IBCBDT:IBCBDT,1:IBICLDT) ;Use earlier date for new admission - IB*2.0*769
S IBFDA(351,IENS,.03)=$G(IBBEGDT)
S IEN351=0 F S IEN351=$O(^IBE(351,"ACT",DFN,IEN351)) Q:IEN351="" D ;loop through "current" clock xref
. Q:$G(IBICLNDT) ;Quit if incoming clock is closed
. I $$GET1^DIQ(351,IEN351_",",.04,"I")=1 D
.. S DIE="^IBE(351,",DA=IEN351,DR=".04///3;"
.. S IBDUZ=$G(DUZ,.5),DR=DR_";13////^S X=IBDUZ"
.. S IBDTUP=$$NOW^XLFDT,DR=DR_";14///^S X=IBDTUP",DR=DR_";14///^S X=IBDTUP"
.. I $G(IBCNT) S IBREASON=$S($G(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query"),DR=DR_";15///^S X=IBREASON"
.. I '$G(IBCNT) S IBREASON="Billing Clock update from Query"
.. D ^DIE ;Use fileman to properly delete ACT x-ref
.. K DIE,DA,DR
I $G(IBISTAT)'=2 S IBISTAT=$S(IBISTAT=3:3,'$G(IBICLNDT):1,$G(IBICLNDT)<=DT:2,1:1) ;IB*2.0*769 - calculate status
S IBFDA(351,IENS,.04)=$G(IBISTAT)
S IBFDA(351,IENS,.05)=$G(IBI901)
S IBFDA(351,IENS,.06)=$G(IBI902)
S IBFDA(351,IENS,.07)=$G(IBI903)
S IBFDA(351,IENS,.08)=$G(IBI904)
S IBFDA(351,IENS,.09)=$G(IBICLDAY)
S:$G(IBICKDT)<=DT IBFDA(351,IENS,.1)=IBICKDT
S IBFDA(351,IENS,15)=$S($G(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query")
S IBFDA(351,IENS,11)=.5
S IBFDA(351,IENS,12)=$$NOW^XLFDT
S IBFDA(351,IENS,13)=.5
S IBFDA(351,IENS,14)=$$NOW^XLFDT
S IBFDA(351,IENS,16)=1 ;Set query sent field for aggregated date stored
I $G(IBFVRSN) S IBFDA(351,IENS,17)=IBFVRSN
D FILE^DIE(,"IBFDA","IBERR")
I '$D(IBERR) S IBUPDT=1,IB351IEN=+IENS ;Update successful positive app ack
I $$GET1^DIQ(351,IENS,15)["-Edit Begin Date via CLOCK MAINT" S DIE="^IBE(351,",DA=$P(IENS,","),DR="15///@" D ^DIE ;IB*2.0*769 - Clear clock edit comment if still exists after update
L -^IBE(351,0)
;
AGGR ;Data has been aggregated at VDIF, but may not have taken into account local data
;
N NODE,IBDA,NODE0,AGG,IBSTDT,IBFLG,IBECLK,IBRCLK,IBSYCLK
S AGG=0
;1. If no active local clock quit
;2. If local active clock and the start dates are not the same, aggregate
;3. If local active clock and start dates are the same, and days inpatient are Less than query, aggregate
;4. If local active clock and start dates are the same, and days inpatient are greater than query, quit
;
;get local clock data (#351)
;S NODE=$S(IBICLNDT:-IBICLNDT_.9999,1:-DT_.9999)
;F S NODE=$O(^IBE(351,"AIVDT",DFN,NODE)) Q:'NODE Q:$G(IBFLG) D
;.S IBDA=";" F S IBDA=$O(^IBE(351,"AIVDT",DFN,NODE,IBDA),-1) Q:'IBDA I $P(^IBE(351,IBDA,0),U,4),$P(^IBE(351,IBDA,0),U,4)<3 S IBFLG=1 Q
;Q:'$G(IBDA)
Q:'$G(IB351IEN)
S NODE0=^IBE(351,IB351IEN,0)
;IB*2*769 - Remove start date check as clocks should still be aggregated
;Q:$P(NODE0,"^",3)<IBICLDT
S IBSTDT=$P(NODE0,"^",3) ;use earliest billing clock if local
I +$P(NODE0,"^",11)=IBICLDT S IBSYCLK=IBICLDT ;IB*2.0*769 - Use original clock date for incoming compare
I '$G(IBSYCLK) S IBSYCLK=IBSTDT
S IBECLK=IBSYCLK_U_$P(NODE0,U,5,9),IBRCLK=+IBICLDT_U_+IBI901_U_+IBI902_U_+IBI903_U_+IBI904_U_+IBICLDAY
I (IBECLK'=IBRCLK) S AGG=1
Q:'AGG
;I $G(IBICLNDT)<DT ;D MULTCLK - For future Cerner work
;Aggregate the incoming clock and the active clock
S IBICLDAY=IBICLDAY+($P(NODE0,"^",9))
S IBI901=IBI901+($P(NODE0,"^",5))
S IBI902=IBI902+($P(NODE0,"^",6))
S IBI903=IBI903+($P(NODE0,"^",7))
S IBI904=IBI904+($P(NODE0,"^",8))
I IBSTDT<IBICLDT S IBICLDT=IBSTDT ;use earliest billing clock if local
Q
;
UPDATE(IBDA) ;Update records when Billing Clock start date is the same
N DIE,DA,IBDTUP,IBDUZ,IBBEGDT
I $G(IBAGG)=1 D AGGR ;Local data needs to be aggregated with incoming clocks to update clock date if needed
S IBBEGDT=IBICLDT S:$G(IBCBDT) IBBEGDT=$S(IBICLDT>IBCBDT:IBCBDT,1:IBICLDT) ;Use earlier date for new admission - IB*2.0*769
L +^IBE(351,IBDA):$G(DILOCKTM,5) Q:'$T
S DIE="^IBE(351,",DA=IBDA,DR=".03///^S X=IBBEGDT"
I $G(IBISTAT)'=2 S IBISTAT=$S(IBISTAT=3:3,'$G(IBICLNDT):1,$G(IBICLNDT)<=DT:2,1:1) ;IB*2.0*769 - calculate status
S DR=DR_";.04///^S X=IBISTAT"
S DR=DR_";.05///"_+IBI901
S DR=DR_";.06///"_+IBI902
S DR=DR_";.07///"_+IBI903
S DR=DR_";.08///"_+IBI904
S DR=DR_";.09///"_+IBICLDAY
S:IBICKDT<=DT DR=DR_";.1///^S X=IBICKDT"
S IBDUZ=$G(DUZ,.5),DR=DR_";13////^S X=IBDUZ"
S IBDTUP=$$NOW^XLFDT,DR=DR_";14///^S X=IBDTUP"
S IBREASON=$S($G(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query"),DR=DR_";15///^S X=IBREASON"
S DR=DR_";16///1" ;Set query sent field for aggregated date stored
I $G(IBFVRSN) S DR=DR_";17///^S X=IBFVRSN"
D ^DIE
I $$GET1^DIQ(351,IBDA_",",15)["-Edit Begin Date via CLOCK MAINT" S DIE="^IBE(351,",DA=IBDA,DR="15///@" D ^DIE ;IB*2.0*769 - Clear clock edit comment if still exists after update
L -^IBE(351,DA)
S IBUPDT=1
Q
MSA ;Build and send App Ack
;RRA IB*2*769
I IBSNDST=$$GCRNSITE^VAFCCRNR Q ;Don't send Ack for Cerner sites
N IBPARMS,IBACK,IBERR,IBX
S IBPARMS("ACK CODE")=$S('$D(IBERROR):"AA",1:"AE")
I $D(IBERROR) S IBPARMS("ERROR MESSAGE")=$G(IBERROR)
S IBPARMS("MESSAGE TYPE")="ACK"
S IBPARMS("COUNTRY")="USA"
S IBPARMS("VERSION")="2.3"
S IBX=$$ACK^HLOAPI2(.IBMSG,.IBPARMS,.IBACK,.IBERR)
S IBX=$$SENDACK^HLOAPI2(.IBACK,.IBERR)
Q
;
DFTACK ;process app ack
;IB*2*769
;MSH|^~\&|IBECEAC-RCV|554^HL7.DENVER.DOMAIN.EXT:5754^DNS|IBECEAC-SEND|537^HL7.CHICAGO-WEST.DOMAIN.EXT:5591^DNS|20250513145255-0600||ACK^P03^ACK|554 22000060|T^|2.3|||AL|NE|USA
;MSA|AE|537 12661932|Unable to update existing MEANS TEST BILLING CLOCK at remote site
N IBSTAT,IBHDR,IBSEG,IBACK,IBID,IBERR,IBERRS,IB351IEN,IB778,IBICLDTS,IBCLDAU
S IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,HLMSGIEN,.IBHDR)
Q:'$$NEXTSEG^HLOPRS(.IBMSG,.IBSEG)
S IBACK=$$GET^HLOPRS(.IBSEG,1,1)
;ONLY PROCESS NEGATIVE ACK'S - QUIT IF AA
Q:IBACK="AA"
;GET MESSAGE ID
S IBID=$$GET^HLOPRS(.IBSEG,2,1)
;MESSAGE SHOULD ONLY BE GENERATED FOR SITE THAT SENT THE DFT
;IF THIS SITE IS NOT THE SITE THAT SENT THE DFT THEN QUIT PROCESSING
Q:'+IBID=$P($$SITE^VASITE,"^",3)
;GET ERROR AND SITE
S IBERR=$$GET^HLOPRS(.IBSEG,3,1) ;error message
S IBERRS=+IBMSG("HDR","SENDING FACILITY",1) ;station sending the error back
D GETDET
D ERR1^IBECECX1(IBERR)
;UPDATE SYNC ERROR FIELD TO PREVENT BILLING EVENTS
I +IB351IEN D
.L +^IBE(351,IB351IEN):$G(DILOCKTM,5) Q:'$T
.S DIE="^IBE(351,",DA=IB351IEN,DR="18///1" D ^DIE
.L -^IBE(351,IB351IEN)
Q
GETDET ;get outgoing DFT details based on returned App Ack Message ID
N IB778,IBSTAT,IBMSG,IBHDR,SEG
S IB778=$P(IBID," ",2) ;OUTGOING DFT 778 IEN
S IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,IB778,.IBHDR)
F Q:'$$NEXTSEG^HLOPRS(.IBMSG,.SEG) S IBSEGT=$G(SEG("SEGMENT TYPE")) Q:IBSEGT="" D
. I IBSEGT="PID" D PIDI
. I IBSEGT="FT1" D FT1I
S IBICLDTS=IBICLDT ;CLOCK START DATE FOR ERROR MESSAGE
S IBCLDAU=IBFVRSN ;CLOCK VERSION FOR ERROR MESSAGE
D INPT^IBECECX1(DFN) ;Get inpatient admit data
S IB351IEN=$$GETIEN^IBECECX1(DFN,IBICLDTS) ;GET CLOCK IEN USING CLOCK BEGIN DATE AND PT DFN
I $$GET1^DIQ(351,IB351IEN_",",17)'=IBCLDAU S IB351IEN="UNABLE TO IDENTIFY BILLING CLOCK IEN" ;MISMATCH IN VERSION INFO - PASS BACK MESSAGE
Q
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HIBECECU1 16977 printed Sep 23, 2025@19:57:54 Page 2
IBECECU1 ;BSL/DVA-BILLING SEND/RECEIVE DFT HL7 MESSAGES PATIENT ACCUMULATOR INTERFACE - SEND/RECEIVE A DFT UPDATE TO/FROM OTHER SITES ; 08 Jul 2022 9:21 AM
+1 ;;2.0;INTEGRATED BILLING;**704,769**;21-MAR-94;Build 42
+2 ;Per VA Directive 6402, this routine should not be modified.
+3 ; This routine will manage the 365 Inpatient stay clock
+4 ;
+5 ;IA# Supports
+6 ;------ -------------------------------------------------
+7 ; Reference to $STARTMSG^HLOPRS,$$NEXTSEG^HLOPRS,$$GET^HLOPRS in ICR #4718
+8 ; Reference to $$ADDSEG^HLOAPI,SET^HLOAPI in ICR #4722
+9 ; Reference to $$SENDONE^HLOAPI1 in ICR #4717
+10 ; Reference to $$GETDFN^MPIF001 in ICR #2701
+11 ;
+12 ; ; ; This will fire off an update (active 365 day clock) entry in file #351,
+13 ; - First when a new entry (clock) is started
+14 ; - Every quarter when the income amounts are entered
+15 ; - then when the Pt is discharged.
+16 ;Sample message:
+17 ; MSH|^~\&|IBECEAC-SEND|537^HL7.CHICAGO-WEST.DOMAIN.EXT:5591^DNS|IBECEAC-RCV|200VDIF^:^DNS|20250507123217-0400||DFT^P03^DFT_P03|537 12661900|T^|2.3|||AL|NE|USA
+18 ; EVN|P03|20250507123217-0400
+19 ; PID|1||1013742761V568744||LNAME^FNAME
+20 ; FT1|537&4|20250201|1|100|15|0|0|100|20260131||||corrected
+21 ;
+22 ;No direct routine calls
QUIT
+23 ;
EN(DFN,IBCLDA,IBUPVRSN) ; OUTGOING DFT PRIMARY ENTRY POINT
+1 ; IBCLDA - IEN FROM 351
+2 ;CALLED FROM ^IBAUTL3 (CLADD [new] AND CLUPD [updates])
+3 ;IBCLDA = 351 ien
+4 ;IBUPVRSN = flag to determine if process should update clock version
+5 NEW X,PARMS,SEG,MSG,VALUE,FIELD,QRYNUM,NAME,ERROR,XXX,WHOTO,IBACBCLK,IBADM,IBDISCH,IBADMIT,IBICN,IBQIEN,IBIEN
+6 NEW IBCLDT,IBSTAT,IB901,IB902,IB903,IB904,IBCLDAY,IBCLNDT,IBNADM,IBNAME,IBSITE,IBSOC,IBECVRSN,IBVNUM,IBVRSN,IBTFL
+7 ;
+8 ;Do not send DFT if patient is not in any other Treating Facilities, IB*2*769
SET IBTFL=$$TFL^IBARXMU(DFN,.IBTFL,2)
if 'IBTFL
QUIT
+9 IF $PIECE($GET(^IBE(351,IBCLDA,1)),U,5)=""
QUIT
+10 ;Don't send DFT if clock is out of sync - IB*2*769
IF $$GET1^DIQ(351,IBCLDA_",",18,"I")
QUIT
+11 ;Get admit/discharge dates
DO INPT^IBECECX1(DFN)
+12 SET IBECVRSN=$$GET1^DIQ(351,IBCLDA_",",17)
IF IBECVRSN
SET IBVNUM=$PIECE(IBECVRSN," ",2)
Begin DoDot:1
+13 ;Set version number - IB*2.0*769
IF $GET(IBUPVRSN)
SET IBECVRSN=IBSTATION_" "_(IBVNUM+1)
SET DA=IBCLDA
SET DIE="^IBE(351,"
SET DR="17///^S X=IBECVRSN"
DO ^DIE
End DoDot:1
+14 ;Set version number - IB*2.0*769
IF 'IBECVRSN
SET IBECVRSN=IBSTATION_" 1"
SET DA=IBCLDA
SET DIE="^IBE(351,"
SET DR="17///^S X=IBECVRSN"
DO ^DIE
+15 SET NAME=$$GET1^DIQ(2,DFN_",",.01)
+16 ;S IBCORRECT=$S($D(IBCORRECT):IBCORRECT,1:"null")
+17 ;Do not send Message if no Patient ICN
DO MSH
DO PARSE
DO EVN
DO PID
if 'IBICN
QUIT
+18 DO FT1
DO SEND
+19 QUIT
+20 ;
+21 ;
MSH ; Build outgoing MSH Segment
+1 NEW PARMS
KILL ^TMP("DFT")
+2 SET PARMS("COUNTRY")="USA"
+3 SET PARMS("MESSAGE TYPE")="DFT"
+4 SET PARMS("EVENT")="P03"
+5 SET PARMS("SENDING APPLICATION")="IBECEAC-SEND"
+6 SET PARMS("VERSION")="2.3"
+7 ;IB*20*769 - Add message structure per VDIF request
SET PARMS("MESSAGE STRUCTURE")="DFT_P03"
+8 SET MSG="^TMP(DFT"
+9 SET X=$$NEWMSG^HLOAPI(.PARMS,.MSG,.ERROR)
+10 QUIT
EVN ;
+1 SET VALUE="EVN"
SET FIELD=0
DO SET^HLOAPI(.SEG,VALUE,FIELD)
+2 SET VALUE="P03"
SET FIELD=1
DO SET^HLOAPI(.SEG,VALUE,FIELD)
+3 DO NOW^%DTC
SET %P1=%
SET VALUE=$$FMTHL7^XLFDT(%P1)
SET FIELD=2
+4 DO SET^HLOAPI(.SEG,VALUE,FIELD)
+5 SET X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
+6 QUIT
PID ; Build outgoing PID Segment
+1 SET VALUE="PID"
SET FIELD=0
DO SET^HLOAPI(.SEG,VALUE,FIELD)
+2 DO SET^HLOAPI(.SEG,1,1)
+3 ;Set ICN field
+4 ;Do not send Message if no Patient ICN
SET IBICN=$$ICN^IBARXMU(DFN)
if 'IBICN
QUIT
+5 SET VALUE=IBICN
SET FIELD=3
+6 DO SET^HLOAPI(.SEG,VALUE,FIELD)
+7 ;;Set Name
+8 SET NAME=$$GET1^DIQ(2,DFN_",",.01)
+9 SET VALUE=$PIECE(NAME,",",1)
SET FIELD=5
DO SET^HLOAPI(.SEG,VALUE,FIELD,1)
+10 SET VALUE=$PIECE(NAME,",",2)
SET FIELD=5
DO SET^HLOAPI(.SEG,VALUE,FIELD,2)
+11 SET X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
+12 QUIT
+13 ;
FT1 ; Build FT1 Outgoing segment
+1 DO SET^HLOAPI(.SEG,"FT1",0)
+2 IF $GET(IBSTN)
Begin DoDot:1
+3 ;STATION # for Clock Version
DO SET^HLOAPI(.SEG,IBSTN,1,0)
+4 ;incremental Clock Version
DO SET^HLOAPI(.SEG,IBVRSN,1,0,2)
End DoDot:1
+5 ;Billing clock begin date
DO SET^HLOAPI(.SEG,+IBCLDT,2)
+6 ;Billing clock Status
DO SET^HLOAPI(.SEG,+IBSTAT,3)
+7 ;1ST QTR CHARGES
DO SET^HLOAPI(.SEG,+IB901,4)
+8 ;2ND QTR CHARGES
DO SET^HLOAPI(.SEG,+IB902,5)
+9 ;3RD QTR CHARGES
DO SET^HLOAPI(.SEG,+IB903,6)
+10 ;4TH QTR CHARGES
DO SET^HLOAPI(.SEG,+IB904,7)
+11 ;Number of Inpatient days
DO SET^HLOAPI(.SEG,+IBCLDAY,8)
+12 ;End of 365 day clock
DO SET^HLOAPI(.SEG,+IBCLNDT,9)
+13 ;Corrected status
IF $DATA(IBCORRECT)
DO SET^HLOAPI(.SEG,IBCORRECT,16)
+14 SET X=$$ADDSEG^HLOAPI(.MSG,.SEG,.ERROR)
+15 QUIT
SEND ;SEND MESSAGE AND QUIT
+1 SET WHOTO("RECEIVING APPLICATION")="IBECEAC-RCV"
+2 SET WHOTO("STATION NUMBER")="200VDIF"
+3 SET WHOTO("MIDDLEWARE LINK NAME")="IBECEC-DFT"
+4 SET PARMS("SENDING APPLICATION")="IBECEAC-SEND"
+5 SET PARMS("APP ACK RESPONSE")="DFTACK^IBECECU1"
+6 SET XXX=$$SENDONE^HLOAPI1(.MSG,.PARMS,.WHOTO,.ERROR)
+7 QUIT
+8 ;
+9 ;-----------------------------------------------INCOMING DFT ------------------
RECV ; INCOMING DFT PRIMARY ENTRY POINT
+1 NEW DFN,IBHDR,IBMSG,SEG,IBSEGT,IBSTAT,IBWHAT,ICN,MSGTYPE,IBIEN,DATEQ,ERR,IBAEVNT,IBEVOCC,IBQRYS,IBUPDT,IBISTN,IBIVRSN
+2 NEW IBI901,IBI902,IBI903,IBI904,IBICKDT,IBICLDAY,IBICLDT,IBICNAL,IBISTAT,IBACTC,IBICNUM,IBDA,IBCBDT,IBSNDST,IBDA1,IBERROR
+3 NEW IBFVRSN,IB351IEN
+4 SET ERR=0
SET IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,HLMSGIEN,.IBHDR)
+5 SET IBIEN=HLMSGIEN
+6 IF 'IBSTAT
SET IBERROR="Unable to start parse of message"
DO MSA
QUIT
+7 IF "DFT"'[IBHDR("MESSAGE TYPE")
SET IBERROR="Incorrect message type"
DO MSA
QUIT
+8 ;
+9 FOR
if '$$NEXTSEG^HLOPRS(.IBMSG,.SEG)
QUIT
SET IBSEGT=$GET(SEG("SEGMENT TYPE"))
if IBSEGT=""
QUIT
Begin DoDot:1
+10 IF IBSEGT="PID"
DO PIDI
+11 IF IBSEGT="FT1"
DO FT1I
End DoDot:1
+12 IF 'DFN
SET IBERROR="Unable to find patient"
DO MSA
QUIT
+13 ;Quit if no billing clocks returned
IF '$GET(IBICLDT)
SET IBERROR="DFT missing clock data"
DO MSA
QUIT
+14 SET IBSNDST=$GET(IBMSG("HDR","SENDING FACILITY",1))
+15 SET IBDA=";"
FOR
SET IBDA=$ORDER(^IBE(351,"AIVDT",DFN,-IBICLDT,IBDA),-1)
if 'IBDA
QUIT
if $GET(IBCBDT)
QUIT
Begin DoDot:1
+16 ;IB*2.0*769 - Quit if clock found is Canceled
if $$GET1^DIQ(351,IBDA_",",.04,"I")=3
QUIT
+17 SET IBCBDT=$$GET1^DIQ(351,IBDA_",",.03,"I")
+18 SET IBQRYS=$$GET1^DIQ(351,IBDA_",",16,"I")
+19 SET IBDA1=IBDA
End DoDot:1
+20 SET IBUPDT=0
+21 ;Update record and send app ack if current Billing Clock Start Date matches incoming Billing Clock Start Date
IF $GET(IBCBDT)=IBICLDT
Begin DoDot:1
+22 DO UPDATE(IBDA1)
+23 IF 'IBUPDT
SET IBERROR="Unable to update existing MEANS TEST BILLING CLOCK at remote site"
+24 DO MSA
+25 QUIT
End DoDot:1
QUIT
+26 ;File data in 351 and send app ack
IF $GET(IBCBDT)'=IBICLDT
Begin DoDot:1
+27 DO NEWREC
+28 IF 'IBUPDT
SET IBERROR="Unable to create new MEANS TEST BILLING CLOCK at remote site"
+29 DO MSA
End DoDot:1
+30 QUIT
+31 ;
PIDI ;Parse Incoming PID Segment
+1 ;S IBICN=$$GET^HLOPRS(.SEG,1,1) ;Alternate Patient ID (DFN)
+2 ;Patient ICN
SET IBICNAL=$$GET^HLOPRS(.SEG,3,1)
+3 ;Patient DFN
SET DFN=$$DFN^IBARXMU(IBICNAL)
+4 ;Pt name
SET IBNAME=$$GET^HLOPRS(.SEG,5,1)
+5 QUIT
+6 ;Get data from HL7 message from QRD and DSP
FT1I ;Parse Incoming FT1 Segment, assumes one record only
+1 ; Get new 365 day clock data
+2 ;Clock Version - Station Number
SET IBISTN=$$GET^HLOPRS(.SEG,1,0)
+3 ;Clock Version #
SET IBIVRSN=$$GET^HLOPRS(.SEG,1,0,2)
+4 ;Full billing clock version
SET IBFVRSN=IBISTN_" "_IBIVRSN
+5 ;Billing clock start date
SET IBICLDT=$$GET^HLOPRS(.SEG,2,1)
+6 ;convert HL7 date to FM
SET IBICLDT=$$HL7TFM^XLFDT(IBICLDT)
+7 ;Status of clock
SET IBISTAT=$$GET^HLOPRS(.SEG,3,1)
+8 ;1ST QTR CHARGES
SET IBI901=$$GET^HLOPRS(.SEG,4,1)
+9 ;2ND QTR CHARGES
SET IBI902=$$GET^HLOPRS(.SEG,5,1)
+10 ;3RD QTR CHARGES
SET IBI903=$$GET^HLOPRS(.SEG,6,1)
+11 ;4TH QTR CHARGES
SET IBI904=$$GET^HLOPRS(.SEG,7,1)
+12 ;Inpatient Days on the received clock
SET IBICLDAY=$$GET^HLOPRS(.SEG,8,1)
+13 ;Clock end date
SET IBICKDT=$$GET^HLOPRS(.SEG,9,1)
+14 ;convert HL7 date to FM
if IBICKDT
SET IBICKDT=$$HL7TFM^XLFDT(IBICKDT)
+15 ;IB*2.0*769 - Update Status to closed if clock end date is in the past
IF IBISTAT=1
IF IBICKDT
IF IBICKDT<DT
SET IBISTAT=2
+16 QUIT
PARSE ; Get the updated clock data to send via DFT
+1 NEW IBARRAY,IBERR
+2 ; Get the values of the new IBE(351) entry
+3 DO GETS^DIQ(351,IBCLDA_",","**","I","IBARRAY","IBERR")
+4 ;Site number
SET IBSITE=$$SITE^IBATUTL
+5 ;Clock start date
SET IBCLDT=IBARRAY(351,IBCLDA_",",.03,"I")
+6 ;convert HL7 date to FM
SET IBCLDT=$$FMTHL7^XLFDT(IBCLDT)
+7 ;Status
SET IBSTAT=IBARRAY(351,IBCLDA_",",.04,"I")
+8 ;1st QTR CHARGES
SET IB901=IBARRAY(351,IBCLDA_",",.05,"I")
+9 ;2nd QTR CHARGES
SET IB902=IBARRAY(351,IBCLDA_",",.06,"I")
+10 ;3rd QTR CHARGES
SET IB903=IBARRAY(351,IBCLDA_",",.07,"I")
+11 ;4th QTR CHARGES
SET IB904=IBARRAY(351,IBCLDA_",",.08,"I")
+12 ;Number of inpatient days
SET IBCLDAY=IBARRAY(351,IBCLDA_",",.09,"I")
+13 ;End date of the clock
SET IBCLNDT=IBARRAY(351,IBCLDA_",",.1,"I")
+14 ;Calc Billing Clock end date when null
IF 'IBCLNDT
SET IBCLNDT=$$FMADD^XLFDT($$HL7TFM^XLFDT(IBCLDT),364)
+15 ;convert HL7 date to FM
SET IBCLNDT=$$FMTHL7^XLFDT(IBCLNDT)
+16 ;Station Number
SET IBSTN=$PIECE($$GET1^DIQ(351,IBCLDA_",",17)," ")
+17 ;Billing Clock version number
SET IBVRSN=+$PIECE($$GET1^DIQ(351,IBCLDA_",",17)," ",2)
+18 QUIT
+19 ;
NEWREC ;Create a new entry in file 351
+1 LOCK +^IBE(351,0):$GET(DILOCKTM,5)
if '$TEST
QUIT
+2 NEW DIC,IBFDA,IEN,IENS,X,Y,IEN351,IBDUZ,IBDTUP,IBREASON,DIE,DA,DR,IBBEGDT
+3 SET DIC="^IBE(351,"
SET DIC(0)=""
+4 ;IB*2.0*769 - Protect global for 1st entry into file
SET X=$PIECE($GET(^IBE(351,+$PIECE($GET(^IBE(351,0)),U,3),0)),U,1)+1
+5 ;IB*769 - IBECNIEN used in DSR response processing to update Clock Version if one doesn't currently exist
+6 DO FILE^DICN
SET (IENS,IEN)=$PIECE(Y,U,1)
SET (DA,IBECNIEN)=$PIECE(Y,U,1)
SET IENS=IENS_","
+7 ;IBFDA(FILE#,"IENS",FIELD#)="VALUE"
+8 IF $GET(IBICNAL)'=""
SET DFN=$$GETDFN^MPIF001(IBICNAL)
+9 IF DFN=""
LOCK -^IBE(351,0)
QUIT
+10 SET IBFDA(351,IENS,.02)=DFN
+11 ;
+12 ;Need to do aggregation of incoming clock with local data on Query Responses (DSR)
+13 ;Has this data been aggregated with local data
IF $GET(IBAGG)=1
DO AGGR
+14 ;Use earlier date for new admission - IB*2.0*769
SET IBBEGDT=IBICLDT
if $GET(IBCBDT)
SET IBBEGDT=$SELECT(IBICLDT>IBCBDT:IBCBDT,1:IBICLDT)
+15 SET IBFDA(351,IENS,.03)=$GET(IBBEGDT)
+16 ;loop through "current" clock xref
SET IEN351=0
FOR
SET IEN351=$ORDER(^IBE(351,"ACT",DFN,IEN351))
if IEN351=""
QUIT
Begin DoDot:1
+17 ;Quit if incoming clock is closed
if $GET(IBICLNDT)
QUIT
+18 IF $$GET1^DIQ(351,IEN351_",",.04,"I")=1
Begin DoDot:2
+19 SET DIE="^IBE(351,"
SET DA=IEN351
SET DR=".04///3;"
+20 SET IBDUZ=$GET(DUZ,.5)
SET DR=DR_";13////^S X=IBDUZ"
+21 SET IBDTUP=$$NOW^XLFDT
SET DR=DR_";14///^S X=IBDTUP"
SET DR=DR_";14///^S X=IBDTUP"
+22 IF $GET(IBCNT)
SET IBREASON=$SELECT($GET(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query")
SET DR=DR_";15///^S X=IBREASON"
+23 IF '$GET(IBCNT)
SET IBREASON="Billing Clock update from Query"
+24 ;Use fileman to properly delete ACT x-ref
DO ^DIE
+25 KILL DIE,DA,DR
End DoDot:2
End DoDot:1
+26 ;IB*2.0*769 - calculate status
IF $GET(IBISTAT)'=2
SET IBISTAT=$SELECT(IBISTAT=3:3,'$GET(IBICLNDT):1,$GET(IBICLNDT)<=DT:2,1:1)
+27 SET IBFDA(351,IENS,.04)=$GET(IBISTAT)
+28 SET IBFDA(351,IENS,.05)=$GET(IBI901)
+29 SET IBFDA(351,IENS,.06)=$GET(IBI902)
+30 SET IBFDA(351,IENS,.07)=$GET(IBI903)
+31 SET IBFDA(351,IENS,.08)=$GET(IBI904)
+32 SET IBFDA(351,IENS,.09)=$GET(IBICLDAY)
+33 if $GET(IBICKDT)<=DT
SET IBFDA(351,IENS,.1)=IBICKDT
+34 SET IBFDA(351,IENS,15)=$SELECT($GET(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query")
+35 SET IBFDA(351,IENS,11)=.5
+36 SET IBFDA(351,IENS,12)=$$NOW^XLFDT
+37 SET IBFDA(351,IENS,13)=.5
+38 SET IBFDA(351,IENS,14)=$$NOW^XLFDT
+39 ;Set query sent field for aggregated date stored
SET IBFDA(351,IENS,16)=1
+40 IF $GET(IBFVRSN)
SET IBFDA(351,IENS,17)=IBFVRSN
+41 DO FILE^DIE(,"IBFDA","IBERR")
+42 ;Update successful positive app ack
IF '$DATA(IBERR)
SET IBUPDT=1
SET IB351IEN=+IENS
+43 ;IB*2.0*769 - Clear clock edit comment if still exists after update
IF $$GET1^DIQ(351,IENS,15)["-Edit Begin Date via CLOCK MAINT"
SET DIE="^IBE(351,"
SET DA=$PIECE(IENS,",")
SET DR="15///@"
DO ^DIE
+44 LOCK -^IBE(351,0)
+45 ;
AGGR ;Data has been aggregated at VDIF, but may not have taken into account local data
+1 ;
+2 NEW NODE,IBDA,NODE0,AGG,IBSTDT,IBFLG,IBECLK,IBRCLK,IBSYCLK
+3 SET AGG=0
+4 ;1. If no active local clock quit
+5 ;2. If local active clock and the start dates are not the same, aggregate
+6 ;3. If local active clock and start dates are the same, and days inpatient are Less than query, aggregate
+7 ;4. If local active clock and start dates are the same, and days inpatient are greater than query, quit
+8 ;
+9 ;get local clock data (#351)
+10 ;S NODE=$S(IBICLNDT:-IBICLNDT_.9999,1:-DT_.9999)
+11 ;F S NODE=$O(^IBE(351,"AIVDT",DFN,NODE)) Q:'NODE Q:$G(IBFLG) D
+12 ;.S IBDA=";" F S IBDA=$O(^IBE(351,"AIVDT",DFN,NODE,IBDA),-1) Q:'IBDA I $P(^IBE(351,IBDA,0),U,4),$P(^IBE(351,IBDA,0),U,4)<3 S IBFLG=1 Q
+13 ;Q:'$G(IBDA)
+14 if '$GET(IB351IEN)
QUIT
+15 SET NODE0=^IBE(351,IB351IEN,0)
+16 ;IB*2*769 - Remove start date check as clocks should still be aggregated
+17 ;Q:$P(NODE0,"^",3)<IBICLDT
+18 ;use earliest billing clock if local
SET IBSTDT=$PIECE(NODE0,"^",3)
+19 ;IB*2.0*769 - Use original clock date for incoming compare
IF +$PIECE(NODE0,"^",11)=IBICLDT
SET IBSYCLK=IBICLDT
+20 IF '$GET(IBSYCLK)
SET IBSYCLK=IBSTDT
+21 SET IBECLK=IBSYCLK_U_$PIECE(NODE0,U,5,9)
SET IBRCLK=+IBICLDT_U_+IBI901_U_+IBI902_U_+IBI903_U_+IBI904_U_+IBICLDAY
+22 IF (IBECLK'=IBRCLK)
SET AGG=1
+23 if 'AGG
QUIT
+24 ;I $G(IBICLNDT)<DT ;D MULTCLK - For future Cerner work
+25 ;Aggregate the incoming clock and the active clock
+26 SET IBICLDAY=IBICLDAY+($PIECE(NODE0,"^",9))
+27 SET IBI901=IBI901+($PIECE(NODE0,"^",5))
+28 SET IBI902=IBI902+($PIECE(NODE0,"^",6))
+29 SET IBI903=IBI903+($PIECE(NODE0,"^",7))
+30 SET IBI904=IBI904+($PIECE(NODE0,"^",8))
+31 ;use earliest billing clock if local
IF IBSTDT<IBICLDT
SET IBICLDT=IBSTDT
+32 QUIT
+33 ;
UPDATE(IBDA) ;Update records when Billing Clock start date is the same
+1 NEW DIE,DA,IBDTUP,IBDUZ,IBBEGDT
+2 ;Local data needs to be aggregated with incoming clocks to update clock date if needed
IF $GET(IBAGG)=1
DO AGGR
+3 ;Use earlier date for new admission - IB*2.0*769
SET IBBEGDT=IBICLDT
if $GET(IBCBDT)
SET IBBEGDT=$SELECT(IBICLDT>IBCBDT:IBCBDT,1:IBICLDT)
+4 LOCK +^IBE(351,IBDA):$GET(DILOCKTM,5)
if '$TEST
QUIT
+5 SET DIE="^IBE(351,"
SET DA=IBDA
SET DR=".03///^S X=IBBEGDT"
+6 ;IB*2.0*769 - calculate status
IF $GET(IBISTAT)'=2
SET IBISTAT=$SELECT(IBISTAT=3:3,'$GET(IBICLNDT):1,$GET(IBICLNDT)<=DT:2,1:1)
+7 SET DR=DR_";.04///^S X=IBISTAT"
+8 SET DR=DR_";.05///"_+IBI901
+9 SET DR=DR_";.06///"_+IBI902
+10 SET DR=DR_";.07///"_+IBI903
+11 SET DR=DR_";.08///"_+IBI904
+12 SET DR=DR_";.09///"_+IBICLDAY
+13 if IBICKDT<=DT
SET DR=DR_";.1///^S X=IBICKDT"
+14 SET IBDUZ=$GET(DUZ,.5)
SET DR=DR_";13////^S X=IBDUZ"
+15 SET IBDTUP=$$NOW^XLFDT
SET DR=DR_";14///^S X=IBDTUP"
+16 SET IBREASON=$SELECT($GET(IBSNDST)'="":"Billing Clock update from Sta #"_IBSNDST,1:"Billing Clock update from Query")
SET DR=DR_";15///^S X=IBREASON"
+17 ;Set query sent field for aggregated date stored
SET DR=DR_";16///1"
+18 IF $GET(IBFVRSN)
SET DR=DR_";17///^S X=IBFVRSN"
+19 DO ^DIE
+20 ;IB*2.0*769 - Clear clock edit comment if still exists after update
IF $$GET1^DIQ(351,IBDA_",",15)["-Edit Begin Date via CLOCK MAINT"
SET DIE="^IBE(351,"
SET DA=IBDA
SET DR="15///@"
DO ^DIE
+21 LOCK -^IBE(351,DA)
+22 SET IBUPDT=1
+23 QUIT
MSA ;Build and send App Ack
+1 ;RRA IB*2*769
+2 ;Don't send Ack for Cerner sites
IF IBSNDST=$$GCRNSITE^VAFCCRNR
QUIT
+3 NEW IBPARMS,IBACK,IBERR,IBX
+4 SET IBPARMS("ACK CODE")=$SELECT('$DATA(IBERROR):"AA",1:"AE")
+5 IF $DATA(IBERROR)
SET IBPARMS("ERROR MESSAGE")=$GET(IBERROR)
+6 SET IBPARMS("MESSAGE TYPE")="ACK"
+7 SET IBPARMS("COUNTRY")="USA"
+8 SET IBPARMS("VERSION")="2.3"
+9 SET IBX=$$ACK^HLOAPI2(.IBMSG,.IBPARMS,.IBACK,.IBERR)
+10 SET IBX=$$SENDACK^HLOAPI2(.IBACK,.IBERR)
+11 QUIT
+12 ;
DFTACK ;process app ack
+1 ;IB*2*769
+2 ;MSH|^~\&|IBECEAC-RCV|554^HL7.DENVER.DOMAIN.EXT:5754^DNS|IBECEAC-SEND|537^HL7.CHICAGO-WEST.DOMAIN.EXT:5591^DNS|20250513145255-0600||ACK^P03^ACK|554 22000060|T^|2.3|||AL|NE|USA
+3 ;MSA|AE|537 12661932|Unable to update existing MEANS TEST BILLING CLOCK at remote site
+4 NEW IBSTAT,IBHDR,IBSEG,IBACK,IBID,IBERR,IBERRS,IB351IEN,IB778,IBICLDTS,IBCLDAU
+5 SET IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,HLMSGIEN,.IBHDR)
+6 if '$$NEXTSEG^HLOPRS(.IBMSG,.IBSEG)
QUIT
+7 SET IBACK=$$GET^HLOPRS(.IBSEG,1,1)
+8 ;ONLY PROCESS NEGATIVE ACK'S - QUIT IF AA
+9 if IBACK="AA"
QUIT
+10 ;GET MESSAGE ID
+11 SET IBID=$$GET^HLOPRS(.IBSEG,2,1)
+12 ;MESSAGE SHOULD ONLY BE GENERATED FOR SITE THAT SENT THE DFT
+13 ;IF THIS SITE IS NOT THE SITE THAT SENT THE DFT THEN QUIT PROCESSING
+14 if '+IBID=$PIECE($$SITE^VASITE,"^",3)
QUIT
+15 ;GET ERROR AND SITE
+16 ;error message
SET IBERR=$$GET^HLOPRS(.IBSEG,3,1)
+17 ;station sending the error back
SET IBERRS=+IBMSG("HDR","SENDING FACILITY",1)
+18 DO GETDET
+19 DO ERR1^IBECECX1(IBERR)
+20 ;UPDATE SYNC ERROR FIELD TO PREVENT BILLING EVENTS
+21 IF +IB351IEN
Begin DoDot:1
+22 LOCK +^IBE(351,IB351IEN):$GET(DILOCKTM,5)
if '$TEST
QUIT
+23 SET DIE="^IBE(351,"
SET DA=IB351IEN
SET DR="18///1"
DO ^DIE
+24 LOCK -^IBE(351,IB351IEN)
End DoDot:1
+25 QUIT
GETDET ;get outgoing DFT details based on returned App Ack Message ID
+1 NEW IB778,IBSTAT,IBMSG,IBHDR,SEG
+2 ;OUTGOING DFT 778 IEN
SET IB778=$PIECE(IBID," ",2)
+3 SET IBSTAT=$$STARTMSG^HLOPRS(.IBMSG,IB778,.IBHDR)
+4 FOR
if '$$NEXTSEG^HLOPRS(.IBMSG,.SEG)
QUIT
SET IBSEGT=$GET(SEG("SEGMENT TYPE"))
if IBSEGT=""
QUIT
Begin DoDot:1
+5 IF IBSEGT="PID"
DO PIDI
+6 IF IBSEGT="FT1"
DO FT1I
End DoDot:1
+7 ;CLOCK START DATE FOR ERROR MESSAGE
SET IBICLDTS=IBICLDT
+8 ;CLOCK VERSION FOR ERROR MESSAGE
SET IBCLDAU=IBFVRSN
+9 ;Get inpatient admit data
DO INPT^IBECECX1(DFN)
+10 ;GET CLOCK IEN USING CLOCK BEGIN DATE AND PT DFN
SET IB351IEN=$$GETIEN^IBECECX1(DFN,IBICLDTS)
+11 ;MISMATCH IN VERSION INFO - PASS BACK MESSAGE
IF $$GET1^DIQ(351,IB351IEN_",",17)'=IBCLDAU
SET IB351IEN="UNABLE TO IDENTIFY BILLING CLOCK IEN"
+12 QUIT