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') 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 = True$ 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 MesageAcked = Message_Box(@Window, Message, "Test Wafer Required", MSG_BTN_OK$ + MSG_ICON_EXCLAM$) WoMatRecord = True$ Database_Services('WriteDataRow', 'WO_MAT', WoMatKey, WoMatRecord, True$, False$, False$) ConfirmNote = 'Test wafer requirement acknowledged. [RDS:' : RDSNo : '], [WO:' : WONo : '], [Cassette:' : CassNo : ']' Reactor_Log_Services('AddComment', Reactor, ConfirmNote, @User4) end end end end QA_Services('SignUnloadStage', RDSNo, @User4) 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 Sigs = WOMatRec SigDTMs = WOMatRec If ReactorType NE 'EPP' then Locate '1UNLOAD' in SigProf using @VM setting vPos then Sigs<1, vPos> = '' SigDTMs<1, vPos> = '' WOMatRec = Sigs WOMatRec = 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 columns) InvActions = WOMatRec Locate '1UNLOAD' in InvActions using @VM setting vPos then WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 0, vPos, 0) WOMatRec = Delete(WOMatRec, 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 = False$ WoMatRecord = 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