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, "DT") Swap " " with @FM in DT Date = Iconv(DT<1>:" ":DT<2>:" ":DT<3>, "D") Time = Iconv(DT<4>, "MT") Times = 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 ;// Current key Case Otherwise$ Read Rec from hTable, Keys 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 then // Reset the display for this appt. rv = SVC_Scheduler("Appt", Keys, Rec) rv = SVC_Scheduler("Bump", Keys, 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, "", 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 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 PinnedSusceptor = PSrec WandRestrictor = PSrec 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 = "" // 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 = "" 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 rv = Get_Property(@Window:".OLE_SCHEDULE", "OLE.Entity[":Ent:"]") rv<3> = "Brown" Set_Property(@Window:".OLE_SCHEDULE", "OLE.Entity[":Ent:"]", rv) Next i return