Function SVC_Scheduler(Service, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8)

/******************************************************************************************************** 

    This program is proprietary and is not to be used by or disclosed to others, nor is it to
    be copied without written permission.

    Name        :   SVC Scheduler

    Description :   

    Tags		:	[SRP]

    Parameters  :

    History (Date, Initials, Notes)
        10/05/09    fjt     Initial development
        01/18/10	fjt		Added color for reactors in escalation
        08/24/10	fjt		Increased security restrictions

********************************************************************************************************/

$insert SRP_APP_INSERTS
$insert SERVICE_INSERT
$insert WO_SCHEDULER_INSERTS

Declare subroutine SRP_ContextMenus, Pop_Mast_Sched_Opts, obj_Appwindow, Update_Index
Declare subroutine Master_Schedule_Control_Base_Settings, Extract_SI_Keys
Declare function   Get_Lparam, NextKey, MemberOf, Utility_Services, Create_Dialog, Max
Declare function   SVC_Process_Time, SVC_Scheduler, SVC_Dates, SVC_Reactor_List, SVC_Change_Log

GoSub Init

Begin Case
	
	// Menus
	Case Service _eqc "Audit"				; GoSub Audit
	Case Service _eqc "Copy"				; GoSub Copy
	Case Service _eqc "Delete"				; GoSub Delete
	Case Service _eqc "New"					; GoSub New
	Case Service _eqc "Open"				; GoSub Open
		
	// Events
	Case Service _eqc "Create"				; GoSub Create
		
	// Methods
	Case Service _eqc "AddAppts"			; GoSub AddAppts
	Case Service _eqc "RemoveAppts"			; GoSub RemoveAppts
		
	// Events
	Case Service _eqc "AfterApptDrop"		; GoSub AfterApptDrop
    Case Service _eqc "AfterNewApptDrop"	; GoSub AfterNewApptDrop
    Case Service _eqc "OnApptClick"			; GoSub OnApptClick
    Case Service _eqc "OnApptDblClick"		; GoSub OnApptDblClick
    Case Service _eqc "OnDateChange"        ; GoSub OnDateChange
	Case Service _eqc "OnScheduleClick"     ; GoSub OnScheduleClick
    Case Service _eqc "OnScheduleDblClick"  ; GoSub OnScheduleDblClick

	Case Service _eqc "BeforeApptDrag"		; GoSub BeforeApptDrag
	Case Service _eqc "BeforeApptDrop"		; GoSub BeforeApptDrop
		
    Case Service _eqc "BeforeNewApptDrag"	; Send_Message(Ctrl$, "OLE.Cancel", 1) ; Ans = 0
    Case Service _eqc "BeforeNewApptDrop"	; Send_Message(Ctrl$, "OLE.Cancel", 1) ; Ans = 0
    Case Service _eqc "OnTreeCheckChange"	; null
    Case Service _eqc "OnTreeItemExpanded"	; null
	
	// Other
	Case Service _eqc "Appt"				; GoSub Appt
	Case Service _eqc "Bump"				; GoSub Bump
    Case Service _eqc "Build_Appt_Rec"		; GoSub Build_Appt_Rec
    Case Service _eqc "CheckWaferSize"		; GoSub Check_Wafer_Size
    Case Service _eqc "ExtSummary"			; GoSub ExtSummary
	Case Service _eqc "FlagSched"			; GoSub FlagSched
	Case Service _eqc "Legacy"				; GoSub Legacy
    Case Service _eqc "ProcTime"			; GoSub ProcTime
	Case Service _eqc "UnFlagSched"			; GoSub UnFlagSched
    
End Case

Return Ans


Init:
	Equ Table$	   to "WO_MAST_SCHED"
	Equ Info$	   to Sched_Win$:".EDT_INFO"
	Equ Day$	   to 60 * 60 * 24
	
	// Set some security levels
	Auth.Edit  = MemberOf(@USER4, 'MASTER_SCHED')
	Auth.Admin = MemberOf(@USER4, 'OI_ADMIN')
	Auth.Test  = MemberOf(@USER4, 'TESTING')
return


!----- RIGHT-CLICK MENUS --------------------------------------------------------------------------------


Audit:
	// Param1 = ApptID
	If Param1 then
		Mode = Yes$ ;// Allow scheduler to remain active
		rv = Create_Dialog("NDW_AUDIT_TRAIL", @Window, Mode, Param1)
	end
return


Copy:
	Error = No$
	Table = "WO_MAST_SCHED"
	Open Table to hTable else hTable = ""
	
	Begin Case
		Case hTable EQ ""	; Error = Yes$
		Case Param1 EQ ""   ; Error = Yes$
			
		Case Otherwise$
			Key = Param1<1>
			Read Rec from hTable, Key else Rec = ""
			GoSub Define_Schedule_Rec
			
			// Determine process time and range
			StartDate = Param1<3>
			StartTime = Rec<16>
			rv = SVC_Scheduler("ProcTime", PSrec, RDS_Cnt, RDS_Comp, WO_Step)
			Proc.Hrs = Field(rv, @RM, 1)
			rv = SVC_Process_Time("CalcRange", StartDate, StartTime, Proc.Hrs)
	
			ApptID  = NextKey(Table)
			Rec<14> = rv<1>		;// Start date
			Rec<15> = Param1<2> ;// Reactor
			Rec<16> = rv<2>		;// StartTime
			Rec<21> = rv<3>		;// End Date
			Rec<22> = rv<4>
			
			Write Rec to hTable, ApptID then
				* Msg(@Window, ApptID)
				rv = SVC_Scheduler("AddAppts", ApptID, Rec)
			end
			
	End Case
return


Delete:
	GoSub RemoveAppts
return


New:
	Transfer Param2 to Times
	
	For i = 1 to 2
		DT   = Oconv(Times<i>, "DT")
		Swap " " with @FM in DT
		Date = Iconv(DT<1>:" ":DT<2>:" ":DT<3>, "D")
		Time = Iconv(DT<4>, "MT")
		Times<i> = Time
	Next i
	
	// Find the next available queue
	Queue = 1
	Loop
		ApptID = Param1 :"*": Queue
	Until Not(RowExists("WO_MAST_SCHED", ApptID))
		Queue += 1
	Repeat
	rv = Dialog_Box("DBW_WO_MAST_SCHED", @Window, ApptID :@FM: Times)
return


Open:
	// Param1 = ApptID
	If Param1 and Auth.Edit then
		rv = Dialog_Box("DBW_WO_MAST_SCHED", @Window, Param1)
	end
return


!----- SCHEDULER METHODS --------------------------------------------------------------------------------


AddAppts:
	// Adds a single appointment to the scheduler
	ApptID = Param1
	Rec    = Param2
	Appt   = SVC_Scheduler("Build_Appt_Rec", ApptID, Rec)
	rv     = Send_Message(Ctrl$, "OLE.AddAppts", Appt)
return


RemoveAppts:
	// Param1 = ApptID
	// Param2 = Appt Record
	Service = "RemoveAppts"
	rv = Send_Message(Ctrl$, "OLE.RemoveAppts", Param1)
	rv = SVC_Scheduler("UnFlagSched", Param1, Param2)
	rv = SVC_Change_Log(Service, Param1, Param2)
	* Delete : need to add more here?
return


!----- SCHEDULER EVENTS ---------------------------------------------------------------------------------


AfterApptDrop:
	Transfer Param1 to Key
	Transfer Param2 to EntityID
	Transfer Param3 to Old.EntityID
	Transfer Param4 to Old.Start
	Transfer Param5 to Old.End
 
	Appt	  = Get_Property(Ctrl$, "OLE.Appt[":Key:"]")
	Reactor   = EntityID
	Start.A   = Appt<2>
	End.A     = Appt<3>
	Duration  = End.A - Start.A
	Old.Len   = Old.End - Old.Start
	
	If Duration NE Old.Len then
		// Since the appointment has already been moved, need to reset it back
		Rec = Xlate(Table$, Key, "", "X")
		rv = SVC_Scheduler("Appt", Key, Rec)
	end else
	  	StartDate = Field(Start.A, ".", 1)
		StartTime = Field(Oconv(Start.A, "DT"), " ", 4)
		StartTime = Iconv(StartTime, "MT")
		If StartTime LE (Day$/2) then StartTime = 0
		If StartTime GT (Day$/2) then StartTime = (Day$/2)
	
		End.A	 = Iconv(Oconv(StartDate, "D") :" ": Oconv(StartTime, "MT"), "DT")
		End.A	+= Duration
	  	EndDate  = Field(End.A, ".", 1)
		EndTime  = Field(Oconv(End.A, "DT"), " ", 4)
		EndTime  = Iconv(EndTime, "MT")
		
	 	If StartDate and EndDate and Reactor and Appt then
			Open "WO_MAST_SCHED" to hTable then
				Read Rec from hTable, Key then
					Rec<14> = StartDate
					Rec<15> = Reactor
					Rec<16> = StartTime
					Rec<21> = EndDate
					Rec<22> = EndTime
					Write Rec to hTable, Key then
						rv = SVC_Scheduler("Appt", Key, Rec)
					end
				end
			end
			rv = SVC_Scheduler("Bump", Key, StartDate :"*": Reactor, No$)
	 		If EndTime EQ (Day$/2) then rv = SVC_Scheduler("Bump", Key, EndDate :"*": Reactor, Yes$)
	 	end
 	end
return


AfterNewApptDrop:
	Transfer Param1 to Reactor
	Transfer Param2 to DT_Start
	Transfer Param3 to DT_End
 
* 	DateS = Field(DT_Start, ".", 1)
* 	DateE = Field(DT_End, ".", 1)
* 
* 	If DateS EQ DateE then
*		ApptID = DateS :"*": Reactor
*		rv = SVC_Scheduler("New", ApptID, DT_Start :@FM: DT_End)
* 	end
return


BeforeApptDrag:
	// Check security restrictions
	If Auth.Edit or Auth.Admin then
		// Clear to drag to another reactor
	end else
		Send_Message(Ctrl$, "OLE.Cancel", 1)
		Ans = 0
	end
return


BeforeApptDrop:
	// Check wafer size
	// Param1 = ApptID, Param2 = Reactor
	Wafer = Field(Xlate("WO_MAST_SCHED", Param1, "WAFER_SIZE", "X"), " ", 1)
	Event = Xlate("WO_MAST_SCHED", Param1, "EVENT", "X")
	rv = SVC_Scheduler("CheckWaferSize", Service, Param1, Param2, Wafer, Event)
return


Create:
	Master_Schedule_Control_Base_Settings(Window, Param1)
	Ctrl = Window:".OLE_STATUS"
	Cols = 9
	Set_Property(Ctrl, "OLE.PaneCount", Cols)
	Set_Property(Ctrl, "OLE.PaneAlignment[All]", "Center")
	Set_Property(Ctrl, "OLE.PaneBehavior[All]", "Fix")
	Set_Property(Ctrl, "OLE.PaneBehavior[":Cols:"]", "Maximum")
	
	// Status bar pane widths
	w = "90,100,150,25,25,25,100,100"
	For i = 1 to 8
		Set_Property(Ctrl, "OLE.PaneWidth[":i:"]", Field(w, ",", i))
	Next i

	Set_Property(Ctrl, "OLE.PaneCaption[1]", " ":Version$)
	Set_Property(Ctrl, "OLE.PaneCaption[2]", " ":@USER4)
	If Auth.Admin then Set_Property(Ctrl, "OLE.PaneCaption[4]", "A")
	If Auth.Edit  then Set_Property(Ctrl, "OLE.PaneCaption[5]", "E")
	If Auth.Test  then Set_Property(Ctrl, "OLE.PaneCaption[6]", "T")
	
	GoSub Reactor_List
return


OnApptClick:
	// Param1 = ApptID
	// Param2 = Button
	Begin Case
		Case Param2 _eqc "Left"
		Case Param2 _eqc "Right"
			lParam = Get_lParam(Ctrl$)
			Table  = "SYSREPOSMENUCONTEXT"
			Key    = "LSL2**WO_MASTER_SCHEDULER*OLE_SCHEDULE"
			
			Begin Case
				Case Auth.Admin		; Key := "_ADMIN"
				Case Not(Auth.Edit)	; Key := "_LIMIT"
			End Case
				
			rv = Xlate(Table, Key, "", "X")
			Set_Property(@Window, "@APPTID", Param1)
			SRP_ContextMenus("CREATE/DISPLAY", Ctrl$, lParam, "", rv)
	End Case
return


OnApptDblClick:
	// Param1 = ApptID
	// Param2 = Button
	Begin Case
		Case Param2 EQ "Left"
			WOStepKey = Xlate(Table$, Param1, 2, "X")
			If WOStepKey then Pop_Mast_Sched_Opts(WOStepKey, Param1)
	End Case
return


OnDateChange:
return


OnScheduleClick:
	// Non-appointment area; single click
	// Param1 to EntityID
	// Param2 to Button
	// Param3 to Location
	// Param4 to Point
return


OnScheduleDblClick:
	// Reactor = Param1
	Transfer Param2 to Button
	Transfer Param3 to Location

	If Button EQ "Left" then
		Begin Case
			Case Location EQ "Header"
				obj_Appwindow("ViewRelated", "REACTOR" :@RM: Param1)
			Case Location EQ "Entity"
				rv = Dialog_Box("DBW_WO_MAST_SCHED", @Window, "REACTOR" :@RM: Param1)      
		End Case
	end
return


!----- OTHER SERVICES -----------------------------------------------------------------------------------


Appt:
	ApptID = Param1
	Rec    = Param2
	Ans    = SVC_Scheduler("Build_Appt_Rec", ApptID, Rec)
	Convert @VM to @FM in Ans
	ApptID = Ans<2>
	
	!!! need to check for pace !!!
	GoSub Build_Single_Appt
	
 	Set_Property(Ctrl$, "OLE.Appt[":ApptID:"]", Appt)
 	Set_Property(Ctrl$, "OLE.ApptLocked[":ApptID:"]", Param2<17>)
return


Build_Appt_Rec:
	Key = Param1
	Rec = Param2
	
	GoSub Define_Schedule_Rec
	GoSub WO_Status_Colors
	GoSub Define_Schedule_Times
	GoSub Build_Appointment
	
	If Locked then Param2<17> = Locked
	Ans = Appt
return


Bump:
	Key		  = Param1
	DateReact = Param2
	Noon	  = Param3
	Date	  = Field(DateReact, "*", 1)
	Reactor	  = Field(DateReact, "*", 2)
	Appt	  = Get_Property(Ctrl$, "OLE.Appt[":Key:"]")
	Table     = "WO_MAST_SCHED"

	Open Table to hTable then
		Update_Index(Table, "DATE_REACT", No$, Yes$)
	 	Extract_SI_Keys(Table, "DATE_REACT", DateReact, Keys)
	 	Duration = (Appt<3> - Appt<2>)
	 	If Noon then Duration -= .5
	 	
	 	If Appt and Keys and Duration then
	 		Swap @VM with @FM in Keys
	 		Cnt = Count(Keys, @FM) + (Keys NE "")
	 		For i = 1 to Cnt
	 			Begin Case
	 				Case Key EQ Keys<i>	;// Current key
	 				Case Otherwise$
			 			Read Rec from hTable, Keys<i> then
			 				StartTime = SVC_Dates("ADD", Rec<14>, Rec<16>, Duration)
			 				EndTime   = SVC_Dates("ADD", Rec<21>, Rec<22>, Duration)
			 				Rec<14>   = StartTime<1>
			 				Rec<16>   = StartTime<2>
			 				Rec<21>   = EndTime<1>
			 				Rec<22>   = EndTime<2>
			 				Write Rec to hTable, Keys<i> then
			 					// Reset the display for this appt.
			 					rv = SVC_Scheduler("Appt", Keys<i>, Rec)
			 					rv = SVC_Scheduler("Bump", Keys<i>, StartTime<1> :"*": Reactor, No$)
			 					If EndTime<2> EQ (Day$/2) then rv = SVC_Scheduler("Bump", Key, EndTime<1> :"*": Reactor, Yes$)
			 				end
			 			end
	 			End Case
	 		Next i
	 	end
 	end
return


Check_Wafer_Size:
	Ans 	= Yes$
	Svc     = Param1
	ApptID  = Param2
	Reactor = Param3
	Size.WO = Param4
	Event   = Param5
	
	* Size.WO = Field(Xlate("WO_MAST_SCHED", ApptID, "WAFER_SIZE", "X"), " ", 1)
 	Size.RE = Field(Xlate("REACTOR", Reactor, 29, "X"), " ", 3) ;// Susceptor size
 	
 	Begin Case
		Case Event
		Case Wafer.Check.On$ EQ No$
 		Case Size.WO NE Size.RE
	 		Ans = No$
	 		Begin Case
	 			Case Svc EQ "BeforeApptDrop"
					Err = "Move not allowed due to a wafer size mismatch."
					rv  = Utility_Services("Balloon", Error, @Window:".EDL_DATE", "", Err)
					Send_Message(Ctrl$, "OLE.Cancel", 1)
				Case Svc EQ "Copy"
					Err = "Copy not allowed due to a wafer size mismatch."
					rv  = Utility_Services("Balloon", Error, @Window:".EDL_DATE", "", Err)
				Case Svc EQ "PUB_SAVE"
					Err = "Appointment save is not allowed due to a wafer size mismatch."
					rv  = Utility_Services("Balloon", Error, @Window:".EDL_APPT", "", Err)
			End Case
	End Case
return


ExtSummary:
	ApptID = Param1
	Rec    = Param2
	Key    = ApptID
	Array  = Get_Property(Info$, "OLE.Array")
	
	If Rec EQ "" then Rec = Xlate(Table$, ApptID, "", "X")
	
	GoSub Define_Schedule_Rec
	GoSub WO_Status_Colors
	GoSub Reactor_Schedule_Setup
	
	// Targets
	TarThick  = Xlate("WO_LOG", WOno, "THICK_TARGET_L1", "X")<0,1>
 	TarResist = Xlate("WO_LOG", WOno, "RES_TARGET_L1", "X")<0,1>
 	TarTuom	  = Xlate("WO_LOG", WOno, "THICK_UNITS_L1", "X")<0,1>
 	TarRuom	  = Xlate("WO_LOG", WOno, "RES_UNITS_L1", "X")<0,1>
	
	// Determine the process time
	rv = SVC_Scheduler("ProcTime", Rec<02>, Rec)
	Proc.Hrs = Field(rv, @RM, 1)
	BoxPer   = Field(rv, @RM, 2)
	MinPer   = Field(rv, @RM, 3)
	MinRem   = Field(rv, @RM, 4)
	Proc.Day = Field(rv, @RM, 5)
	Wafers   = Field(rv, @RM, 6)
	
	CustName = Trim(CustNo:" - ":CustName)
	If Index(CustName, "<no name>", 1) then CustName = ""
	Cycles = Xlate("REACT_TUBE", Reactor, "SVC_CYCLES", "X")<0,1>

	Array<01> = ApptID
 	Array<02> = WOno
 	Array<03> = CustName
	Array<04> = EPIno
 	Array<05> = PSNno
 	Array<06> = Oconv(TarThick, "MD2") :" ":TarTuom:" / ": Oconv(TarResist, "MD3") :" ":TarRuom
 	Array<07> = RDS_Comp
 	Array<08> = RDS_Cnt
 	Array<09> = Wafer
 	Array<10> = Oconv(MinPer, "MD1") :" mpw"
 	Array<11> = Oconv(Commit, "D4/")
 	Array<12> = Cycles
 	Array<13> = MinRem
 	Array<14> = Notes
 	Array<15> = Event
 	Array<16> = Color_B
 	Array<17> = Color_F
 	Array<18> = Color_S
 	Array<19> = Reactor
 	Array<20> = Date
 	Array<21> = RecipeNo
 	Array<22> = RecipeName
 	Array<23> = Dopant
	Array<24> = TubePressure
	Array<25> = WandRestrictor
	Array<26> = PinnedSusceptor
	Array<27> = Oconv(BoxPer, "MD1") :" mpb"
	Array<28> = Proc.Day
	Array<29> = Wafers
	Array<30> = Oconv(Proc.Hrs, "MD1") : " hrs."
	Array<31> = WO_Qty
	Array<32> = RDS_Comp*WPB
	
	Ans = Array
return


FlagSched:
	// Flag an WO as being scheduled
	// This is field 9 in WO_LOG and field 14 in WO_STEP
	ApptID  = Param1
	Rec 	= Param2
	WO_Step = Rec<01>
	WO_No   = Rec<02>
	Flag	= Yes$
	GoSub WO_Flag
return


ProcTime:
	Ans = SVC_Process_Time(Service, Param1, Param2, Param3, Param4, Param5)
return


Legacy:
    If Get_Property('NDW_MAIN', 'VISIBLE') then
        AppMain = 'NDW_MAIN'
    end else
        AppMain = 'LSL_MAIN2'
    end
	Enabled	= No$
	If Auth.All$ EQ No$ then
		Enabled = Yes$
		Set_Property(AppMain : ".MENU.WIN.PROD.RSCHED", "ENABLED", 1)
	end else
		If MemberOf(@USER4, 'TESTING') then
			Enabled = Yes$
		end
	end
	Set_Property(AppMain : ".MENU.WIN.PROD.RSCHED", "ENABLED", Enabled)
return


WO_Flag:
	Open "WO_LOG" to hTable then
		Read rv from hTable, WO_No then
			WriteV Flag to hTable, WO_No, 9 else null
		end
	end
	
	Open "WO_STEP" to hTable then
		Read rv from hTable, WO_Step then
			// Change to boolean per David/JH
			WriteV Flag to hTable, WO_Step, 14 else null
			* WriteV 1 to hTable, WO_No, 14 else null
			* WriteV WO_No:"*1" to hTable, WO_No, 14 else null
		end		
	end
return


UnFlagSched:
	// Unflag an WO as being scheduled
	// This is field 9 in WO_LOG and field 14 in WO_STEP
	ApptID  = Param1
	Rec 	= Param2
	WO_Step = Rec<01>
	WO_No   = Rec<02>
	Flag	= No$
	GoSub WO_Flag
return


!----- INTERNAL ROUTINES --------------------------------------------------------------------------------


Build_Single_Appt:
	Appt = ""
	Appt<01> = Ans<01>	;// Entity ID
	Appt<02> = Ans<03>	;// Start date / time
	Appt<03> = Ans<04>	;// End date / time
	Appt<04> = Ans<05>	;// Background color
	Appt<05> = Ans<06>  ;// Foreground color
	Appt<06> = Ans<07>	;// Title
	Appt<07> = Ans<08>	;// Description
	Appt<08> = ""		;// Lead Time
	Appt<09> = ""
	Appt<10> = ""
	Appt<11> = ""
	Appt<12> = ""		;// Trail Time
return


Reset_Date:
* 	Table = "WO_MAST_SCHED"
* 	Update_Index(Table, "SCHED_DT", No$)
* 	Extract_SI_Keys(Table, "SCHED_DT", Date, rv)
* 	Cnt = Count(rv, @VM) + (rv NE "")
* 	
* 	For i = 1 to Cnt
*		Key = rv<0,i>
*		Rec = Xlate(Table, Key, "", "X")
*		rv = SVC_Scheduler("Appt", Key, Rec)
* 	Next i
return


Reactor_Schedule_Setup:
	// Taken from the window WO_MAINT_SCHED, Create event
	Equ Prod_Spec_Spec_Epi$				to 15
	Equ Prod_Spec_Wand_Restricter$ 		to 89
	Equ Prod_Spec_Tube_Pressure_Type$ 	to 92
	Equ Prod_Spec_Susceptor_Type$		to 110
	
	Equ QSEpiDopant$					to 10
	Equ QSEpiRecipe$					to 11
	Equ QSEpiRecipeName$				to 12

	SpecEpi = PSrec<Prod_Spec_Spec_Epi$>
	Convert Char(247) to @FM in SpecEpi
	Convert Char(248) to @FM in SpecEpi

	// Pull off the first layer info
	Dopant			= SpecEpi<1,QSEpiDopant$>
	RecipeNo		= SpecEpi<1,QSEpiRecipe$>
	RecipeName		= SpecEpi<1,QSEpiRecipeName$>
    TubePressure	= PSrec<Prod_Spec_Tube_Pressure_Type$>
	PinnedSusceptor = PSrec<Prod_Spec_Susceptor_Type$>
	WandRestrictor  = PSrec<Prod_Spec_Wand_Restricter$>
	WandRestrictor  = Oconv(WandRestrictor, 'B')
return


Define_Schedule_Rec:
	// WO Schedule Record
	StepKey   = Rec<01,1>
	WOno      = Rec<02>
	Event	  = Rec<04>
	Hot		  = Rec<05>
	PSNno     = Rec<06>
	* Released  = Rec<07>
	CustNo    = Rec<08>
	Status    = Rec<09>
	Notes	  = Rec<11>
	EPIno     = Rec<13>
	Date      = Rec<14>
	StartDate = Rec<14>
    Reactor   = Rec<15>
	StartTime = Rec<16>
	Locked	  = Rec<17>
	ProcTime  = Rec<20>
	EndDate   = Rec<21>
	EndTime   = Rec<22>
	Stoppage  = Rec<29>

	// RDS
	RDS_Comp   = 0
	WO_Qty     = Max(Xlate("WO_LOG", WOno, 4, "X"), Xlate("WO_LOG", WOno, "RX_QTY", "X")) ;// Qty vs. Rcvd
	WO_Step    = Xlate("WO_STEP", StepKey, "", "X")
	RDS_Keys   = WO_Step<06>
	RDS_Unload = Xlate("REACT_RUN", RDS_Keys, "UNLOAD_SIG", "X")
	* RDS_Unload = Xlate("REACT_RUN", RDS_Keys, "LOAD_SIG", "X")
	RDS_Cnt    = Count(RDS_Keys, @VM) + (RDS_Keys NE "")
	WPB 	   = Xlate("RDS", WO_Step<6>, "WAFERS_SCHEDULED", "X")<0,1> ;// Wafers per box

	// RDS Completed
	Pos.x = 0 ; Delim.x = ""
	Loop
		Remove Val from RDS_Unload at Pos.x setting Delim.x
		If Val GT "" then RDS_Comp += 1
	Until Delim.x EQ 0
	Repeat
	
	// Build completed line with note tag if applicable
	* Comp = "RDS: ":RDS_Comp:" of ":RDS_Cnt
	Qty_Comp = RDS_Comp * WPB
	Comp = "Wafers: ":Qty_Comp:" of ":WO_Qty
	If Notes then Comp := " (See Note)"

	WO.Done = (RDS_Comp EQ RDS_Cnt) and (RDS_Comp NE 0)
	Comp.Time = "0.0"
	If WO.Done then
		Comp.Time = Sum(Xlate("RDS", RDS_Keys, "ELAPSED_HOURS", "X"))
		Comp.Time = Iconv(Comp.Time, "MD0")
		Comp.Time = Oconv(Comp.Time, "MD2")
	end
	
	// Customer Name
	CustName = Xlate(Table$, Key, "CUST_NAME", "X")
	If CustName EQ "" then CustName = "<no name>"
	
	// Work Order Record
	WOrec    = Xlate("WO_LOG", WOno, "", "X")
	Released = Xlate("WO_LOG", WONo, "REL_STAMP", "X") GT ""
	Commit   = WOrec<14>
	
	// Product Spec Record
	PSrec  = Xlate("PROD_SPEC", PSNno, "", "X")
	MinPer = PSrec<96>											;// MINUTES_PER_WAFER
	Wafer  = Xlate("PROD_SPEC", PSNno, "SUB_WAFER_INCHES", "X")	;// symb

	// Stoppage adjustment
 	Stoppage = Oconv(Stoppage, "MD1")

	// Element is the top header of the appointment; description
	Desc	= ""
	Element = ""
	Begin Case
		Case Event
			Element = Event
			Desc  = "Notes: ":Notes
			
		Case WO.Done
			Stoppage = 0
			Element  = "WO ":WOno
			Desc  = CustName :Crlf$
			Desc := "Completed ":RDS_Comp:" of ":RDS_Cnt :Crlf$
			Desc := "Est: ":Oconv(ProcTime, "MD1") : " / Act: " : Comp.Time
			Locked = Yes$

		Case WOno
			Spcr = 3
			Days = Int((EndDate - StartDate) / Spcr)
			If Days LE 0 then Days = 1
			Element = "WO ":WOno
			If Days GT 1 then Element = Str(Fmt(Element, "L#":27*Spcr), Days)
			
			Desc  = Str(Fmt(Trim(CustNo:" - ":CustName), "L#104"), Days) :Crlf$
			Desc := Str(Fmt("PSN: ":PSNno, "L#14")   : Fmt("EPI: ":EPIno, "L#":30*Spcr), Days) :Crlf$
			Desc := Str(Fmt("Wafer: ":Wafer, "L#14") : Fmt(Comp, "L#":30*Spcr), Days)
			
		Case Otherwise$
			Element = "<unknown>"
			Desc = ""
			
	End Case
return


WO_Status_Colors:
	Color_F = "" ; Color_B = "" ; Color_S = ""
	Begin Case
		Case Event EQ "Down â€“ No Material"					; Color_F = White$ ; Color_B = "Sienna"			; Color_S = "Offline"
		Case Event											; Color_F = Black$ ; Color_B = "GoldenRod"		; Color_S = "Offline"
		Case WO.Done										; Color_F = Black$ ; Color_B = "Gainsboro"		; Color_S = "Completed"
		Case Hot 											; Color_F = Black$ ; Color_B = "LightCoral"		; Color_S = "Hot"
		Case Not(Released)									; Color_F = Black$ ; Color_B = "Yellow"			; Color_S = "Not Released"
		Case Released and RDS_Comp EQ 0						; Color_F = Black$ ; Color_B = "GreenYellow"	; Color_S = "Not Started"
		Case RDS_Comp EQ RDS_Cnt and Qty_Comp NE WO_Qty		; Color_F = Black$ ; Color_B = "GreenYellow"	; Color_S = "More Unreleased"
		Case RDS_Comp GT 0									; Color_F = Black$ ; Color_B = "Lime"			; Color_S = "In Process"
		Case Index(Status, "INPR", 1)						; Color_F = Black$ ; Color_B = "Lime"			; Color_S = "In Process"
		Case Index(Status, "RTS", 1)						; Color_F = Black$ ; Color_B = "DarkGray"		; Color_S = "In Process"
		Case Otherwise$										; Color_F = White$ ; Color_B = "DarkSlateBlue"  ; Color_S = "Unknown"
	End Case
return


Define_Schedule_Times:
* 	If EndTime EQ 0 then EndTime = Iconv("11:59:59PM", "MT")

* debug
    T_Start    = Oconv(StartDate, "D4/")
    T_Start<2> = Oconv(StartTime, "MTS")
    T_Start    = Iconv(T_Start<1> :" ": T_Start<2>, "DT")
    T_End	   = Oconv(EndDate, "D4/")
    T_End<2>   = Oconv(EndTime, "MTS")
	T_End      = Iconv(T_End<1> :" ": T_End<2>, "DT")
return


Build_Appointment:
	T_End += Stoppage

	Appt = ""
	Appt := Reactor		:@VM	;// 01 Entity ID
	Appt := Key			:@VM	;// 02 Appointment key
	Appt := T_Start		:@VM	;// 03 Start date / time
	Appt := T_End		:@VM	;// 04 End date / time
	Appt := Color_B    	:@VM    ;// 05 Background color
	Appt := Color_F  	:@VM    ;// 06 Foreground color
	Appt := Element		:@VM	;// 07 Element (header)
	Appt := Desc		:@VM	;// 08 Description
	Appt := ""			:@VM	;// 09 Lead time
	Appt := "3DFace"	:@VM	;// 10 Lead Back Color
	Appt := "3DShadow"	:@VM	;// 11 Lead Text Color
	Appt := ""			:@VM	;// 12 Lead time text label
	Appt := Stoppage	:@VM	;// 13 Trail time
	Appt := "3DFace"	:@VM	;// 14 Trail Back Color
	Appt := "3DShadow"	:@VM	;// 15 Trail Text Color
	
	// 16 Trail time text label
	If Stoppage GT 0 then Appt<0,16> = "Pace Adjustment"
return


Reactor_List:
	// Reactors are the appointment entities
    rv = SVC_Reactor_List("List", Data, Colors)
	
	// Set the list of reactors
	Set_Property(@Window:".OLE_SCHEDULE", "OLE.EntityList", Data)
	
	// Set foreground colors
	Cnt = Count(Colors, @FM) + (Colors NE "")
	For i = 1 to Cnt
		Ent = Colors<i>
		rv  = Get_Property(@Window:".OLE_SCHEDULE", "OLE.Entity[":Ent:"]")
		rv<3> = "Brown"
		Set_Property(@Window:".OLE_SCHEDULE", "OLE.Entity[":Ent:"]", rv)
	Next i
return


