Index: /Scheduling/trunk/m/BSDXAPI.m
===================================================================
--- /Scheduling/trunk/m/BSDXAPI.m	(revision 1455)
+++ /Scheduling/trunk/m/BSDXAPI.m	(revision 1456)
@@ -1,3 +1,3 @@
-BSDXAPI	; IHS/ANMC/LJF & VW/SMH - SCHEDULING APIs ; 6/20/12 12:40pm
+BSDXAPI	; IHS/ANMC/LJF & VW/SMH - SCHEDULING APIs ; 6/22/12 4:25pm
 	;;1.7T1;BSDX;;Aug 31, 2011;Build 18
 	; Licensed under LGPL  
@@ -292,4 +292,58 @@
 	;   = 1^message:  error and reason
 	;
+	N BSDXCANCK S BSDXCANCK=$$CANCELCK(.BSDR)
+	I BSDXCANCK Q BSDXCANCK
+	;
+	; BSDX 1.5 3110125
+	; UJO/SMH - Add ability to remove check-in if the patient is checked in
+	; I $$CI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"),IEN) Q 1_U_"Patient already checked in; cannot cancel until checkin deleted: Patient="_BSDR("PAT")_" Clinic="_BSDR("CLN")_" Appt="_BSDR("ADT")
+	; Remove check-in if the patient is checked in.
+	N BSDXRESULT S BSDXRESULT=0 ; Result; should be zero if success; -1 + message if failure
+	NEW IEN S IEN=$$SCIEN(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"))
+	I $$CI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"),IEN) SET BSDXRESULT=$$RMCI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"))
+	I BSDXRESULT Q BSDXRESULT
+	; NB: Failure point 1: we fail here nothing has happened yet
+	;
+	; remember before status
+	NEW SDATA,DFN,SDT,SDCL,SDDA,SDCPHDL
+	S DFN=BSDR("PAT"),SDT=BSDR("ADT"),SDCL=BSDR("CLN"),SDMODE=2,SDDA=IEN
+	S SDCPHDL=$$HANDLE^SDAMEVT(1),SDATA=SDDA_U_DFN_U_SDT_U_SDCL
+	D BEFORE^SDAMEVT(.SDATA,DFN,SDT,SDCL,SDDA,SDCPHDL)
+	; NB: Here only globals are set. Nothing else.
+	;
+	; get user who made appt and date appt made from ^SC
+	;    because data in ^SC will be deleted
+	NEW USER,DATE
+	S USER=$P($G(^SC(SDCL,"S",SDT,1,IEN,0)),U,6)
+	S DATE=$P($G(^SC(SDCL,"S",SDT,1,IEN,0)),U,7)
+	;
+	; update file 2 info
+	NEW DIE,DA,DR
+	S DIE="^DPT("_DFN_",""S"",",DA(1)=DFN,DA=SDT
+	S DR="3///"_BSDR("TYP")_";14///`"_BSDR("USR")_";15///"_BSDR("CDT")_";16///`"_BSDR("CR")_";19///`"_USER_";20///"_DATE
+	S:$G(BSDR("NOT"))]"" DR=DR_";17///"_$E(BSDR("NOT"),1,160)
+	D ^DIE
+	; Failure point 2: If we fail here, it means that the check-in was removed; 
+	; but the appointment wasn't cancelled.
+	; To roll back, we should restore the check-in. However, I would rather not
+	; do that. This code will only fail if there's something wrong in the DB.
+	; (deleted field for example). If I try to restore the check-in, I just
+	; may excercerbate the problem.
+	;
+	; delete data in ^SC
+	NEW DIK,DA
+	S DIK="^SC("_BSDR("CLN")_",""S"","_BSDR("ADT")_",1,"
+	S DA(2)=BSDR("CLN"),DA(1)=BSDR("ADT"),DA=IEN
+	D ^DIK
+	; Failure point 3: If we fail here, we need to restore the cancel date, 
+	; and possibly, the check-in.
+	;
+	; call event driver
+	D CANCEL^SDAMEVT(.SDATA,DFN,SDT,SDCL,SDDA,SDMODE,SDCPHDL)
+	Q 0
+	;
+CANCELCK(BSDR) ; $$ PEP; Okay to Cancel Appointment?
+	; Input: .BSDR array as documented in $$CANCEL
+	; Output: 0 or 1^Error message
 	I '$D(^DPT(+$G(BSDR("PAT")),0)) Q 1_U_"Patient not on file: "_$G(BSDR("PAT"))
 	I '$D(^SC(+$G(BSDR("CLN")),0)) Q 1_U_"Clinic not on file: "_$G(BSDR("CLN"))
@@ -302,45 +356,7 @@
 	I '$D(^SD(409.2,+$G(BSDR("CR")))) Q 1_U_"Cancel Reason error: "_$G(BSDR("CR"))
 	;
-	NEW IEN,DIE,DA,DR
-	S IEN=$$SCIEN(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"))
+	NEW IEN S IEN=$$SCIEN(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"))
 	I 'IEN Q 1_U_"Error trying to find appointment for cancel: Patient="_BSDR("PAT")_" Clinic="_BSDR("CLN")_" Appt="_BSDR("ADT")
-	;
-	; BSDX 1.5 3110125
-	; UJO/SMH - Add ability to remove check-in if the patient is checked in
-	; I $$CI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"),IEN) Q 1_U_"Patient already checked in; cannot cancel until checkin deleted: Patient="_BSDR("PAT")_" Clinic="_BSDR("CLN")_" Appt="_BSDR("ADT")
-	; Remove check-in if the patient is checked in.
-	N BSDXRESULT S BSDXRESULT=0 ; Result; should be zero if success; -1 + message if failure
-	I $$CI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"),IEN) SET BSDXRESULT=$$RMCI(BSDR("PAT"),BSDR("CLN"),BSDR("ADT"))
-	I BSDXRESULT Q BSDXRESULT
-	;
-	; remember before status
-	NEW SDATA,DFN,SDT,SDCL,SDDA,SDCPHDL
-	S DFN=BSDR("PAT"),SDT=BSDR("ADT"),SDCL=BSDR("CLN"),SDMODE=2,SDDA=IEN
-	S SDCPHDL=$$HANDLE^SDAMEVT(1),SDATA=SDDA_U_DFN_U_SDT_U_SDCL
-	D BEFORE^SDAMEVT(.SDATA,DFN,SDT,SDCL,SDDA,SDCPHDL)
-	;
-	; get user who made appt and date appt made from ^SC
-	;    because data in ^SC will be deleted
-	NEW USER,DATE
-	S USER=$P($G(^SC(SDCL,"S",SDT,1,IEN,0)),U,6)
-	S DATE=$P($G(^SC(SDCL,"S",SDT,1,IEN,0)),U,7)
-	;
-	; update file 2 info
-	NEW DIE,DA,DR
-	S DIE="^DPT("_DFN_",""S"",",DA(1)=DFN,DA=SDT
-	S DR="3///"_BSDR("TYP")_";14///`"_BSDR("USR")_";15///"_BSDR("CDT")_";16///`"_BSDR("CR")_";19///`"_USER_";20///"_DATE
-	S:$G(BSDR("NOT"))]"" DR=DR_";17///"_$E(BSDR("NOT"),1,160)
-	D ^DIE
-	;
-	; delete data in ^SC
-	NEW DIK,DA
-	S DIK="^SC("_BSDR("CLN")_",""S"","_BSDR("ADT")_",1,"
-	S DA(2)=BSDR("CLN"),DA(1)=BSDR("ADT"),DA=IEN
-	D ^DIK
-	;
-	; call event driver
-	D CANCEL^SDAMEVT(.SDATA,DFN,SDT,SDCL,SDDA,SDMODE,SDCPHDL)
-	Q 0
-	;
+	Q 0
 CI(PAT,CLINIC,DATE,SDIEN)	;PEP; -- returns 1 if appt already checked-in
 	NEW X
@@ -396,4 +412,10 @@
 	Q $G(IEN)
 	;
+APPLEN(PAT,CLINIC,DATE) ; $$ PEP; returns an appointment's length
+	; Get either the appointment length or zero
+	; TODO: Test
+	N SCIEN S SCIEN=$$SCIEN(PAT,CLINIC,DATE)
+	Q:SCIEN $P(^SC(CLINIC,"S",DATE,1,SCIEN,0),U,2)
+	Q 0
 APPTYP(PAT,DATE)	;PEP; -- returns type of appt (scheduled or walk-in)
 	NEW X S X=$P($G(^DPT(PAT,"S",DATE,0)),U,7)
