Function RDS_Unload_Events(CtrlEntId, Event, @PARAMS)
/***********************************************************************************************************************

    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        :   RDS_Unload_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)
        03/26/19    djs     Created initial commuter module.
        06/13/24	djm		Add new stage-specific supplement system.
                            

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

#pragma precomp SRP_PreCompiler
#Window RDS_UNLOAD
      
$insert APP_INSERTS
$insert EVENT_SETUP
$insert MSG_EQUATES
$insert RDS_EQUATES
$insert LSL_USERS_EQUATES
$insert PROD_SPEC_EQUATES
$insert WO_MAT_EQUATES
$insert SURFACE_SCAN_EQUATES
$insert REACTOR_EQUATES
$insert PRS_STAGE_EQUATES
$insert COMPANY_EQUATES
$insert WO_MAT_QA_EQUATES
$insert REACT_STATUS_EQUATES
$insert SUPPL_INFO_ARRAY_EQU
$insert CLEAN_INSP_EQUATES
$insert REACT_STATE_EQUATES
$insert REACT_RUN_EQUATES
$insert REACT_ITEM_EQUATES
$Insert MESSAGE_BOX_EQUATES

Equ COL$LOG_FILE        to 1
Equ COL$LOG_DTM         to 2
Equ COL$ACTION          to 3
Equ COL$WH_CD           to 4
Equ COL$LOC_CD          to 5
Equ COL$WO_NOS          to 6
Equ COL$CASS_NOS        to 7
Equ COL$USER_ID         to 8
Equ COL$TAGS            to 9
Equ COL$TOOL_ID         to 10

Equ COL$MET_TEST        to 1    ; // QA Metrology control on RDS_UNLOAD & RDS_POST_EPI windows
Equ COL$MET_TEST_DESC   to 2
Equ COL$MET_SLOT        to 3
Equ COL$MET_SLOT_DESC   to 4
Equ COL$MET_WFR_QTY     to 5
Equ COL$MET_MIN         to 6
Equ COL$MET_MAX         to 7
Equ COL$MET_RESULT      to 8
Equ COL$MET_STD_MAX     to 9
Equ COL$MET_STD_RESULT  to 10
Equ COL$MET_SIG         to 11
Equ COL$MET_SIG_DTM     to 12

* Clean Insp Actions

Equ ACTION$ACTIONS				TO 1	;* Data structures for each action
Equ ACTION$SIGS					TO 2
Equ ACTION$SIG_DTMS				TO 3
Equ ACTION$TOOLS				TO 4
Equ ACTION$SPEC_CLEAN_TOOL		TO 5
Equ ACTION$SPEC_MICROSCOPE		TO 6
Equ ACTION$SPEC_BRIGHTLIGHT		TO 7
Equ ACTION$SPEC_SURFSCAN_RECIPE	TO 8

Declare subroutine ErrMsg, Set_Status, obj_WO_Mat, obj_WO_Mat_Log, obj_RDS, Set_Property, Send_Event, Database_Services
Declare subroutine Dialog_Box, Msg, MemberOf, obj_WO_Mat, Get_Property, obj_React_Status, Get_Status, Override_Services
Declare subroutine record_lock, obj_React_Status, Post_Event, obj_React_State, obj_Post_Log, Qa_Services, Reactor_Services
Declare Subroutine Rds_Services, WO_MAT_Services, Message_Box, Reactor_Log_Services, Schedule_Services

Declare function   dialog_box, msg, Get_Status, obj_WO_Mat, Get_Status, obj_Clean_Insp, obj_Reactor, Get_Property
Declare function   QA_Services, Database_Services, Set_Property, Rds_Services, Qa_Services, Memberof, Reactor_Services
Declare function Supplement_Services, WO_MAT_Services, Message_Box, Reactor_Log_Services, Schedule_Services

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

GoToEvent Event for CtrlEntID

Return EventFlow else EVENT_CONTINUE$


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

Event WINDOW.CREATE(CreateParam)
    
    GoSub Setup_OLE_Controls

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

end event


Event WINDOW.READ()

end event


Event WINDOW.CLOSE(CancelFlag)

end event


Event WINDOW.CLEAR(bSaveKey, bSuppressWarning, bMaintainFocus, CtrlIDFocus)

end event


Event SUPPL_BUTTON.CLICK()
	
	RDSNo = Get_Property(@Window:'.RDS_NO', 'TEXT')
	Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: 'UNLOAD' :@FM: FALSE$)
	
end event


Event OP_OUT_DATE.LOSTFOCUS(Flag, FocusID)
    
    UnloadDt   = IConv(Get_Property(CtrlEntID, 'TEXT'), 'D')
    RDSNo      = Get_Property(@Window:'.RDS_NO', 'TEXT')
    LoadDt     = Xlate('RDS', RDSNo, 'DATE_IN', 'X')
    Runtime    = UnloadDt - LoadDt
    Today      = Date()
    Error      = True$
    ErrorMsg   = 'Invalid UNLOAD date ':OConv(UnloadDt, 'D/'):'! '
    Supervisor = Memberof(@User4, 'SUPERVISOR')
    Lead       = Memberof(@User4, 'LEAD')
    Begin Case
        Case UnloadDt GT Today
            ErrorMsg := 'Unload date cannot be in the future!'
            
        Case ( (Runtime GT 2) and Not(Supervisor or Lead) )
            ErrorMsg := 'Unload date must be within two days of the LOAD date ':OConv(LoadDt, 'D/'):'.'
            
        Case ( (Runtime GT 2) and (Supervisor or Lead) )
            Override_Services('SetOverride', 'RDS', RDSNo, 'UNLOAD_DTM', @User4)
            Error = False$
            
        Case UnloadDt LT LoadDt
            ErrorMsg := 'Unload date cannot be less than the LOAD date ':OConv(LoadDt, 'D/'):'.'
        
        Case Otherwise$
            Error = False$
    End Case
    
    If Error then
        ErrMsg(ErrorMsg)
        // Return focus to control and highlight the invalid date entered.
        Set_Property(CtrlEntID, 'FOCUS', True$)
        Set_Property(CtrlEntID, 'SELECTION', 1:@FM:65534)
    end
    
end event


Event PUB_SIGN.CLICK()
	
	SignEventType = Get_Property(CtrlEntID, 'TEXT')
	WONo          = Get_Property(@Window:'.WO','DEFPROP')
	CassNo        = Get_Property(@Window:'.CASS_NO','DEFPROP')
	WOStep        = Get_Property(@Window:'.WO_STEP','DEFPROP')
	RDSNo         = Get_Property(@Window:'.RDS_NO','TEXT')
	Reactor       = Get_Property(@Window:'.REACTOR', 'TEXT')
	
	Preauthenticated = FALSE$
	Begin Case
		Case SignEventType EQ 'Sign'
			
			LWIInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ', 'X')
			If LWIInstAckReq EQ True$ then
				Response = RDS_Services('RDSVerifyInst', RDSNo, 'LWI')
				If Response EQ False$ then return
			end
			
			UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ', 'X')
			If UnloadInstAckReq EQ True$ then
				Response = RDS_Services('RDSVerifyInst', RDSNo, 'UNLOAD')
				If Response EQ False$ then return
			end
			
			PostInstAckReq = Xlate('RDS', RDSNo, 'POST_INST_ACK_REQ', 'X')
			If PostInstAckReq EQ True$ then
				Response = RDS_Services('RDSVerifyInst', RDSNo, 'POST')
				If Response EQ False$ then return
			end
			
			SupplAckReq = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD')
			IF (SupplAckReq NE FALSE$) then
				Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: 'UNLOAD' :@FM: FALSE$)
				If Response EQ False$ then
					return
				end else
					Preauthenticated = TRUE$
				end
			end
			
			Override    = False$
			ReadyToSign = QA_Services('UnloadSignatureReady', RDSNo, @User4, Reactor)
			If Error_Services('HasError') then
				ErrorMsg = Error_Services('GetMessage')
				If ErrorMsg EQ 'Cassette runtime exceeds three days! An override by a LEAD or SUPERVISOR is required.' then
					// Prompt for override
					Response = Msg(@Window, '', 'OVERRIDE', '', ErrorMsg)
					
					Begin Case
						Case Response EQ 1
							Response = True$        ; // User Clicked Override
						Case Response EQ 2
							Response = False$       ; // User Clicked Cancel
						Case Response EQ char(27)
							Response = False$       ; // User Pressed Escape Key
					End Case            
					
					If Response EQ True$ then
						OverrideGroups  = 'LEAD' : @VM : 'SUPERVISOR'
						Response        = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : OverrideGroups)
						Valid           = Response<1>
						Username        = Response<2>
						If Valid then
							Override_Services('SetOverride', 'RDS', RDSNo, 'UNLOAD_DTM', Username)
							ReadyToSign = True$
							Override    = True$
						end
					end
				end
			end
			If (ReadyToSign EQ True$) then
				If Preauthenticated EQ False$ Then
					If Override EQ False$ then
						Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW)
						Valid    = Response<1>
					end
				end else
					Valid = True$
				end
				If (Valid EQ True$) then
					ReactorType = XLATE('RDS',RDSNo,'REACTOR_TYPE','X')
					ErrMsg = ''
					If Len(ReactorType) GE 3 and ReactorType[1, 3] _EQC 'HTR' then
						WoMatKey = WONo:'*':CassNo
						IsLastCassetteInWo = WO_MAT_Services('CassetteIsLastInWo', WoMatKey)
						If Error_Services('NoError') then
							If IsLastCassetteInWo then
								NextEventScheduled = False$
								NextEventHasSamePsn = True$
								NextEventIsBlock = False$
								
								NextScheduledEvent = Schedule_Services('GetNextEvent', Reactor)
								If Error_Services('NoError') then
									NextEventScheduled = True$
									
									NextEventHasSamePsn = Schedule_Services('NextEventIsSamePsn', Reactor)
									NextEventIsBlock = Schedule_Services('NextEventIsBlock', Reactor)
								end
								
								If NextEventScheduled EQ False$ or NextEventHasSamePsn EQ False$ or NextEventIsBlock EQ True$ then
									WoMatRecord = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey)
									WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_ACK_REQ$> = True$
									
									TestWaferRanSinceLoad = WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_RAN$>
									
									If TestWaferRanSinceLoad NE True$ then
										TestWaferRanSinceLoad = Rds_Services('TestWaferRanAfterLoad', RDSNo)
										WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_RAN$> = TestWaferRanSinceLoad
										
										If TestWaferRanSinceLoad NE True$ then
											Message = ''
											If NextEventScheduled EQ False$ or NextEventIsBlock EQ True$ then
												Message = 'No material scheduled. Test wafer required.'
											end else if NextEventHasSamePsn EQ False$ then
												Message = 'Next work order is a NEW PSN number. Test wafer required.'
											end
											
											Message_Box(@Window, Message, "Test Wafer Required", MSG_BTN_OK$ + MSG_ICON_EXCLAM$)
											
											TWLogResult = Dialog_Box('NDW_LOG_TEST_WAFER_USAGE', @Window, RDSNo : @VM : '' : @VM : 'REACTOR' : @VM :  Reactor)
											
											WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_RAN$> = TWLogResult
											
											If TWLogResult NE True$ then
												ErrMsg = 'Unload blocked! You must run a test wafer before signing the unload'
											end
										end
									end
								end
								Database_Services('WriteDataRow', 'WO_MAT', WoMatKey, WoMatRecord, True$, False$, False$)
							end
						end
					end
					
					If ErrMsg NE '' then
						Error_Services('Add', ErrMsg)
					end
					
					If Error_Services('NoError') then
						QA_Services('SignUnloadStage', RDSNo, @User4)
					end
				end
			end
			If Error_Services('HasError') then
				ErrorMsg = Error_Services('GetMessage')
				ErrMsg(ErrorMsg)
			end
			Set_Property(@Window, 'SAVEWARN', False$)
			Send_Event(@Window, 'READ')
			
		Case SignEventType EQ 'Unsign'
			
			// 1. Check if on hold. If so, then block event and inform user
			WOMatKey = WONo:'*':CassNo
			WOMatCurrStatus = obj_WO_Mat('CurrStatus',WOMatKey)
			IF WOMatCurrStatus = 'HOLD' THEN
				ErrorMessage  = 'Process Error':@SVM:'Cassette is on Hold and may not be signed off.':CRLF$:CRLF$
				ErrMsg(ErrorMessage)
				RETURN 0
			END
			Reactor          = XLATE('RDS',RDSNo,'REACTOR','X')
			// 2. Check if the reactor will have enough capacity to load this lot. If not then block the event and
			// inform user.
			CurrChamberCount = Reactor_Services('GetReactorAvailChamberCount', Reactor)
			If CurrChamberCount LE 0 then
				ErrorMessage  = 'Process Error':@SVM:'Reactor ' : Reactor : ' does not have the capacity for this lot.' :CRLF$:CRLF$
				ErrMsg(ErrorMessage)
				RETURN 0
			end
			// 3.
			//   a. For Non-EPP - Check if LWII, LWIS, or FQA has been signed. If so, then block event and inform user           
			//   b. For EPP - Check Clean_Insp actions to see if an inspection or surfscan has been completed
			//           Also check the FQA signature (MO_QA)
			ReactorType      = XLATE('RDS',RDSNo,'REACTOR_TYPE','X')
			CISigs           = Xlate('RDS', RDSNo, 'LWI_CI_SIG', 'X')
			Convert @VM to '' in CISigs
			IF ReactorType NE 'EPP' THEN               
				FQASig = Xlate('RDS', RDSNo, 'SUP_VER_SIG', 'X')                
			END ELSE
				WMOutKey = Xlate('RDS', RDSNo, 'WM_OUT_KEY', 'X')
				FQASig   = Xlate('WM_OUT', WMOutKey, 'SUP_VER_SIG', 'X')
			END
			If (CISigs NE '') or (FQASig NE '') then
				// LWII, LWIS, or FQA already signed. Block unload unsign event.
				ErrorMessage  = 'Process Error':@SVM:'LWII, LWIS, or FQA already signed. Cannot unsign unload event.' |
				: CRLF$ : CRLF$
				ErrMsg(ErrorMessage)
				Return 0
			end
			// 3. LEAD/SUPERVISOR standard override
			Response     = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : 'LEAD' : @VM : 'SUPERVISOR')
			Valid        = Response<1>
			OverrideUser = Response<2>
			If Valid then
				
				// 4. Remove RDS Unload signature, date, and time
				Set_Property(@Window:'.OP_OUT', 'TEXT', '')
				Set_Property(@Window:'.OP_OUT_NAME', 'TEXT', '')
				Set_Property(@Window:'.OP_OUT_DATE', 'TEXT', '')
				Set_Property(@Window:'.OP_OUT_TIME', 'TEXT', '')
				IOOptions = Get_Property(@Window, 'IOOPTIONS')
				IOOptions<6> = True$
				Set_Property(@Window, 'IOOPTIONS', IOOptions)
				Send_Event(@Window, 'WRITE')
				IOOptions<6> = False$
				Set_Property(@Window, 'IOOPTIONS', IOOptions)
				
				// 5. Remove WO_MAT Unload signature, date, and time
				WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
				
				SigProf  = WOMatRec<WO_MAT_SIG_PROFILE$>
				Sigs     = WOMatRec<WO_MAT_SIGNATURE$>
				SigDTMs  = WOMatRec<WO_MAT_SIG_DTM$>
				
				If ReactorType NE 'EPP' then
					Locate '1UNLOAD' in SigProf using @VM setting vPos then
						Sigs<1, vPos>    = ''
						SigDTMs<1, vPos> = ''
						WOMatRec<WO_MAT_SIGNATURE$> = Sigs
						WOMatRec<WO_MAT_SIG_DTM$>   = SigDTMs
					end
					Reactor_Services('DecrementWfrMetrics', RDSNo)
				end
				
				// Added by JRO
				obj_React_Status('HandleUnloadUnsign',Reactor:@RM:WONo:@RM:CassNo:@RM:RDSNo:@RM:OverrideUser)
				Rds_Services('AddComment', RDSNo, 'Unload Stage unsigned from Reactor ' : Reactor)
				// 6. Remove '1UNLOAD' material log entry (i.e. WO_MAT<INV...> columns)
				InvActions = WOMatRec<WO_MAT_INV_ACTION$>
				Locate '1UNLOAD' in InvActions using @VM setting vPos then
					WOMatRec<WO_MAT_INV_WH$>         = Delete(WOMatRec<WO_MAT_INV_WH$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_LOCATION$>   = Delete(WOMatRec<WO_MAT_INV_LOCATION$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_ACTION$>     = Delete(WOMatRec<WO_MAT_INV_ACTION$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_DTM$>        = Delete(WOMatRec<WO_MAT_INV_DTM$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_USER$>       = Delete(WOMatRec<WO_MAT_INV_USER$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_TAG$>        = Delete(WOMatRec<WO_MAT_INV_TAG$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_TOOL_ID$>    = Delete(WOMatRec<WO_MAT_INV_TOOL_ID$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_LOC$>        = Delete(WOMatRec<WO_MAT_INV_LOC$>, 0, vPos, 0)
					WOMatRec<WO_MAT_INV_SCAN_ENTRY$> = Delete(WOMatRec<WO_MAT_INV_SCAN_ENTRY$>, 0, vPos, 0)
				end
				Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$)
				
				WoMatKey = WONo:'*':CassNo
				WoMatRecord = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey)
				
				WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_ACK_REQ$> = False$
				WoMatRecord<WO_MAT_LAST_CASSETTE_TEST_WAFER_ACKED$> = False$
				
				Database_Services('WriteDataRow', 'WO_MAT', WoMatKey, WoMatRecord, True$, False$, False$)
				
				Set_Property(@Window:'.PUB_SIGN', 'TEXT', 'Sign')    
			end else
				Return 0               
			end           
	End Case
	
end event

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

Setup_OLE_Controls:

return





