Index: /Scheduling/trunk/m/BSDX08.m
===================================================================
--- /Scheduling/trunk/m/BSDX08.m	(revision 1454)
+++ /Scheduling/trunk/m/BSDX08.m	(revision 1455)
@@ -1,4 +1,4 @@
-BSDX08	; VW/UJO/SMH - WINDOWS SCHEDULING RPCS ; 6/21/12 4:49pm
-	;;1.6;BSDX;;Aug 31, 2011;Build 18
+BSDX08	; VW/UJO/SMH - WINDOWS SCHEDULING RPCS ; 6/22/12 4:19pm
+	;;1.7T1;BSDX;;Aug 31, 2011;Build 18
 	; 
 	; Original by HMW. New Written by Sam Habiel. Licensed under LGPL.
@@ -71,8 +71,4 @@
 	L +^BSDXAPPT(BSDXAPTID):5 I '$T D ERR(BSDXI,"-1~BSDX08: Appt record is locked. Please contact technical support.") Q
 	;
-	;Restartable Transaction; restore paramters when starting.
-	; (Params restored are what's passed here + BSDXI)
-	TSTART (BSDXY,BSDXAPTID,BSDXTYP,BSDXCR,BSDXNOT,BSDXI):T="BSDX CANCEL APPOINTEMENT^BSDX08"
-	;
 	; Turn off SDAM APPT PROTOCOL BSDX Entries
 	N BSDXNOEV
@@ -81,50 +77,58 @@
 	;;;test for error inside transaction. See if %ZTER works
 	I $G(BSDXDIE) S X=1/0
-	;;;test
-	;;;test for TRESTART
-	I $G(BSDXRESTART) K BSDXRESTART tRESTART
-	;;;test
 	;
 	; Check appointment ID and whether it exists
 	I '+BSDXAPTID D ERR(BSDXI,"-2~BSDX08: Invalid Appointment ID") Q
 	I '$D(^BSDXAPPT(BSDXAPTID,0)) D ERR(BSDXI,"-3~BSDX08: Invalid Appointment ID") Q
-	;
+	; 
 	; Start Processing:
-	; First, add cancellation date to appt entry in BSDX APPOINTMENT
+	; First, get data
 	N BSDXNOD S BSDXNOD=^BSDXAPPT(BSDXAPTID,0) ; BSDX Appt Node
 	N BSDXPATID S BSDXPATID=$P(BSDXNOD,U,5) ; Patient ID
 	N BSDXSTART S BSDXSTART=$P(BSDXNOD,U) ; Start Time
-	D BSDXCAN(BSDXAPTID)  ; Add a cancellation date in BSDX APPOINTMENT
-	;
-	; Second, cancel appt in "S" nodes in file 2 and 44, then update Legacy PIMS Availability
+	;
+	; Check the resource ID and whether it exists
 	N BSDXSC1 S BSDXSC1=$P(BSDXNOD,U,7) ;RESOURCEID
 	; If the resouce id doesn't exist...
 	I BSDXSC1="" D ERR(BSDXI,"-4~BSDX08: Cancelled appointment does not have a Resouce ID") QUIT
 	I '$D(^BSDXRES(BSDXSC1,0)) D ERR(BSDXI,"-5~BSDX08: Resouce ID does not exist in BSDX RESOURCE") QUIT
+	;
+	; Process PIMS issues first: 
+	; cancel appt in "S" nodes in file 2 and 44, then update Legacy PIMS Availability
 	; Get zero node of resouce
-	S BSDXNOD=^BSDXRES(BSDXSC1,0)
+	N BSDXNOD S BSDXNOD=^BSDXRES(BSDXSC1,0)
 	; Get Hosp location
 	N BSDXLOC S BSDXLOC=$P(BSDXNOD,U,4)
 	; Error indicator for Hosp Location filing for getting out of routine
 	N BSDXERR S BSDXERR=0
+	; For BSDXC
+	N BSDXC
 	; Only file in 2/44 if there is an associated hospital location
 	I BSDXLOC D  QUIT:BSDXERR
-	. I '$D(^SC(BSDXLOC,0)) S BSDXERR=1 D ERR(BSDXI,"-6~BSDX08: Invalid Hosp Location stored in Database") QUIT
-	. ; Get the IEN of the appointment in the "S" node of ^SC
-	. N BSDXSCIEN
-	. S BSDXSCIEN=$$SCIEN^BSDXAPI(BSDXPATID,BSDXLOC,BSDXSTART)
-	. I BSDXSCIEN="" S BSDXERR=1 D ERR(BSDXI,"-7~BSDX08: Patient does not have an appointment in PIMS Clinic") QUIT
-	. ; Get the appointment node
-	. S BSDXNOD=$G(^SC(BSDXLOC,"S",BSDXSTART,1,BSDXSCIEN,0))
-	. I BSDXNOD="" S BSDXERR=1 D ERR(BSDXI,"-8^BSDX08: Unable to find associated PIMS appointment for this patient") QUIT
-	. N BSDXLEN S BSDXLEN=$P(BSDXNOD,U,2)
+	. S BSDXC("PAT")=BSDXPATID
+	. S BSDXC("CLN")=BSDXLOC
+	. S BSDXC("TYP")=BSDXTYP
+	. S BSDXC("ADT")=BSDXSTART
+	. S BSDXC("CDT")=$$NOW^XLFDT()
+	. S BSDXC("NOT")=BSDXNOT
+	. S:'+$G(BSDXCR) BSDXCR=11 ;Other
+	. S BSDXC("CR")=BSDXCR
+	. S BSDXC("USR")=DUZ
+	. ;
+	. S BSDXERR=$$CANCELCK^BSDXAPI(.BSDXC) ; 0 or 1^error message
+	. I BSDXERR D ERR(BSDXI,"-9^BSDX08: BSDXAPI returned an error: "_$P(BSDXERR,U,2)) QUIT
+	. ;
+	. N BSDXLEN S BSDXLEN=$$APPLEN^BSDXAPI(BSDXPATID,BSDXLOC,BSDXSTART)
+	. ; DEBUG
+	. I 'BSDXLEN S $EC=",U1,"
+	. ; DEBUG
 	. ; Cancel through BSDXAPI
-	. N BSDXZ
-	. D APCAN(.BSDXZ,BSDXLOC,BSDXPATID,BSDXSTART)
-	. I +BSDXZ>0 S BSDXERR=1 D ERR(BSDXI,"-9^BSDX08: BSDXAPI returned an error: "_$P(BSDXZ,U,2)) QUIT
+	. S BSDXERR=$$CANCEL^BSDXAPI(.BSDXC)
+	. I BSDXERR=1 D ERR(BSDXI,"-9^BSDX08: BSDXAPI returned an error: "_$P(BSDXZ,U,2)) QUIT
 	. ; Update Legacy PIMS clinic Availability
 	. D AVUPDT(BSDXLOC,BSDXSTART,BSDXLEN)
 	;
-	TCOMMIT
+	D BSDXCAN(BSDXAPTID)  ; Add a cancellation date in BSDX APPOINTMENT
+	;
 	L -^BSDXAPPT(BSDXAPTID)
 	S BSDXI=BSDXI+1
@@ -180,22 +184,4 @@
 	Q
 	;
-APCAN(BSDXZ,BSDXLOC,BSDXDFN,BSDXSD)	        ;
-	;Cancel appointment for patient BSDXDFN in clinic BSDXSC1
-	;at time BSDXSD
-	N BSDXC,%H
-	S BSDXC("PAT")=BSDXPATID
-	S BSDXC("CLN")=BSDXLOC
-	S BSDXC("TYP")=BSDXTYP
-	S BSDXC("ADT")=BSDXSD
-	S %H=$H D YMD^%DTC
-	S BSDXC("CDT")=X+%
-	S BSDXC("NOT")=BSDXNOT
-	S:'+$G(BSDXCR) BSDXCR=11 ;Other
-	S BSDXC("CR")=BSDXCR
-	S BSDXC("USR")=DUZ
-	;
-	S BSDXZ=$$CANCEL^BSDXAPI(.BSDXC)
-	Q
-	;
 BSDXCAN(BSDXAPTID)	;
 	;Cancel BSDX APPOINTMENT entry
@@ -231,4 +217,5 @@
 	Q:'$D(^BSDXAPPT("ARSRC",BSDXRES,BSDXSTART)) BSDXFOUND
 	S BSDXAPPT=0 F  S BSDXAPPT=$O(^BSDXAPPT("ARSRC",BSDXRES,BSDXSTART,BSDXAPPT)) Q:'+BSDXAPPT  D  Q:BSDXFOUND
+	. N BSDXNOD
 	. S BSDXNOD=$G(^BSDXAPPT(BSDXAPPT,0)) Q:BSDXNOD=""
 	. I $P(BSDXNOD,U,5)=BSDXPAT,$P(BSDXNOD,U,12)="" S BSDXFOUND=1 Q
@@ -250,5 +237,4 @@
 	S BSDXI=BSDXI+1
 	S BSDXERR=$TR(BSDXERR,"^","~")
-	I $TL>0 TROLLBACK
 	S ^BSDXTMP($J,BSDXI)=BSDXERR_$C(30)
 	S BSDXI=BSDXI+1
@@ -259,6 +245,4 @@
 ETRAP	;EP Error trap entry
 	N $ET S $ET="D ^%ZTER HALT"  ; Emergency Error Trap
-	; Rollback, otherwise ^XTER will be empty from future rollback
-	I $TL>0 TROLLBACK 
 	D ^%ZTER
 	S $EC=""  ; Clear Error
Index: /Scheduling/trunk/m/BSDX29.m
===================================================================
--- /Scheduling/trunk/m/BSDX29.m	(revision 1454)
+++ /Scheduling/trunk/m/BSDX29.m	(revision 1455)
@@ -1,4 +1,4 @@
-BSDX29	; IHS/OIT/HMW - WINDOWS SCHEDULING RPCS ; 4/28/11 10:25am
-	;;1.6T2;BSDX;;May 16, 2011
+BSDX29	; IHS/OIT/HMW - WINDOWS SCHEDULING RPCS ; 6/22/12 1:46pm
+	;;1.7T1;BSDX;;Aug 31, 2011;Build 18
 	; Licensed under LGPL
 	; 
@@ -8,11 +8,13 @@
 	; v1.42 by WV/SMH on 3101023
 	; - Transaction moved; now restartable too.
-	; --> Thanks to Zach Gonzalez and Rick Marshall.
 	; - Refactoring of major portions of routine
+	; v1.7 by VEN/SMH on 3120622
+	; - Removed transaction code; Locks added in update to prevent concurrent
+	;   update
 	;
 BSDXCPD(BSDXY,BSDXRES,BSDX44,BSDXBEG,BSDXEND)	;EP
 	;Entry point for debugging
 	;
-	D DEBUG^%Serenji("BSDXCP^BSDX29(.BSDXY,BSDXRES,BSDX44,BSDXBEG,BSDXEND)")
+	;D DEBUG^%Serenji("BSDXCP^BSDX29(.BSDXY,BSDXRES,BSDX44,BSDXBEG,BSDXEND)")
 	Q
 	;
@@ -22,31 +24,31 @@
 	   ;Called by RPC: BSDX COPY APPOINTMENTS
 	;
-	   ; Parameters:
-	   ; - BSDXY: Global Return
-	   ; - BSDXRES: BSDX RESOURCE to copy appointments to
-	   ; - BSDX44: Hospital Location IEN to copy appointments from
-	   ; - BSDXBEG: Beginning Date in FM Format
-	   ; - BSDXEND: End Date in FM Format
-	   ;
+	; Parameters:
+	; - BSDXY: Global Return
+	; - BSDXRES: BSDX RESOURCE to copy appointments to
+	; - BSDX44: Hospital Location IEN to copy appointments from
+	; - BSDXBEG: Beginning Date in FM Format
+	; - BSDXEND: End Date in FM Format
+	;
 	;Returns ADO Recordset containing TASK_NUMBER and ERRORID
 	;
-	   ; Return Array
+	; Return Array
 	S BSDXY=$NA(^BSDXTMP($J))
-	   K ^BSDXTMP($J)
-	   ; $ET
-	   N $ET S $ET="G ETRAP^BSDX29"
+	K ^BSDXTMP($J)
+	; $ET
+	N $ET S $ET="G ETRAP^BSDX29"
 	; Counter
-	   N BSDXI S BSDXI=0
-	   ; Header Node
+	N BSDXI S BSDXI=0
+	; Header Node
 	S ^BSDXTMP($J,0)="T00010TASK_NUMBER^T00100ERRORID"_$C(30)
 	;
-	   ; Make dates inclusive; add 1 to FM dates
-	   S BSDXBEG=BSDXBEG-1
-	S BSDXEND=BSDXEND+1
-	;
-	   ; Taskman variables
-	   N ZTSK,ZTRTN,ZTDTH,ZTDESC,ZTSAVE 
+	; Make dates inclusive; add 1 to FM dates
+	S BSDXBEG=$$FMADD^XLFDT(BSDXBEG,-1)
+	S BSDXEND=$$FMADD^XLFDT(BSDXEND,+1)
+	;
+	; Taskman variables
+	N ZTSK,ZTRTN,ZTDTH,ZTDESC,ZTSAVE,ZTIO
 	; Task Load
-	S ZTRTN="ZTM^BSDX29",ZTDTH=$H,ZTDESC="COPY PATIENT APPTS"
+	S ZTRTN="ZTM^BSDX29",ZTDTH=$H,ZTDESC="COPY PATIENT APPTS",ZTIO=""
 	S ZTSAVE("BSDXBEG")="",ZTSAVE("BSDXEND")="",ZTSAVE("BSDX44")="",ZTSAVE("BSDXRES")=""
 	D ^%ZTLOAD
@@ -62,28 +64,28 @@
 	;
 ZTM	;EP - Taskman entry point
-	   ; Variables set up in ZTSAVE above
-	   ;
+	; Variables set up in ZTSAVE above
+	;
 	Q:'$D(ZTSK)
-	   ; $ET
-	   N $ET S $ET="G ZTMERR^BSDX29"
-	; Txn
-	   TSTART (BSDXBEG,BSDXEND,BSDX44,BSDXRES):T="BSDX COPY APPOINTMENT^BSDX29"
+	;
+	; $ET
+	N $ET S $ET="G ZTMERR^BSDX29"
+	;
 	;$O through ^SC(BSDX44,"S",
 	N BSDXCNT S BSDXCNT=0  ; Count of Copied Appointments
-	   N BSDXQUIT S BSDXQUIT=0  ; Quit Flag to be retrieved from an external proc
+	N BSDXQUIT S BSDXQUIT=0  ; Quit Flag to be retrieved from an external proc
 	; Set Count
-	   S ^BSDXTMP("BSDXCOPY",ZTSK)=BSDXCNT
+	S ^BSDXTMP("BSDXCOPY",ZTSK)=BSDXCNT
 	; Loop through dates here.
-	   F  S BSDXBEG=$O(^SC(BSDX44,"S",BSDXBEG)) Q:'+BSDXBEG  Q:BSDXBEG>BSDXEND  Q:BSDXQUIT  D
-	   . ; Loop through Entries in each date in the subsubfile.
-	   . ; Quit if we are at the end or if a remote process requests a quit.
-	   . N BSDXIEN S BSDXIEN=0
+	F  S BSDXBEG=$O(^SC(BSDX44,"S",BSDXBEG)) Q:'+BSDXBEG  Q:BSDXBEG>BSDXEND  Q:BSDXQUIT  D
+	. ; Loop through Entries in each date in the subsubfile.
+	. ; Quit if we are at the end or if a remote process requests a quit.
+	. N BSDXIEN S BSDXIEN=0
 	. F  S BSDXIEN=$O(^SC(BSDX44,"S",BSDXBEG,1,BSDXIEN)) Q:'+BSDXIEN  Q:BSDXQUIT  D
 	. . N BSDXNOD S BSDXNOD=$G(^SC(BSDX44,"S",BSDXBEG,1,BSDXIEN,0)) ; Node
 	. . Q:'+BSDXNOD  ; Quit if no node
 	. . N BSDXCAN S BSDXCAN=$P(BSDXNOD,U,9) ; Cancel flag
-	. . Q:BSDXCAN="C"  ; Quit if appt cancelled
-	   . . N BSDXPAT S BSDXPAT=$P(BSDXNOD,U) ; Patient
-	   . . N BSDXLEN S BSDXLEN=$P(BSDXNOD,U,2) ;duration in minutes
+	. . Q:BSDXCAN="C"  ; Quit if appt cancelled -- smh - this will never happen; cancelled appointments are normally removed from 44
+	. . N BSDXPAT S BSDXPAT=$P(BSDXNOD,U) ; Patient
+	. . N BSDXLEN S BSDXLEN=$P(BSDXNOD,U,2) ;duration in minutes
 	. . N BSDXCLRK S BSDXCLRK=$P(BSDXNOD,U,6) ;appt made by (clerk)
 	. . N BSDXMADE S BSDXMADE=$P(BSDXNOD,U,7) ;date appt made
@@ -91,9 +93,7 @@
 	. . S BSDXCNT=BSDXCNT+$$XFER(BSDXRES,BSDXBEG,BSDXPAT,BSDXLEN,BSDXCLRK,BSDXMADE,BSDXNOTE)
 	. . I +BSDXCNT,BSDXCNT#10=0 S ^BSDXTMP("BSDXCOPY",ZTSK)=BSDXCNT_" records copied." ;every 10th record
-	. . I $D(^BSDXTMP("BSDXCOPY",ZTSK,"CANCEL")) S BSDXQUIT=1 ;Check for cancel flag
-	. . Q
-	. Q
-	I 'BSDXQUIT TCOMMIT
-	E  TROLLBACK
+	. . I $D(^BSDXTMP("BSDXCOPY",ZTSK,"CANCEL")) S BSDXQUIT=1 ;Check for cancel flag ; smh - not used currently (v1.7)
+	;
+	;
 	S ^BSDXTMP("BSDXCOPY",ZTSK)=$S(BSDXQUIT:"Cancelled.  No records copied.",1:"Finished.  "_BSDXCNT_" records copied.")
 	Q
@@ -101,8 +101,6 @@
 ZTMERR	; For now, error from TM is only in trap; not returned to client.
 	N $ET S $ET="D ^%ZTER HALT" ; Emergency Error Trap
-	   ; Rollback before logging the error
-	   I $TL>0 TROLLBACK
 	D ^%ZTER
-	   S $EC="" ; Clear Error
+	S $EC="" ; Clear Error
 	QUIT
 	;
@@ -112,6 +110,10 @@
 	;Return 1 if record copied, otherwise 0
 	;
+	N REF
+	S REF=$NA(^BSDXLOCK(BSDXRES,BSDXBEG,BSDXPAT)) ; This combo is unique
+	L +@REF:0  E  Q 0
+	;
 	;$O Thru ^BSDXAPPT to determine if this appt already added
-	N BSDXEND,BSDXIEN,BSDXFND,BSDXPAT2
+	N BSDXEND,BSDXIEN,BSDXFND,BSDXPAT2,BSDXNOD
 	S BSDXIEN=0,BSDXFND=0
 	F  S BSDXIEN=$O(^BSDXAPPT("ARSRC",BSDXRES,BSDXBEG,BSDXIEN)) Q:'+BSDXIEN  D  Q:BSDXFND
@@ -122,5 +124,5 @@
 	. I BSDXPAT2=BSDXPAT S BSDXFND=1
 	. Q
-	Q:BSDXFND 0
+	I BSDXFND L -@REF Q 0
 	;
 	;Add to BSDX APPOINTMENT
@@ -128,4 +130,5 @@
 	;Calculate ending time from beginning time and duration.
 	S BSDXEND=$$ADDMIN(BSDXBEG,BSDXLEN)
+	N BSDXFDA,BSDXIENS
 	S BSDXIENS="+1,"
 	S BSDXFDA(9002018.4,BSDXIENS,.01)=BSDXBEG
@@ -137,11 +140,13 @@
 	;
 	K BSDXIEN
+	;
 	D UPDATE^DIE("","BSDXFDA","BSDXIEN","BSDXMSG")
 	S BSDXIEN=+$G(BSDXIEN(1))
-	I '+BSDXIEN Q 0
+	I '+BSDXIEN L -@REF Q 0
 	;
 	;Add WP field
 	I BSDXNOTE]"" S BSDXNOTE(.5)=BSDXNOTE,BSDXNOTE="" D
 	. D WP^DIE(9002018.4,BSDXIEN_",",1,"","BSDXNOTE","BSDXMSG")
+	L -@REF
 	;
 	Q 1
@@ -149,5 +154,5 @@
 ERR(BSDXI,BSDXCNT,BSDXERR)	;Error processing
 	S BSDXI=BSDXI+1
-	   S BSDXERR=$TR(BSDXERR,"^","~")
+	S BSDXERR=$TR(BSDXERR,"^","~")
 	S ^BSDXTMP($J,BSDXI)=BSDXCNT_"^"_BSDXERR_$C(30)
 	S BSDXI=BSDXI+1
@@ -157,7 +162,7 @@
 ETRAP	;EP Error trap entry
 	; No Txn here. So don't rollback anything
-	   N $ET S $ET="D ^%ZTER HALT" ; Emergency Error Trap
-	   D ^%ZTER
-	   S $EC="" ; Clear error
+	N $ET S $ET="D ^%ZTER HALT" ; Emergency Error Trap
+	D ^%ZTER
+	S $EC="" ; Clear error
 	I '$D(BSDXI) N BSDXI S BSDXI=0
 	D ERR(BSDXI,$G(BSDXCNT),"~100~BSDX29, Error: "_$G(%ZTERZE))
Index: /Scheduling/trunk/m/BSDXUT.m
===================================================================
--- /Scheduling/trunk/m/BSDXUT.m	(revision 1454)
+++ /Scheduling/trunk/m/BSDXUT.m	(revision 1455)
@@ -1,3 +1,3 @@
-BSDXUT ; VEN/SMH - Unit Tests for Scheduling GUI ; 6/21/12 4:42pm
+BSDXUT ; VEN/SMH - Unit Tests for Scheduling GUI ; 6/22/12 4:27pm
 	;;1.7T1;BSDX;;Aug 31, 2011;Build 18
 	; Licensed under LGPL
@@ -262,8 +262,8 @@
 	S APPID=+$P(^BSDXTMP($J,1),U)
 	D APPDEL^BSDX08(.ZZZ,APPID,"PC",1,"Sam's Cancel Note")
-	I $P(^BSDXAPPT(APPID,0),U,12)'>0 W "Error in Cancellation-1"
-	I $O(^SC(HLIEN,"S",APPTTIME,1,0))]"" W "Error in Cancellation-2"
-	I $P(^DPT(DFN,"S",APPTTIME,0),U,2)'="PC" W "Error in Cancellation-3"
-	I ^DPT(DFN,"S",APPTTIME,"R")'="Sam's Cancel Note" W "Error in Cancellation-4"
+	I $P(^BSDXAPPT(APPID,0),U,12)'>0 W "Error in Cancellation-1",!
+	I $O(^SC(HLIEN,"S",APPTTIME,1,0))]"" W "Error in Cancellation-2",!
+	I $P(^DPT(DFN,"S",APPTTIME,0),U,2)'="PC" W "Error in Cancellation-3",!
+	I ^DPT(DFN,"S",APPTTIME,"R")'="Sam's Cancel Note" W "Error in Cancellation-4",!
 	;
 	; Test 2: Check for -1 -- TODO: Fix later... Can't do right now automatically
@@ -312,5 +312,5 @@
 	I APPID=0 W "Error in test 6",!
 	D CHECKIN^BSDX25(.ZZZ,APPID,$$NOW^XLFDT) ; Checkin
-	S BSDXRESULT=$$RMCI^BSDXAPI(DFN,HLIEN,BSDXSTART) ; remove checkin
+	S BSDXRESULT=$$RMCI^BSDXAPI(DFN,HLIEN,APPTTIME) ; remove checkin
 	D APPDEL^BSDX08(.ZZZ,APPID,"PC",10,"Cancel Note") ; delete appt
 	I $P(^BSDXTMP($J,1),$C(30))'="" W "Error in test 6",!
@@ -358,5 +358,5 @@
 	I APPID=0 W "Error in test 6",!
 	D CHECKIN^BSDX25(.ZZZ,APPID,$$NOW^XLFDT) ; Checkin
-	S BSDXRESULT=$$RMCI^BSDXAPI(DFN,HLIEN,BSDXSTART) ; remove checkin
+	S BSDXRESULT=$$RMCI^BSDXAPI(DFN,HLIEN,APPTTIME) ; remove checkin
 	D APPDEL^BSDX08(.ZZZ,APPID,"PC",10,"Cancel Note") ; delete appt
 	I $P(^BSDXTMP($J,1),$C(30))'="" W "Error in test 6",!
@@ -415,4 +415,5 @@
  ;
 TIMES() ; $$ - Create a next available appointment time^ending time; Private
+ ; Output: appttime^endtime
  N NOW S NOW=$$NOW^XLFDT() ; Now time
  N LAST S LAST=$O(^BSDXAPPT("B"," "),-1) ; highest time in file
@@ -422,2 +423,8 @@
  N ENDTIME S ENDTIME=$$FMADD^XLFDT(APPTIME,0,0,15,0) ; Add 15 more min
  Q APPTIME_U_ENDTIME ; quit with apptime^endtime
+ ;
+TIMEHL(HLIEN) ; $$ - Create a next available appointment time^ending time by HL; Private
+ ; Input: HLIEN
+ ; Output: Next available appointment time for the HLIEN
+ N LAST S LAST=$O(^SC(HLIEN,"S",""),-1)
+ Q $$FMADD^XLFDT(LAST,1,0,15,0) ; Add 1 day and 15 minutes
Index: /Scheduling/trunk/m/BSDXUT1.m
===================================================================
--- /Scheduling/trunk/m/BSDXUT1.m	(revision 1455)
+++ /Scheduling/trunk/m/BSDXUT1.m	(revision 1455)
@@ -0,0 +1,87 @@
+BSDXUT1 ; VEN/SMH - Unit Tests for Scheduling GUI - cont. ; 6/22/12 1:44pm
+	;;1.7T1;BSDX;;Aug 31, 2011;Build 18
+	;
+	;
+UT29 ; Unit Test for BSDX29
+	; HLs/Resources are created as part of the UT
+	; Patients 1,2,3,4,5 must exist
+	;
+	I '$$TM^%ZTLOAD() W "Cannot test. Taskman is not running!" QUIT
+	;
+	; Set-up - Create Clinics
+	N RESNAM S RESNAM="UTCLINIC"
+	N HLRESIENS ; holds output of UTCR^BSDXUT - HL IEN^Resource IEN
+	D
+	. N $ET S $ET="D ^%ZTER B"
+	. S HLRESIENS=$$UTCR^BSDXUT(RESNAM)
+	. I HLRESIENS<0 S $EC=",U1," ; not supposed to happen - hard crash if so
+	;
+	N HLIEN,RESIEN
+	S HLIEN=$P(HLRESIENS,U)
+	S RESIEN=$P(HLRESIENS,U,2)
+	;
+	; Turn off SDAM APPT PROTOCOL BSDX Entries
+	N BSDXNOEV
+	S BSDXNOEV=1 ;Don't execute BSDX ADD APPOINTMENT protocol
+	;
+	; Create a bunch of appointments in PIMS (25 actually)
+	N DFN
+	N BSDXAPPT,BSDXDATE
+	N BSDXI
+	F BSDXI=1:1:5 D
+	. N APPTTIME S APPTTIME=$$TIMEHL^BSDXUT(HLIEN) ; appt time
+	. F DFN=1,2,3,4,5 D
+	. . N % S %=$$MAKE1^BSDXAPI(DFN,HLIEN,3,APPTTIME,15,"Sam Test Appt"_DFN)
+	. . I % W "Error in $$MAKE1^BSDXAPI for TIME "_APPTTIME_" for DFN "_DFN,!,%,!
+	. . E  S BSDXAPPT(DFN,APPTTIME)="",BSDXDATE(APPTTIME)=""
+	;
+	; Check that appointments are not in ^BSDXAPPT
+	N DFN,APPTTIME S (DFN,APPTTIME)=""
+	F  S DFN=$O(BSDXAPPT(DFN)) Q:'DFN  D
+	. F  S APPTTIME=$O(BSDXAPPT(DFN,APPTTIME)) Q:'APPTTIME  D
+	. . I $D(^BSDXAPPT("APAT",DFN,APPTTIME)) W "Appt for "_DFN_" @ "_APPTTIME_" present",!
+	;
+	; Now, copy those appointments using BSDX29 to ^BSDXAPPT
+	N FIRSTDATE S FIRSTDATE=$O(BSDXDATE(""))
+	N LASTDATE S LASTDATE=$O(BSDXDATE(""),-1)
+	N ZZZ ; garbage
+	D BSDXCP^BSDX29(.ZZZ,RESIEN,HLIEN,FIRSTDATE,LASTDATE)
+	I +^BSDXTMP($J,1)=0 W "Error... task not created",! QUIT
+	;
+	W "Waiting for 5 seconds for it to finish",! HANG 5
+	N DFN,APPTTIME S (DFN,APPTTIME)=""
+	F  S DFN=$O(BSDXAPPT(DFN)) Q:'DFN  D
+	. F  S APPTTIME=$O(BSDXAPPT(DFN,APPTTIME)) Q:'APPTTIME  D
+	. . I '$D(^BSDXAPPT("APAT",DFN,APPTTIME)) W "Appt for "_DFN_" @ "_APPTTIME_" missing",!
+	;
+	; Do all of this again making sure that events execute.
+	K BSDXNOEV
+	;
+	; Create a bunch of appointments in PIMS (25 actually)
+	N DFN
+	N BSDXAPPT,BSDXDATE
+	N BSDXI
+	F BSDXI=1:1:5 D
+	. N APPTTIME S APPTTIME=$$TIMEHL^BSDXUT(HLIEN) ; appt time
+	. F DFN=1,2,3,4,5 D
+	. . N % S %=$$MAKE1^BSDXAPI(DFN,HLIEN,3,APPTTIME,15,"Sam Test Appt"_DFN)
+	. . I % W "Error in $$MAKE1^BSDXAPI for TIME "_APPTTIME_" for DFN "_DFN,!,%,!
+	. . E  S BSDXAPPT(DFN,APPTTIME)="",BSDXDATE(APPTTIME)=""
+	;
+	; Check that appointments are in ^BSDXAPPT (different from last time)
+	N DFN,APPTTIME S (DFN,APPTTIME)=""
+	F  S DFN=$O(BSDXAPPT(DFN)) Q:'DFN  D
+	. F  S APPTTIME=$O(BSDXAPPT(DFN,APPTTIME)) Q:'APPTTIME  D
+	. . I '$D(^BSDXAPPT("APAT",DFN,APPTTIME)) W "Appt for "_DFN_" @ "_APPTTIME_" present",!
+	;
+	; Now, copy those appointments using BSDX29 to ^BSDXAPPT
+	N FIRSTDATE S FIRSTDATE=$O(BSDXDATE(""))
+	N LASTDATE S LASTDATE=$O(BSDXDATE(""),-1)
+	N ZZZ ; garbage
+	D BSDXCP^BSDX29(.ZZZ,RESIEN,HLIEN,FIRSTDATE,LASTDATE)
+	I +^BSDXTMP($J,1)=0 W "Error... task not created",! QUIT
+	;
+	W "Waiting for 5 seconds for it to finish",! HANG 5
+	W ^BSDXTMP("BSDXCOPY",+^BSDXTMP($J,1)),!
+	W "Last line should say 0",!
+	QUIT
