Function Scheduler_Actions_Dev_Events(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)
/***********************************************************************************************************************

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

    Name        :   Scheduler_Actions_Dev_Events

    Description :   This function acts as a commuter module for all events related to this window.

    Notes       :   Commuter Modules are automatically called from the Promoted_Events function which is called by the
                    application-specific promoted event handler. This makes it possible to add QuickEvents that need to
                    execute Basic+ logic without having use the Form Designer to make the association, although this is
                    limited to the events which are currently promoted.

                    If the form needs to call the commuter module directly then the QuickEvent parameters should be
                    formatted like this:

                        '@SELF','@EVENT',['@PARAM1','@PARAMx']

    Parameters  :
        CtrlEntId   [in] -- The fully qualified name of the control calling the promoted event
        Event       [in] -- The event being executed. See the Notes section regarding "PRE" events
        Param1-15   [in] -- Additional event parameter holders
        EventFlow  [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
                            EVENT_SETUP insert

    History     :   (Date, Initials, Notes)
        06/12/17    dmb     Created initial commuter module.
        01/08/21    djs     Began work on version 2.0.

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

#pragma precomp SRP_PreCompiler
#Window SCHEDULER_ACTIONS_DEV

$insert APP_INSERTS
$insert EVENT_SETUP
$insert MSG_EQUATES
$insert SCHED_DET_NG_EQUATES
$insert WO_LOG_EQUATES
$insert WO_SCHEDULE_NG_EQUATES
$insert REACTOR_EQUATES

Equ OI_DISABLED_GREY$ TO 239 + (239*256) + (239*65536)

WorkOrderCtrls      = 'OLE_DIV_WORK_ORDER_DETAILS,WO_NO_LABEL,WO_NO,EPI_PART_LABEL,EPI_PART,DESCRIPTION_LABEL,DESCRIPTION,CUSTOMER_NAME_LABEL,CUSTOMER_NAME,'
WorkOrderCtrls     := 'TOTAL_WAFERS_LABEL,TOTAL_WAFERS,TOTAL_REMAINING_LABEL,TOTAL_REMAINING,PERCENT_COMPLETE_LABEL,PERCENT_COMPLETE'
DateRangeCtrls      = 'SCHEDULE_START_DTM_LABEL,SCHEDULE_START_DTM,SCHEDULE_END_DTM_LABEL,SCHEDULE_END_DTM,DAYS_LABEL,DAYS'

Declare function    SRP_Array, Schedule_Services_Dev, Database_Services, Work_Order_Services, SRP_Math
Declare function    Epi_Part_Services, Datetime
Declare subroutine  obj_Appwindow, Center_Window, Schedule_Services_Dev, Form_Services, SRP_Show_Window
Declare subroutine  Form_Services, ErrMsg

SubclassInfo    = Form_Services('FindSubclassControl')
Subclass        = SubclassInfo<1>

// Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler.
If Event EQ 'OLE' then
    Transfer Event to OIEvent
    Transfer Param1 to Event
    Transfer Param2 to Param1
    Transfer Param3 to Param2
    Transfer Param4 to Param3
    Transfer Param5 to Param4
    Transfer Param6 to Param5
    Transfer Param7 to Param6
    Transfer Param8 to Param7
end

Type = Get_Property(CtrlEntId, 'TYPE')
If Type EQ 'RADIOBUTTON' then
    Convert ' ' to '_' in CtrlEntID
end

GoToEvent Event for CtrlEntID

Return EventFlow else EVENT_CONTINUE$


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Event WINDOW.CREATE(CreateParam)

    ReactorNo        = CreateParam<1>
    SchedStartDTM    = CreateParam<2>
    Set_Property(@Window, '@SCHED_START_DTM', SchedStartDTM)
    NextStartDTM     = ''
    ReactSchedEvents = Xlate('REACTOR', ReactorNo, 'SCHED_EVENTS', 'X')
    If ReactSchedEvents NE '' then
        LastEventKey    = ReactSchedEvents[-1, 'B':@VM]
        LastSchedDetRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', LastEventKey)
        NextStartDTM    = LastSchedDetRec<SCHED_DET_NG.STOP_DTM$>
    end
    Set_Property(@Window, '@NEXT_START_DTM', NextStartDTM)
    If NextStartDTM NE '' then
        StartDTM  = NextStartDTM
    end else
        StartDTM  = SchedStartDTM
    end
    Set_Property(@Window : '.REACTOR_NO', 'TEXT', ReactorNo)
    Set_Property(@Window : '.SCHEDULE_START_DTM', 'INVALUE', StartDTM)

 	GoSub Setup_OLE_Controls
    GoSub PopulateControls
	Set_Property(@Window : '.CLOSE_BUTTON', 'NEXT', @Window : '.REACTOR_NO')

    SRP_Show_Window(@Window, '', 'C', 'C', 1, '', False$, False$)

end event


Event WINDOW.CLOSE(CancelFlag)

end event


Event SCHEDULE_OPTIONS_DATETIME.NEXT_AVAILABLE.CLICK()
    
    StartDTM = Get_Property(@Window, '@NEXT_START_DTM')
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'INVALUE', StartDTM)
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'ENABLED', False$)
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'BACKCOLOR', OI_DISABLED_GREY$)
    GoSub UpdateWorkOrderDetails
    
end event


Event SCHEDULE_OPTIONS_DATETIME.SPECIFIC_DATE_AND_TIME.CLICK()
    
    StartDTM = Get_Property(@Window, '@SCHED_START_DTM')
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'INVALUE', StartDTM)
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'ENABLED', True$)
    Set_Property(@Window:'.SCHEDULE_START_DTM', 'BACKCOLOR', WHITE$)
    GoSub UpdateWorkOrderDetails
    
end event


Event SCHEDULE_END_DTM.LOSTFOCUS(Flag, FocusID)

    StartDTM = Get_Property(@Window : '.SCHEDULE_START_DTM', 'INVALUE')
    EndDTM   = Get_Property(CtrlEntId, 'INVALUE')
    If StartDTM NE '' AND EndDTM NE '' then
        Days    = EndDTM - StartDTM + 1
        Set_Property(@Window : '.DAYS', 'DEFPROP', Days)
    end

end event


Event SCHEDULE_START_DTM.LOSTFOCUS(Flag, FocusID)

    WorkOrder   = Get_Property(@Window : '.WO_NO', 'TEXT')
    If WorkOrder NE '' then
        GoSub UpdateWorkOrderDetails
    end else
        Set_Property(@Window : '.SCHEDULE_END_DTM', 'INVALUE', '')
    end

end event


Event WO_NO.LOSTFOCUS(Flag, FocusID)

    WONo     = Get_Property(CtrlEntID, 'TEXT')
    OrigWONo = Get_Property(@Window, '@WO_NO')
    If WONo NE OrigWONo then 
        Set_Property(@Window, '@WO_NO', WONo)
        // User changed the value in this control. Update related controls.
        GoSub UpdateCustomerName
        GoSub InitializeProperties
        GoSub UpdateWorkOrderDetails
    end
    
end event


Event SAVE_BUTTON.CLICK()

    ResponseData = '' 
    ReactorNo    = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
    WorkOrder    = Get_Property(@Window : '.WO_NO', 'TEXT')
    StartDTM     = Get_Property(@Window : '.SCHEDULE_START_DTM', 'INVALUE')
    EndDTM       = Get_Property(@Window : '.SCHEDULE_END_DTM', 'INVALUE')
    Description  = Get_Property(@Window : '.DESCRIPTION', 'INVALUE')
    EventQty     = Get_Property(@Window : '.SCHEDULE_WAFERS', 'TEXT')
    ResponseData = ReactorNo : @FM : WorkOrder : @FM : StartDTM : @FM : EndDTM : @FM : Description : @FM : EventQty
    End_Dialog(@Window, ResponseData)

end event


Event CLOSE_BUTTON.CLICK()

    Post_Event(@Window, 'CLOSE')
   
end event


Event OLE_SUBCLASS.OnOptionClick(CtrlId)

    Send_Event(CtrlId, 'OPTIONS')

end event


Event OLE_SUBCLASS.OnComboClick(CtrlId)

    Send_Event(CtrlId, 'LOSTFOCUS')

end event


Event SCHEDULE_WAFERS.CHANGED(NewData)

    SchedQty = NewData
    AvailQty = Get_Property(@Window : '.AVAILABLE_QTY', 'TEXT')
    If SchedQty NE '' then
        If (SchedQty GT AvailQty) then
            Set_Property(CtrlEntID, 'FOCUS', True$)
            Set_Property(CtrlEntID, 'SELECTION', 1 : @FM : 999)
            Message = 'Schedule quantity must be less than or equal to the avialable quantity.'
            Form_Services('DisplayControlMessage', Message, 'Invalid Quantity', CtrlEndID, 'VALIDATION', 'RGB(229,20,0)')
        end else
            GoSub UpdateWorkOrderDetails
        end
    end
    GoSub EnableSaveButton
    
end event


Event SCHEDULE_WAFERS.CHAR(VirtCode, ScanCode, CtrlKey, ShiftKey, AltKey)
    
    Form_Services('CloseControlMessage', CtrlEntId)
*    SchedQty = Get_Property(CtrlEntID, 'TEXT')
*    AvailQty = Get_Property(@Window : '.AVAILABLE_QTY', 'TEXT')
*    If SchedQty GT AvailQty then
*        Set_Property(CtrlEntID, 'FOCUS', True$)
*        Set_Property(CtrlEntID, 'SELECTION', 1 : @FM : 999)
*        Message = 'Schedule quantity must be less than or equal to the avialable quantity.'
*        Form_Services('DisplayControlMessage', Message, 'Invalid Quantity', CtrlEndID, 'VALIDATION', 'RGB(229,20,0)')
*    end else
*        GoSub UpdateWorkOrderDetails
*    end
*    GoSub EnableSaveButton
        
end event


Event SCHEDULE_WAFERS.LOSTFOCUS(Flag, FocusID)
    
*    SchedQty = Get_Property(CtrlEntID, 'TEXT')
*    AvailQty = Get_Property(@Window : '.AVAILABLE_QTY', 'TEXT')
*    If SchedQty GT AvailQty then
*        Set_Property(CtrlEntID, 'FOCUS', True$)
*        Set_Property(CtrlEntID, 'SELECTION', 1 : @FM : 999)
*        Message = 'Schedule quantity must be less than or equal to the avialable quantity.'
*        Form_Services('DisplayControlMessage', Message, 'Invalid Quantity', CtrlEndID, 'VALIDATION', 'RGB(229,20,0)')
*    end else
*        GoSub UpdateWorkOrderDetails
*    end
*    GoSub EnableSaveButton
    
end event


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Setup_OLE_Controls:

    Ctrl        = @Window : '.OLE_SUBCLASS'
    // Get the current reactor type and size so the GetReactor and GetUnscheduledWorkOrders service results can be filtered
    // down to only those items that match the same type and size.
    ReactorNo       = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
    ReactorRec      = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
    ReactorType     = ReactorRec<REACTOR_REACT_TYPE$>
    SusceptorSize   = ReactorRec<REACTOR_SUSC_POCKET_SIZE$>

    EditLine    = @Window : '.WO_NO'
    Handle      = Get_Property(EditLine, 'HANDLE')
    Send_Message(Ctrl, 'OLE.Subclass', Handle, EditLine)
    Combo       = ''
    Combo<1>    = 1
    Combo<2, 1> = 'Work Order' : @TM : 'Epi Part' : @TM : 'Customer' : @TM : 'Reactor Type' : @TM : 'PSN Block'
    Combo<2, 2> = 'L' : @STM : 'DYN' : @TM : 'L' : @STM : 'DYN' : @TM : 'L' : @STM : 'DYN' : @TM : 'L' : @STM : 'DYN' : @TM : 'C' : @STM : 'DYN'
    Combo<2, 3> = ''
    Combo<2, 4> = 1
    Combo<2, 5> = 1
    Combo<2, 6> = 0
    Combo<2, 7> = 40
    Combo<2, 9> = 1
    Combo<2,10> = 0
    Combo<2,11> = 0
    Combo<2,12> = 1
    Combo<2,24> = 0
    EditLine    = @Window : ';WO_NO'
    Set_Property(@Window : '.OLE_SUBCLASS', 'OLE.Combo[' : EditLine : ']', Combo)
 	Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnOptionClick', 1)
 	Send_Message(Ctrl, 'QUALIFY_EVENT', 'OLE.OnComboClick', 1)

return


SelectAll:

    Set_Property(CtrlEntId, 'SELECTION', 1 : @FM : 999)

return


UpdateScheduleDetails:

    ScheduleDetail  = Schedule_Services_Dev('GetScheduleDetail', ScheduleKeyID)
    Set_Property(@Window, '@ORIG_SCHEDULEDETAIL', ScheduleDetail)
    WorkOrder           = Get_Property(@Window : '.WO_NO', 'TEXT')
    If WorkOrder NE '' then
        Set_Property(@Window : '.DESCRIPTION', 'TEXT', ScheduleDetail<SCHED_DET_NG.DESC$>)
    end else
        Set_Property(@Window : '.DESCRIPTION', 'TEXT', '')
    end

return

UpdateCustomerName:

    WoNo            = Get_Property(@Window : '.WO_NO', 'TEXT')
    If WoNo NE '' then
        WorkOrderDetail = Work_Order_Services('GetWorkOrderLogDetail', WONo)
        CustNo          = WorkOrderDetail<WO_LOG_CUST_NO$>
        CompanyRow      = Database_Services('ReadDataRow', 'COMPANY', CustNo)
        CustName        = CompanyRow<42>
    end else
        CustName        = ''
    end
    Set_Property(@Window : '.CUSTOMER_NAME', 'TEXT', CustName)

return


UpdateReactorDetails:

    ReactorNo       = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
    If Index(ReactorNo, '/', 1) then
        // EpiPro reactors formatted as such, "40/42". We must truncate the reactor number to the first reactor.
        ReactorNo = Field(ReactorNo, '/', 1, 1)
        Set_Property(@Window : '.REACTOR_NO', 'TEXT', ReactorNo)
    end
    ReactorDetails  = Schedule_Services_Dev('GetReactorDetails', ReactorNo)
    ReactorType     = ReactorDetails<REACTOR_REACT_TYPE$>
    Begin Case
        Case ReactorType _EQC 'EPP' ; ReactorType = 'EpiPro'
        Case ReactorType _EQC 'GAN' ; ReactorType = 'GaN'
    End Case
    Set_Property(@Window : '.REACTOR_TYPE', 'TEXT', ReactorType)
    Set_Property(@Window : '.REACTOR_SIZE', 'TEXT', ReactorDetails<REACTOR_SUSC_POCKET_SIZE$>)
    FutureEvents    = Schedule_Services_Dev('GetScheduleEvents', Date() + 1, '', ReactorNo, '', False$)
    Set_Property(@Window, '@FUTURE_EVENTS', FutureEvents)

return


InitializeProperties:

    WorkOrder               = Get_Property(@Window : '.WO_NO', 'TEXT')
    ReactNo                 = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
    ReactorType             = Get_Property(@Window : '.REACTOR_TYPE', 'TEXT')
    WorkOrderDetail         = Work_Order_Services('GetWorkOrderLogDetail', WorkOrder)
    RemainingToProcess      = Work_Order_Services('GetUnprocessedWafers', WorkOrder)
    RemainingToSchedule     = Schedule_Services_Dev('GetUnscheduledWfrQty', WorkOrder)
    EpiPart                 = WorkOrderDetail<WO_LOG_EPI_PART_NO$>
    MinutesPerWaferAdjusted = Epi_Part_Services('GetAdjustedWafersPerDayScheduler', EpiPart, ReactorType)
    ScheduledWfrQty         = Schedule_Services_Dev('GetScheduledWfrQty', WorkOrder)
    WOSchedCass             = Schedule_Services_Dev('GetScheduledCassettes', WorkOrder)
    Set_Property(@Window, '@WORK_ORDER_DETAIL', WorkOrderDetail)
    Set_Property(@Window, '@REMAINING_TO_PROCESS', RemainingToProcess)
    Set_Property(@Window, '@REMAINING_TO_SCHEDULE', RemainingToSchedule)
    Set_Property(@Window, '@MINUTES_PER_WAFER_ADJUSTED', MinutesPerWaferAdjusted)
    Set_Property(@Window, '@SCHEDULED_WFR_QTY', ScheduledWfrQty)
    Set_Property(@Window, '@WO_SCHED_CASS', WOSchedCass)
    
return


UpdateWorkOrderDetails:

    MinutesPerWaferAdjusted = ''
    WorkOrder               = Get_Property(@Window : '.WO_NO', 'TEXT')
    ReactNo                 = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
    CurrDTM                 = Datetime()
    If WorkOrder NE '' then
        PSNBlocked      = False$
        WorkOrdersArray = Get_Property(@Window, '@UNSCHEDULED_WORK_ORDERS')
        Convert @TM to @FM in WorkOrdersArray
        Convert @STM to @VM in WorkOrdersArray
        WorkOrderList   = WorkOrdersArray<1>
        PSNBlockedList  = WorkOrdersArray<5>
        Locate WorkOrder in WorkOrderList using @VM setting vPos then PSNBlocked = PSNBlockedList<0, vPos>
        If PSNBlocked EQ '' then
            Set_Property(@Window:'.LBL_PSN_BLOCK', 'VISIBLE', False$)
            WorkOrderDetail     = Get_Property(@Window, '@WORK_ORDER_DETAIL')
            EpiPart             = WorkOrderDetail<WO_LOG_EPI_PART_NO$>
            TotalWafers         = WorkOrderDetail<WO_LOG_WO_QTY$>
            RemainingToProcess  = Get_Property(@Window, '@REMAINING_TO_PROCESS')
            RemainingToSchedule = Get_Property(@Window, '@REMAINING_TO_SCHEDULE')
            If TotalWafers GT 0 then
                Complete = ( (TotalWafers - RemainingToProcess) / TotalWafers) * 100
            end else
                Complete = 0
            end
            ReactorType             = Get_Property(@Window : '.REACTOR_TYPE', 'TEXT')
            MinutesPerWaferAdjusted = Get_Property(@Window, '@MINUTES_PER_WAFER_ADJUSTED')
            ScheduledWfrQty         = Get_Property(@Window, '@SCHEDULED_WFR_QTY')
            AvailableWfrQty         = RemainingToSchedule
            EventWafers             = Get_Property(@Window:'.SCHEDULE_WAFERS', 'TEXT')
            If ( (EventWafers EQ '') and (MinutesPerWaferAdjusted NE '') ) then
                EventWafers = AvailableWfrQty
                Set_Property(@Window : '.SCHEDULE_WAFERS', 'TEXT', AvailableWfrQty)
            end
            
            // Are any cassettes already engaged?
            WOSchedCass  = Get_Property(@Window, '@WO_SCHED_CASS')
            WOLastCass   = WOSchedCass[-1, 'B':@VM]
            CassNo       = WOLastCass + 1
            EpiPro       = (Xlate('WO_LOG', WorkOrder, 'REACT_TYPE', 'X') EQ 'EPP')
            EventEngaged = False$
            RDSNo        = ''

*            If @User4 EQ 'DANIEL_ST' then
                ! New Code - UAT began 11/10/2021
                TotalCass = SRP_Math('CEILING', (TotalWafers / 25))
    
                If WOSchedCass NE '' then
                    WOLastCass   = WOSchedCass[-1, 'B':@VM]
                end else
                    WOLastCass   = 0
                end
                
                UnprocessedCassettes                        = ''
                ProcessedCassettes                          = ''
                For CassIndex = 0 to TotalCass
                    CurrStatus    = ''
                    Skip          = False$
                    CassProcessed = False$
                    CassNo        = WOLastCass + CassIndex
                    If CassNo GT 0 then
                        RDSNo         = ''
                        // Is this cassette processed?
                        If EpiPro then
                            // EpiPro --- Get WM_IN record and see if it has any wafers remaining.
                            WMIKey  = WorkOrder:'*1*':CassNo
                            RemWfrs = Xlate('WM_IN', WMIKey, 'REM_WFRS', 'X')
                            If RemWfrs EQ 0 then CassProcessed = True$
                        end else
                            // Non-EpiPro --- Get RDS number and check if DATE_OUT is populated
                            WOMatKey = WorkOrder:'*':CassNo
                            RDSNo    = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
                            If CassIndex EQ 0 then
                                // This is necessary as we had to set CassIndex = 0 for EpiPro.
                                // EpiPro can cassettes can be in two different work order events.
                                Skip = True$
                            end
                            CurrStatus = Xlate('WO_MAT', WOMatKey, 'CURR_STATUS', 'X')
                        end
                        If ( (RDSNo NE '') and (CurrStatus NE '') ) then
                            DateOut = Xlate('RDS', RDSNo, 'DATE_OUT', 'X')
                            If ( (DateOut NE '') or (CurrStatus EQ 'REJ') or (CurrStatus EQ 'MT') ) then CassProcessed = True$
                        end
                        If Skip EQ False$ then
                            If CassProcessed then
                                ProcessedCassettes<0, -1> = CassNo
                            end else
                                UnProcessedCassettes<0, -1> = CassNo
                            end
                        end
                    end
                Next CassIndex
                CassToSched = SRP_Array('Join', UnprocessedCassettes, ProcessedCassettes, 'OR', @VM)
                CassToSched = SRP_Array('SortSimpleList', CassToSched, 'AscendingNumbers', @VM)
                WOMatKeys   = ''
                For each SchedCassNo in CassToSched using @VM setting vPos
                    WOMatKeys<0, vPos> = WorkOrder:'*':SchedCassNo
                Next SchedCassNo
*                SchedRDSNos  = Xlate('WO_MAT', WOMatKeys, 'RDS_NO', 'X')

                If EpiPro then
                    FirstCass = CassToSched<0, 1>
                    If FirstCass NE '' then
                        WMIKey      = WorkOrder:'*1*':FirstCass
                        SchedRDSNos = Xlate('WM_IN', WMIKey, 'RDS_NO', 'X')
                        // Look at the next slot to be scheduled!
                        SchedSlot   = Mod(ScheduledWfrQty, 25) + 1
                        SchedRDSNos = Field(SchedRDSNos, @VM, SchedSlot, (25 - SchedSlot))
                    end
                end else
                    SchedRDSNos  = Xlate('WO_MAT', WOMatKeys, 'RDS_NO', 'X')
                end
        

                SchedDateIns = Xlate('RDS', SchedRDSNos, 'DATE_IN', 'X')
                If SchedDateIns NE '' then
                    FirstLoad    = ''
                    For each SchedDateIn in SchedDateIns using @VM setting vPos
                        If SchedDateIn NE '' then
                            RDSNo        = SchedRDSNos<0, vPos>
                            EventEngaged = True$
                        end
                    Until EventEngaged EQ True$
                    Next SchedDateIn
                end
*            end else
*                ! Old code
*                // Is this cassette processed?
*                If EpiPro then
*                    // EpiPro --- Get WM_IN record and see if RDS in slot 1 has DATE_IN field populated
*                    WMIKey = WorkOrder:'*1*':CassNo
*                    RDSNos = Xlate('WM_IN', WMIKey, 'RDS_NO', 'X')
*                    RDSNo  = RDSNos<0, 1>
*                end else
*                    // Non-EpiPro --- Get RDS number and check if DATE_IN is populated
*                    WOMatKey = WorkOrder:'*':CassNo
*                    RDSNo    = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
*                end
*                If RDSNo NE '' then
*                    DateIn = Xlate('RDS', RDSNo, 'DATE_IN', 'X')
*                    If DateIn NE '' then EventEngaged = True$
*                end
*            end
            If EventEngaged EQ True$ then
                // Set the start DTM of this event to the DATETIME_IN of the first cassette that was loaded.
                StartDTM             = Xlate('RDS', RDSNo, 'DATETIME_IN', 'X')
                
                ! This needs to be updated to support EpiPro logic. We need to look at the datetime_in
                ! of the first remaining wafer (RDS), not the first wafer (RDS) in the WM_IN cassette as
                ! it may have already been processed.
                
                // Disable Start Date Options Group
                Set_Property(@Window:'.OPTIONS_GRP_START_DTM', 'ENABLED', False$)
                
                // Calculate the end DTM based on the number of wafers remaining to process.
                // Round up in case the number of wafers is not a multiple of 25.
                EventCassettes       = SRP_Math('CEILING', (EventWafers / 25))
                ProcessedCassettes   = ''
                UnprocessedCassettes = ''
                
                
                
                For CassIndex = 1 to EventCassettes
                    CassProcessed = False$
                    CassNo        = WOLastCass + CassIndex
                    RDSNo         = ''
                    // Is this cassette processed?
                    If EpiPro then
                        // EpiPro --- Get WM_IN record and see if RDS in slot 25 has DATE_OUT field populated
                        WMIKey = WorkOrder:'*1*':CassNo
                        RDSNos = Xlate('WM_IN', WMIKey, 'RDS_NO', 'X')
                        RDSNo  = RDSNos<0, 25>
                    end else
                        // Non-EpiPro --- Get RDS number and check if DATE_OUT is populated
                        WOMatKey = WorkOrder:'*':CassNo
                        RDSNo    = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
                        CurrStatus = CurrStatus = Xlate('WO_MAT', WOMatKey, 'CURR_STATUS', 'X')
                    end
                    If RDSNo NE '' then
                        DateOut    = Xlate('RDS', RDSNo, 'DATE_OUT', 'X')
                        If ( (DateOut NE '') or (CurrStatus EQ 'REJ') or (CurrStatus EQ 'MT') ) then CassProcessed = True$
                    end
                    If CassProcessed then
                        ProcessedCassettes<0, -1> = CassNo
                    end else
                        UnprocessedCassettes<0, -1> = CassNo
                    end
                Next CassIndex
                UnprocessedWfrQty = 0
                For each UnprocCassNo in UnprocessedCassettes using @VM setting vPos
                    WOMatKey           = WorkOrder:'*':UnprocCassNo
                    If RowExists('WO_MAT', WOMatKey) then
                        CassQty            = Xlate('WO_MAT', WOMatKey, 'WAFER_QTY', 'X')
                        UnprocessedWfrQty += CassQty
                    end else
                        // Material for this cassette has not yet been released. Assume quantity of 25 wafers.
                        UnprocessedWfrQty += 25
                    end
                Next UnprocCassNo
                DurationEstimate  = Schedule_Services_Dev('GetEventDuration', WorkOrder, UnprocessedWfrQty)
                If Error_Services('NoError') then
                    EndDTM = CurrDTM + DurationEstimate
                end
            end else
                // Event not engaged yet. Use previous event's end DTM unless it is in the past.
                // In that event use the current DTM.
                Set_Property(@Window:'.OPTIONS_GRP_START_DTM', 'ENABLED', True$)
                NextStartDTM     = Get_Property(@Window, '@NEXT_START_DTM')
                CurrDTM          = Datetime()
                If NextStartDTM GT CurrDTM then
                    StartDTM = NextStartDTM
                end else
                    StartDTM = CurrDTM
                end
                // Calculate End DTM based on the start DTM in the form and duration estimate
                DurationEstimate = Schedule_Services_Dev('GetEventDuration', WorkOrder, EventWafers)
                Set_Property(@Window:'.SCHEDULE_START_DTM', 'INVALUE', StartDTM)
                EndDTM           = StartDTM + DurationEstimate
            end
            
            If MinutesPerWaferAdjusted EQ '' then
                Msg(@Window, 'Warning: ' : EpiPart : ' appears to be missing minutes per wafer values for ' : ReactorType)
                Set_Property(@Window:'.CLOSE_BUTTON', 'FOCUS', True$)
            end
        end else
            // PSN Blocked
            Set_Property(@Window:'.LBL_PSN_BLOCK', 'VISIBLE', True$)
        end
    end

    If ( (WorkOrder NE '') and (MinutesPerWaferAdjusted NE '') ) then
        Set_Property(@Window : '.EPI_PART', 'TEXT', EpiPart)
        Set_Property(@Window : '.TOTAL_WAFERS', 'TEXT', TotalWafers)
        Set_Property(@Window : '.TOTAL_REMAINING', 'TEXT', RemainingToProcess)
        Set_Property(@Window : '.PERCENT_COMPLETE', 'TEXT', Oconv(Complete, 'MD0[ %]S'))
        Set_Property(@Window : '.SCHEDULE_START_DTM', 'INVALUE', StartDTM)
        Set_Property(@Window : '.SCHEDULE_END_DTM', 'INVALUE', EndDTM)
        DurationDaysRounded = SRP_Math('ROUND', DurationEstimate, 1)
        Set_Property(@Window : '.DAYS', 'DEFPROP', DurationDaysRounded)
        Set_Property(@Window : '.AVAILABLE_QTY', 'TEXT', AvailableWfrQty)
    end else
        Error_Services('DisplayError')
        Set_Property(@Window : '.EPI_PART', 'TEXT', '')
        Set_Property(@Window : '.TOTAL_WAFERS', 'TEXT', '')
        Set_Property(@Window : '.TOTAL_REMAINING', 'TEXT', '')
        Set_Property(@Window : '.SCHEDULE_WAFERS', 'TEXT', '')
        Set_Property(@Window : '.PERCENT_COMPLETE', 'TEXT', '')
        Set_Property(@Window : '.SCHEDULE_END_DTM', 'INVALUE', '')
        Set_Property(@Window : '.DAYS', 'DEFPROP', '')
    end
    
    GoSub EnableSaveButton

return


UpdateWorkOrderList:

    WorkOrders  = ''
    // Adding work order.
    WorkOrders  = Get_Property(@Window, '@UNSCHEDULED_WORK_ORDERS')
    If WorkOrders EQ '' then
        // Get the current reactor type and size so the GetReactor and GetUnscheduledWorkOrders service results 
        // can be filtered down to only those items that match the same type and size.
        ReactorNo     = Get_Property(@Window : '.REACTOR_NO', 'TEXT')
        ReactorRec    = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
        ReactorType   = ReactorRec<REACTOR_REACT_TYPE$>
        SusceptorSize = ReactorRec<REACTOR_SUSC_POCKET_SIZE$>
        WorkOrders    = Schedule_Services_Dev('GetAvailableWorkOrders', ReactorType, '', ReactorNo)
        WorkOrders    = SRP_Array('Rotate', WorkOrders)
        Convert @FM to @TM in WorkOrders
        Convert @VM to @STM in WorkOrders
        Set_Property(@Window, '@UNSCHEDULED_WORK_ORDERS', WorkOrders)
    end
    EditLine    = @Window : ';WO_NO'
    Set_Property(@Window : '.OLE_SUBCLASS', 'OLE.ComboData[' : EditLine : ']', WorkOrders)

return


PopulateControls:
    
    Set_Property(@Window, 'TEXT', 'Scheduler Actions - Add Work Order Event')
    Set_Property(@Window : '.REACTOR_NO', 'NEXT', @Window : '.SCHEDULE_START_DTM')
    Set_Property(@Window : '.DESCRIPTION', 'NEXT', @Window : '.REACTOR_NO')
    WorkOrders     = Get_Property(@Window, '@UNSCHEDULED_WORK_ORDERS')
    WONo           = ''
    ScheduleKeyID  = ''
    GoSub UpdateWorkOrderList
    GoSub UpdateScheduleDetails
    GoSub UpdateReactorDetails
    GoSub UpdateCustomerName
    GoSub EnableSaveButton
    Set_Property(@Window : '.REACTOR_NO', 'FOCUS', True$)
    
return


EnableSaveButton:

    PSNBlocked    = Get_Property(@Window:'.LBL_PSN_BLOCK', 'VISIBLE')
    SchedQty      = Get_Property(@Window : '.SCHEDULE_WAFERS', 'TEXT')
    AvailQty      = Get_Property(@Window : '.AVAILABLE_QTY', 'TEXT')
    ButtonEnabled = ( (SchedQty NE '') and (SchedQty NE 0) and (AvailQty NE 0) and (SchedQty LE AvailQty) and (PSNBlocked EQ False$) )
    Set_Property(@Window : '.SAVE_BUTTON', 'ENABLED', ButtonEnabled)
    
return


