open-insight/LSL2/STPROC/SCHEDULER_ACTIONS_DEV_EVENTS.txt
2024-05-22 14:06:46 -07:00

701 lines
30 KiB
Plaintext

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