SDES2GETNEXTSLOT ;ALB/JAS - SDES2 GET NEXT CLINIC SLOT ; Apr 6, 2026
;;5.3;Scheduling;**942**;Aug 13, 1993;Build 2
;;Per VHA Directive 6402, this routine should not be modified
;
; Reference to DUZ^XUP is supported by IA #7487
;
; The SDCONTEXT array is controlled by the Acheron application and its fields are
; needed for the storage of the required auditing information.
;
; SDCONTEXT("ACHERON AUDIT ID") = Up to 40 Character unique ID number. Ex: 11d9dcc6-c6a2-4785-8031-8261576fca37
; SDCONTEXT("PATIENT DFN") = The DFN/IEN of the target patient from the calling application.
; SDCONTEXT("PATIENT ICN") = The ICN of the target patient from the calling application.
; SDCONTEXT("USER DUZ") = The DUZ of the user taking action in the calling application.
; SDCONTEXT("USER SECID") = The SECID of the user taking action in the calling application.
;
; Note: SDINPUT("CLINIC IEN",1) is required. Additional clinics can be specified, but are optional
; SDINPUT("CLINIC IEN",1)=IEN1 The clinic IEN from HOSPITAL LOCATION (#44) to list appointments (required)
; SDINPUT("CLINIC IEN",2)=IEN2 (optional)
; SDINPUT("CLINIC IEN",3)=IEN3 (optional)
; SDINPUT("SEARCH LIMIT")=90 How many days into the future to search if availability is not being found (optional)
; If not passed will default to each clinic's MAX # DAYS FOR FUTURE BOOKING (#2002) field
; from the HOSPITAL LOCATION (#44) file.
Q
;
GETNEXTSLOT(JSONRETURN,SDCONTEXT,SDINPUT) ;
; This RPC returns the first available appointment slot for a list of clinics in JSON format.
;
N %DT,DIERR,ERRORS,I,RETURN
D VALCONTEXT^SDES2VALCONTEXT(.ERRORS,.SDCONTEXT)
I $D(ERRORS) S ERRORS("nextAvailableTimeSlot",1)="" D BUILDJSON^SDES2JSON(.JSONRETURN,.ERRORS) Q
I $G(SDCONTEXT("USER DUZ"))'="" N DUZ D DUZ^XUP(SDCONTEXT("USER DUZ"))
;
D VALPARAM(.ERRORS,.SDINPUT)
I $D(ERRORS) S ERRORS("nextAvailableTimeSlot",1)="" D BUILDJSON^SDES2JSON(.JSONRETURN,.ERRORS) Q
;
D BUILDDATA(.RETURN,.SDINPUT)
I '$D(RETURN("nextAvailableTimeSlot")) S RETURN("nextAvailableTimeSlot",1)=""
;
D BUILDJSON^SDES2JSON(.JSONRETURN,.RETURN)
Q
;
VALPARAM(ERRORS,SDINPUT) ; Validate the clinics in SDINPUT
I $D(SDINPUT("CLINIC IEN"))'>1 D ERRLOG^SDES2JSON(.ERRORS,18) Q ; no clinic array to build
Q
;
BUILDDATA(RETURN,SDINPUT) ;retrieve clinic availability data
N CLINICIEN,ENDDATE,ERRORS,DAYSINFUTURE,INDEX,RESOURCEIEN,SLOTARRAY,STARTDATE
S INDEX=0,SLOTARRAY=$NA(^TMP($J,"CLNCAVAIL"))
K @SLOTARRAY
;
F S INDEX=$O(SDINPUT("CLINIC IEN",INDEX)) Q:'INDEX D
. S CLINICIEN=SDINPUT("CLINIC IEN",INDEX)
. ;
. ; Check the clinic IEN to make sure it's valid
. D VALCLINIEN^SDES2VAL44(.ERRORS,CLINICIEN,1,0) I $D(ERRORS) D Q
. . S RETURN("Error",INDEX)="ClinicIEN "_CLINICIEN_": "_ERRORS("Error",1) K ERRORS
. ;
. ; Retrieve the resource IEN for the clinic
. S RESOURCEIEN=$$GETRES^SDES2UTIL1(CLINICIEN,1)
. I RESOURCEIEN="" D ERRLOG^SDES2JSON(.ERRORS,70) D Q ;invalid clinic resource id
. . S RETURN("Error",INDEX)="ClinicIEN "_CLINICIEN_": "_ERRORS("Error",1) K ERRORS
. ;
. ; Initialize search criteria
. S STARTDATE=$$NOW^XLFDT()
. S DAYSINFUTURE=$S(+$G(SDINPUT("SEARCH LIMIT"))>0:SDINPUT("SEARCH LIMIT"),+$$GET1^DIQ(44,CLINICIEN,2002):$$GET1^DIQ(44,CLINICIEN,2002),1:99)
. S ENDDATE=$$FMADD^XLFDT(DT,DAYSINFUTURE)_".999999"
. ;
. ; Search for clinic slots and build return array
. D GETSLOTS^SDEC57(SLOTARRAY,RESOURCEIEN,$P(STARTDATE,"."),$P(ENDDATE,"."))
. D BUILDRET(.RETURN,CLINICIEN,SLOTARRAY,STARTDATE,ENDDATE,INDEX)
. K @SLOTARRAY
Q
;
BUILDRET(RETURN,CLINICIEN,SLOTARRAY,STARTDATE,ENDDATE,INDEX) ;
N COUNT,FOUND,FMDATE,FMTIME,HASAVAIL,ISODATE,OPENSLOTS,SLOTSTARTDTTM,SLOTENDDTTM,SDSLOTS,SDENDDTTM,SDSTARTDTTM,TOTALFND
S (FOUND,HASAVAIL)=0
;
; Adjust STARTDATE for clinic's time zone
S ISODATE=$$FMTISO^SDAMUTDT(STARTDATE)
S STARTDATE=$$ISOTFM^SDAMUTDT(ISODATE,CLINICIEN)
;
; If no results, set return for no availability
I $O(@SLOTARRAY@(""))="" D Q
. S RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
. S RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
;
S TOTALFND=@SLOTARRAY@("CNT")
F COUNT=1:1:TOTALFND D Q:FOUND
. S SLOTSTARTDTTM=$P(@SLOTARRAY@(COUNT),U,2) ;start date
. S SLOTENDDTTM=$P(@SLOTARRAY@(COUNT),U,3) ;end date
. I (SLOTSTARTDTTM<STARTDATE)!(SLOTSTARTDTTM>ENDDATE) Q
. S OPENSLOTS=+$P(@SLOTARRAY@(COUNT),U,4) ;open slots available
. Q:'OPENSLOTS
. ;
. ; Availability has been found, set return with availability data
. S HASAVAIL=1,FOUND=1
. I $P(SLOTSTARTDTTM,".",2)=""!($P(SLOTSTARTDTTM,".",2)="00") S $P(SLOTSTARTDTTM,".",2)="0001"
. ;
. ; Adjust start date/time if time is greater than 24, so it will pass $$FMTISO^SDAMUTDT
. I $E($P(SLOTSTARTDTTM,".",2),1,2)=24,($E($P(SLOTSTARTDTTM,".",2),3,6))>0 D
. . N FMDATE,FMTIME
. . S FMDATE=$P(SLOTSTARTDTTM,".",1),FMTIME=$P(SLOTSTARTDTTM,".",2)
. . S FMDATE=$$FMADD^XLFDT(FMDATE,1)
. . S SLOTSTARTDTTM=FMDATE_".00"_$E(FMTIME,3,6)
. ;
. S SDSTARTDTTM=$$FMTISO^SDAMUTDT(SLOTSTARTDTTM,CLINICIEN)
. S SDENDDTTM=$$FMTISO^SDAMUTDT(SLOTENDDTTM,CLINICIEN)
. S RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
. S RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
. S RETURN("nextAvailableTimeSlot",INDEX,"beginDateTime")=SDSTARTDTTM
. S RETURN("nextAvailableTimeSlot",INDEX,"endDateTime")=SDENDDTTM
;
; If no availability found, set return for no availability
I 'FOUND D
. S RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
. S RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
Q
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HSDES2GETNEXTSLOT 5744 printed Jul 11, 2026@02:51:08 Page 2
SDES2GETNEXTSLOT ;ALB/JAS - SDES2 GET NEXT CLINIC SLOT ; Apr 6, 2026
+1 ;;5.3;Scheduling;**942**;Aug 13, 1993;Build 2
+2 ;;Per VHA Directive 6402, this routine should not be modified
+3 ;
+4 ; Reference to DUZ^XUP is supported by IA #7487
+5 ;
+6 ; The SDCONTEXT array is controlled by the Acheron application and its fields are
+7 ; needed for the storage of the required auditing information.
+8 ;
+9 ; SDCONTEXT("ACHERON AUDIT ID") = Up to 40 Character unique ID number. Ex: 11d9dcc6-c6a2-4785-8031-8261576fca37
+10 ; SDCONTEXT("PATIENT DFN") = The DFN/IEN of the target patient from the calling application.
+11 ; SDCONTEXT("PATIENT ICN") = The ICN of the target patient from the calling application.
+12 ; SDCONTEXT("USER DUZ") = The DUZ of the user taking action in the calling application.
+13 ; SDCONTEXT("USER SECID") = The SECID of the user taking action in the calling application.
+14 ;
+15 ; Note: SDINPUT("CLINIC IEN",1) is required. Additional clinics can be specified, but are optional
+16 ; SDINPUT("CLINIC IEN",1)=IEN1 The clinic IEN from HOSPITAL LOCATION (#44) to list appointments (required)
+17 ; SDINPUT("CLINIC IEN",2)=IEN2 (optional)
+18 ; SDINPUT("CLINIC IEN",3)=IEN3 (optional)
+19 ; SDINPUT("SEARCH LIMIT")=90 How many days into the future to search if availability is not being found (optional)
+20 ; If not passed will default to each clinic's MAX # DAYS FOR FUTURE BOOKING (#2002) field
+21 ; from the HOSPITAL LOCATION (#44) file.
+22 QUIT
+23 ;
GETNEXTSLOT(JSONRETURN,SDCONTEXT,SDINPUT) ;
+1 ; This RPC returns the first available appointment slot for a list of clinics in JSON format.
+2 ;
+3 NEW %DT,DIERR,ERRORS,I,RETURN
+4 DO VALCONTEXT^SDES2VALCONTEXT(.ERRORS,.SDCONTEXT)
+5 IF $DATA(ERRORS)
SET ERRORS("nextAvailableTimeSlot",1)=""
DO BUILDJSON^SDES2JSON(.JSONRETURN,.ERRORS)
QUIT
+6 IF $GET(SDCONTEXT("USER DUZ"))'=""
NEW DUZ
DO DUZ^XUP(SDCONTEXT("USER DUZ"))
+7 ;
+8 DO VALPARAM(.ERRORS,.SDINPUT)
+9 IF $DATA(ERRORS)
SET ERRORS("nextAvailableTimeSlot",1)=""
DO BUILDJSON^SDES2JSON(.JSONRETURN,.ERRORS)
QUIT
+10 ;
+11 DO BUILDDATA(.RETURN,.SDINPUT)
+12 IF '$DATA(RETURN("nextAvailableTimeSlot"))
SET RETURN("nextAvailableTimeSlot",1)=""
+13 ;
+14 DO BUILDJSON^SDES2JSON(.JSONRETURN,.RETURN)
+15 QUIT
+16 ;
VALPARAM(ERRORS,SDINPUT) ; Validate the clinics in SDINPUT
+1 ; no clinic array to build
IF $DATA(SDINPUT("CLINIC IEN"))'>1
DO ERRLOG^SDES2JSON(.ERRORS,18)
QUIT
+2 QUIT
+3 ;
BUILDDATA(RETURN,SDINPUT) ;retrieve clinic availability data
+1 NEW CLINICIEN,ENDDATE,ERRORS,DAYSINFUTURE,INDEX,RESOURCEIEN,SLOTARRAY,STARTDATE
+2 SET INDEX=0
SET SLOTARRAY=$NAME(^TMP($JOB,"CLNCAVAIL"))
+3 KILL @SLOTARRAY
+4 ;
+5 FOR
SET INDEX=$ORDER(SDINPUT("CLINIC IEN",INDEX))
if 'INDEX
QUIT
Begin DoDot:1
+6 SET CLINICIEN=SDINPUT("CLINIC IEN",INDEX)
+7 ;
+8 ; Check the clinic IEN to make sure it's valid
+9 DO VALCLINIEN^SDES2VAL44(.ERRORS,CLINICIEN,1,0)
IF $DATA(ERRORS)
Begin DoDot:2
+10 SET RETURN("Error",INDEX)="ClinicIEN "_CLINICIEN_": "_ERRORS("Error",1)
KILL ERRORS
End DoDot:2
QUIT
+11 ;
+12 ; Retrieve the resource IEN for the clinic
+13 SET RESOURCEIEN=$$GETRES^SDES2UTIL1(CLINICIEN,1)
+14 ;invalid clinic resource id
IF RESOURCEIEN=""
DO ERRLOG^SDES2JSON(.ERRORS,70)
Begin DoDot:2
+15 SET RETURN("Error",INDEX)="ClinicIEN "_CLINICIEN_": "_ERRORS("Error",1)
KILL ERRORS
End DoDot:2
QUIT
+16 ;
+17 ; Initialize search criteria
+18 SET STARTDATE=$$NOW^XLFDT()
+19 SET DAYSINFUTURE=$SELECT(+$GET(SDINPUT("SEARCH LIMIT"))>0:SDINPUT("SEARCH LIMIT"),+$$GET1^DIQ(44,CLINICIEN,2002):$$GET1^DIQ(44,CLINICIEN,2002),1:99)
+20 SET ENDDATE=$$FMADD^XLFDT(DT,DAYSINFUTURE)_".999999"
+21 ;
+22 ; Search for clinic slots and build return array
+23 DO GETSLOTS^SDEC57(SLOTARRAY,RESOURCEIEN,$PIECE(STARTDATE,"."),$PIECE(ENDDATE,"."))
+24 DO BUILDRET(.RETURN,CLINICIEN,SLOTARRAY,STARTDATE,ENDDATE,INDEX)
+25 KILL @SLOTARRAY
End DoDot:1
+26 QUIT
+27 ;
BUILDRET(RETURN,CLINICIEN,SLOTARRAY,STARTDATE,ENDDATE,INDEX) ;
+1 NEW COUNT,FOUND,FMDATE,FMTIME,HASAVAIL,ISODATE,OPENSLOTS,SLOTSTARTDTTM,SLOTENDDTTM,SDSLOTS,SDENDDTTM,SDSTARTDTTM,TOTALFND
+2 SET (FOUND,HASAVAIL)=0
+3 ;
+4 ; Adjust STARTDATE for clinic's time zone
+5 SET ISODATE=$$FMTISO^SDAMUTDT(STARTDATE)
+6 SET STARTDATE=$$ISOTFM^SDAMUTDT(ISODATE,CLINICIEN)
+7 ;
+8 ; If no results, set return for no availability
+9 IF $ORDER(@SLOTARRAY@(""))=""
Begin DoDot:1
+10 SET RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
+11 SET RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
End DoDot:1
QUIT
+12 ;
+13 SET TOTALFND=@SLOTARRAY@("CNT")
+14 FOR COUNT=1:1:TOTALFND
Begin DoDot:1
+15 ;start date
SET SLOTSTARTDTTM=$PIECE(@SLOTARRAY@(COUNT),U,2)
+16 ;end date
SET SLOTENDDTTM=$PIECE(@SLOTARRAY@(COUNT),U,3)
+17 IF (SLOTSTARTDTTM<STARTDATE)!(SLOTSTARTDTTM>ENDDATE)
QUIT
+18 ;open slots available
SET OPENSLOTS=+$PIECE(@SLOTARRAY@(COUNT),U,4)
+19 if 'OPENSLOTS
QUIT
+20 ;
+21 ; Availability has been found, set return with availability data
+22 SET HASAVAIL=1
SET FOUND=1
+23 IF $PIECE(SLOTSTARTDTTM,".",2)=""!($PIECE(SLOTSTARTDTTM,".",2)="00")
SET $PIECE(SLOTSTARTDTTM,".",2)="0001"
+24 ;
+25 ; Adjust start date/time if time is greater than 24, so it will pass $$FMTISO^SDAMUTDT
+26 IF $EXTRACT($PIECE(SLOTSTARTDTTM,".",2),1,2)=24
IF ($EXTRACT($PIECE(SLOTSTARTDTTM,".",2),3,6))>0
Begin DoDot:2
+27 NEW FMDATE,FMTIME
+28 SET FMDATE=$PIECE(SLOTSTARTDTTM,".",1)
SET FMTIME=$PIECE(SLOTSTARTDTTM,".",2)
+29 SET FMDATE=$$FMADD^XLFDT(FMDATE,1)
+30 SET SLOTSTARTDTTM=FMDATE_".00"_$EXTRACT(FMTIME,3,6)
End DoDot:2
+31 ;
+32 SET SDSTARTDTTM=$$FMTISO^SDAMUTDT(SLOTSTARTDTTM,CLINICIEN)
+33 SET SDENDDTTM=$$FMTISO^SDAMUTDT(SLOTENDDTTM,CLINICIEN)
+34 SET RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
+35 SET RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
+36 SET RETURN("nextAvailableTimeSlot",INDEX,"beginDateTime")=SDSTARTDTTM
+37 SET RETURN("nextAvailableTimeSlot",INDEX,"endDateTime")=SDENDDTTM
End DoDot:1
if FOUND
QUIT
+38 ;
+39 ; If no availability found, set return for no availability
+40 IF 'FOUND
Begin DoDot:1
+41 SET RETURN("nextAvailableTimeSlot",INDEX,"clinicIEN")=CLINICIEN
+42 SET RETURN("nextAvailableTimeSlot",INDEX,"hasAvailability")=HASAVAIL
End DoDot:1
+43 QUIT