Function RDS_Actions(Action, CalcColName, FSList, Handle, Name, FMC, Record, Status, OrigRecord, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10) /*********************************************************************************************************************** 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_Actions Description : Handles calculated columns and MFS calls for the current table. Notes : This function uses @ID, @RECORD, and @DICT to make sure {ColumnName} references work correctly. If called from outside of a calculated column these will need to be set and restored. Parameters : Action [in] -- Name of the action to be taken CalcColName [in] -- Name of the calculated column that needs to be processed. Normally this should only be populated when the CalcField action is being used. FSList [in] -- The list of MFSs and the BFS name for the current file or volume. This is an @SVM delimited array, with the current MFS name as the first value in the array, and the BFS name as the last value. Normally set by a calling MFS. Handle [in] -- The file handle of the file or media map being accessed. Note, this does contain the entire handle structure that the Basic+ Open statement would provide. Normally set by a calling MFS. Name [in] -- The name (key) of the record or file being accessed. Normally set by a calling MFS. FMC [in] -- Various functions. Normally set by a calling MFS. Record [in] -- The entire record (for record-oriented functions) or a newly-created handle (for "get handle" functions). Normally set by a calling MFS. Status [in/out] -- Indicator of the success or failure of an action. Normally set by the calling MFS but for some actions can be set by the action handler to indicate failure. OrigRecord [in] -- Original content of the record being processed by the current action. This is automatically being assigned by the WRITE_RECORD and DELETE_RECORD actions within BASE_MFS. Param1-10 [in/out] -- Additional request parameter holders ActionFlow [out] -- Used to control the action chain (see the ACTION_SETUP insert for more information.) Can also be used to return a special value, such as the results of the CalcField method. History : (Date, Initials, Notes) 04/10/18 dmb Original programmer. 10/04/18 djs Added a trigger within the WRITE_RECORD event, which fires when the reactor number has changed. When this occurs the related RDS_LAYER records for this RDS record are populated with the most recent associated TOOL_PARMS record. (related by PSN and Reactor) ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $Insert FILE.SYSTEM.EQUATES $Insert ACTION_SETUP $Insert RDS_EQUATES $Insert CLEAN_INSP_EQUATES $Insert COMPANY_EQUATES $Insert RDS_LAYER_EQUATES $Insert TOOL_PARMS_EQUATES $Insert RLIST_EQUATES $Insert APP_INSERTS $Insert QA_MET_EQUATES $Insert PRS_STAGE_EQUATES $Insert WO_MAT_EQUATES $Insert WO_MAT_QA_EQUATES $Insert LOT_EVENT_EQUATES Equ COMMA$ to ',' Declare function Error_Services, Database_Services, obj_RDS_Test, Logging_Services, Environment_Services Declare function Tool_Parms_Services, Signature_Services, obj_WO_Mat_QA, Datetime, Override_Services Declare function Rds_Services, SRP_DateTime, SRP_Math, obj_WO_Mat, Lot_Services, SRP_Array Declare subroutine Error_Services, Database_Services, Logging_Services, Service_Services LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\RDS' LogDate = Oconv(Date(), 'D4/') LogTime = Oconv(Time(), 'MTS') LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' RDS Log.csv' Headers = 'Logging DTM' : @FM : 'User' : @FM : 'RDS Key ID' : @FM : 'Notes' objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\RDS' LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' RDS Erase attempt.csv' Headers = 'Logging DTM' : @FM : 'RDSNo' : @FM : 'WONo' : @FM : 'CassNo' : @FM : 'Reactor Type' objLog3 = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$) If KeyID then GoSub Initialize_System_Variables Begin Case Case Action _EQC 'CalculateColumn' ; GoSub CalculateColumn Case Action _EQC 'READ_RECORD_PRE' ; GoSub READ_RECORD_PRE Case Action _EQC 'READ_RECORD' ; GoSub READ_RECORD Case Action _EQC 'READONLY_RECORD_PRE' ; GoSub READONLY_RECORD_PRE Case Action _EQC 'READONLY_RECORD' ; GoSub READONLY_RECORD Case Action _EQC 'WRITE_RECORD_PRE' ; GoSub WRITE_RECORD_PRE Case Action _EQC 'WRITE_RECORD' ; GoSub WRITE_RECORD Case Action _EQC 'DELETE_RECORD_PRE' ; GoSub DELETE_RECORD_PRE Case Action _EQC 'DELETE_RECORD' ; GoSub DELETE_RECORD Case Otherwise$ ; Status = 'Invalid Action' End Case If KeyID then GoSub Restore_System_Variables If Assigned(ActionFlow) else ActionFlow = ACTION_CONTINUE$ Return ActionFlow //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Calculated Columns // // The typical structure of a calculated column will look like this: // // Declare function Database_Services // // @ANS = Database_Services('CalculateColumn') //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CalculateColumn: // Make sure the ActionFlow return variable is cleared in case nothing is calculated. ActionFlow = '' Begin Case Case CalcColName EQ 'CURR_STAGE' ; GoSub CURR_STAGE Case CalcColName EQ 'DATETIME_IN' ; GoSub DATETIME_IN CAse CalcColName EQ 'DATETIME_OUT' ; GoSub DATETIME_OUT Case CalcColName EQ 'PRE_INST' ; GoSub PRE_INST Case CalcColName EQ 'PRE_INST_ACK_REQ' ; GoSub PRE_INST_ACK_REQ Case CalcColName EQ 'FWI_INST' ; GoSub FWI_INST Case CalcColName EQ 'FWI_INST_ACK_REQ' ; GoSub FWI_INST_ACK_REQ Case CalcColName EQ 'LWI_INST' ; GoSub LWI_INST Case CalcColName EQ 'LWI_INST_ACK_REQ' ; GoSub LWI_INST_ACK_REQ Case CalcColName EQ 'QA_INST' ; GoSub QA_INST Case CalcColName EQ 'QA_INST_ACK_REQ' ; GoSub QA_INST_ACK_REQ Case CalcColName EQ 'LOAD_INST' ; GoSub LOAD_INST Case CalcColName EQ 'LOAD_INST_ACK_REQ' ; GoSub LOAD_INST_ACK_REQ Case CalcColName EQ 'UNLOAD_INST' ; GoSub UNLOAD_INST Case CalcColName EQ 'UNLOAD_INST_ACK_REQ' ; GoSub UNLOAD_INST_ACK_REQ Case CalcColName EQ 'ON_TW_FREQ' ; GoSub ON_TW_FREQ Case CalcColName EQ 'POST_INST' ; GoSub POST_INST Case CalcColName EQ 'POST_INST_ACK_REQ' ; GoSub POST_INST_ACK_REQ Case CalcColName EQ 'ROTR_ACTION' ; GoSub ROTR_ACTION Case CalcColName EQ 'RDS_LAYER_ACK_REQ' ; GoSub RDS_LAYER_ACK_REQ Case CalcColName EQ 'RUNTIME' ; GoSub RUNTIME Case CalcColName EQ 'SUPPL_ACK_REQ' ; GoSub SUPPL_ACK_REQ Case CalcColName EQ 'WAFER_COUNT_ACK_REQ' ; GoSub WAFER_COUNT_ACK_REQ Case CalcColName EQ 'TW_PROD' ; GoSub TW_PROD Case CalcColName EQ 'ABBREV_OR_CO_NAME' ; GoSub ABBREV_OR_CO_NAME Case CalcColName EQ 'LOAD_LOCK_REQ' ; GoSub LOAD_LOCK_REQ Case CalcColName EQ 'UNLOAD_THICK_TEST' ; GoSub UNLOAD_THICK_TEST Case CalcColName EQ 'WO_MAT_KEY' ; GoSub WO_MAT_KEY Case CalcColName EQ 'HOT_LOT' ; GoSub HOT_LOT End Case return DATETIME_IN: TimeIn = {TIME_IN} TimeIn = TimeIn/86400 TimeIn = SRP_Math('ROUND', TimeIn, 5) TimeIn = TimeIn[2, 6] ActionFlow = {DATE_IN}:TimeIn return DATETIME_OUT: TimeOut = {TIME_OUT} TimeOut = TimeOut/86400 TimeOut = SRP_Math('ROUND', TimeOut, 5) TimeOut = TimeOut[2, 6] ActionFlow = {DATE_OUT}:TimeOut return LOAD_LOCK_REQ: ActionFlow = False$ ReactorType = {REACTOR_TYPE} LoadLock = {LOAD_LOCK_SIDE} If ( ( (ReactorType EQ 'ASM+') or (ReactorType EQ 'HTR') ) and (LoadLock EQ '') ) then ActionFlow = True$ return CURR_STAGE: Stage = '' RDSNo = @ID Stage = Rds_Services('GetCurrentStage', RDSNo) ActionFlow = Stage return PRE_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*PRE', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return PRE_INST_ACK_REQ: If ( ({PRE_INST} NE '') and ( ({PRE_INST_ACK} EQ '') or ({PRE_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'VER') ) then ActionFlow = True$ end else ActionFlow = False$ end return FWI_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*FWI', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return FWI_INST_ACK_REQ: If ( ({FWI_INST} NE '') and ( ({FWI_INST_ACK} EQ '') or ({FWI_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'LOAD') ) then ActionFlow = True$ end else ActionFlow = False$ end return LWI_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*LWI', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return LWI_INST_ACK_REQ: If ( ({LWI_INST} NE '') and ( ({LWI_INST_ACK} EQ '') or ({LWI_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'UNLOAD') ) then ActionFlow = True$ end else ActionFlow = False$ end return POST_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*POST', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return POST_INST_ACK_REQ: If ( ({POST_INST} NE '') and ( ({POST_INST_ACK} EQ '') or ({POST_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'POST') ) then ActionFlow = True$ end else ActionFlow = False$ end return QA_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*QA', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return QA_INST_ACK_REQ: If ( ({QA_INST} NE '') and ( ({QA_INST_ACK} EQ '') or ({QA_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'QA') ) then ActionFlow = True$ end else ActionFlow = False$ end return LOAD_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*LOAD', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return LOAD_INST_ACK_REQ: If ( ({LOAD_INST} NE '') and ( ({LOAD_INST_ACK} EQ '') or ({LOAD_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'LOAD') ) then ActionFlow = True$ end else ActionFlow = False$ end return UNLOAD_INST: PSN = {PROD_SPEC_ID} StageInst = Xlate('PRS_STAGE', PSN:'*UNLOAD', 'INST', 'X') Convert @TM to ' ' in StageInst ActionFlow = StageInst return UNLOAD_INST_ACK_REQ: If ( ({UNLOAD_INST} NE '') and ( ({UNLOAD_INST_ACK} EQ '') or ({UNLOAD_INST_ACK} EQ False$) ) and ({CURR_STAGE} EQ 'UNLOAD') ) then ActionFlow = True$ end else ActionFlow = False$ end return UNLOAD_THICK_TEST: UnloadThickTest = '' Parms = {WO_MAT_KEY}:@RM Parms := '':@RM Parms := FIELD(@RECORD<256>,'*',2):@RM ;* WOStep Parms := 'UNLOAD':@RM Parms := WO_MAT_QA_PROFILE$ QAMetArray = obj_WO_Mat_QA('GetQAMet', Parms) For each Row in QAMetArray using @FM setting fPos Locate 'THICK_ONLY' in Row using @VM setting vPos then UnloadThickTest = True$ end Until UnloadThickTest EQ True$ Next Row ActionFlow = UnloadThickTest return SUPPL_ACK_REQ: ActionFlow = False$ SupplementFlag = {SUPPLEMENT} SupplAck = {SUPPL_ACK} If ( (SupplementFlag EQ True$) and ( (SupplAck EQ '') or (SupplAck EQ False$) ) ) then ActionFlow = True$ end return RDS_LAYER_ACK_REQ: ActionFlow = False$ IsTestWafer = {ON_TW_FREQ} RDSLayerAck = {RDS_LAYER_ACK} If ( (IsTestWafer EQ True$) and ( (RDSLayerAck EQ False$) or (RDSLayerAck EQ '') ) ) then ActionFlow = True$ end return WAFER_COUNT_ACK_REQ: ActionFlow = False$ If ( ({CURR_STAGE} EQ 'VER') and ( ({WAFER_COUNT_ACK} EQ False$) or ({WAFER_COUNT_ACK} EQ '') ) ) then ActionFlow = True$ end return ON_TW_FREQ: ActionFlow = False$ CassNo = {CASS_NO} PSNo = {PROD_SPEC_ID} UnloadKey = PSNo:'*UNLOAD' UnloadRec = Database_Services('ReadDataRow', 'PRS_STAGE', UnloadKey) Intervals = UnloadRec Starts = UnloadRec MetTests = UnloadRec TestSlots = UnloadRec Found = False$ For each MetTest in MetTests using @VM setting vPos TestSlot = TestSlots<0, vPos> If (MetTest EQ 'THICK_ONLY') and (TestSlot EQ 'L') then Found = True$ Until Found EQ True$ Next MetTest If Found EQ True$ then TestWaferFlag = 0 Interval = Intervals<0, vPos> Start = Starts<0, vPos> IF Interval NE '' AND Start NE '' THEN IF Interval = Start THEN IF REM(CassNo,Interval) = 0 THEN TestWaferFlag = 1 END ELSE IF ABS((Start + INT(CassNo/Interval)*Interval) - CassNo) = 0 THEN TestWaferFlag = 1 END end ActionFlow = TestWaferFlag end return ROTR_ACTION: CleanInspRow = Database_Services('ReadDataRow', 'CLEAN_INSP', {LWI_CI_NO}) ROTRAction = CleanInspRow If ROTRAction EQ 'F' then // Before returning a Fail, check to see if there is an acceptance for the results. AcceptedSignature = CleanInspRow AcceptedReason = CleanInspRow If (AcceptedSignature NE '') AND (AcceptedReason NE '') then ROTRAction = 'A' end ActionFlow = ROTRAction return TW_PROD: IF {REACTOR_TYPE} = 'EPP' THEN WaferChars = @RECORD<275> PktChars = @RECORD<268> OutCnt = COUNT(PktChars,@VM) + (PktChars NE '') Ans = 0 FOR I = 1 TO OutCnt PktChar = PktChars<1,I> WfrChar = WaferChars<1,I> IF PktChar = 'TEST' AND WfrChar = 'PROD' THEN Ans += 1 NEXT I ActionFlow = Ans END ELSE TestKeys = XLATE('RDS_LAYER',@RECORD<150>,3,'X') ActionFlow = obj_RDS_Test('ProdTestCount',TestKeys) END return ABBREV_OR_CO_NAME: CompRec = Database_Services('ReadDataRow', 'COMPANY', {CUST_NO}) CustomerName = CompRec ActionFlow = CustomerName return WO_MAT_KEY: ActionFlow = '' ReactType = {REACTOR_TYPE} IF {REACTOR_TYPE} NE 'EPP' THEN WONo = @RECORD<6> CassNo = @RECORD<260> IF WONo NE '' AND CassNo NE '' THEN ActionFlow = WONo:'*':CassNo END END If ActionFlow EQ '' and ReactType NE 'EPP' and ReactType NE 'GAN' then RDSNo = @ID // Log the above data to troubleshoot. LogData = '' LogData<1> = LoggingDTM LogData<2> = RDSNo LogData<3> = @Record LogData<4> = @Record LogData<5> = ReactType Logging_Services('AppendLog', objLog3, LogData, @RM, @FM) end return RUNTIME: LoadDTM = IConv(OConv({DATE_IN}, 'D'):' ':OConv({TIME_IN}, 'MT'), 'DT') LoadEx2DTM = IConv(OConv({OP_IN_EX2_DATE}, 'D'):' ':OConv({OP_IN_EX2_TIME}, 'MT'), 'DT') LoadEx3DTM = IConv(OConv({OP_IN_EX3_DATE}, 'D'):' ':OConv({OP_IN_EX3_TIME}, 'MT'), 'DT') UnloadEx1DTM = IConv(OConv({OP_OUT_EX1_DATE}, 'D'):' ':OConv({OP_OUT_EX1_TIME}, 'MT'), 'DT') UnloadEx2DTM = IConv(OConv({OP_OUT_EX2_DATE}, 'D'):' ':OConv({OP_OUT_EX2_TIME}, 'MT'), 'DT') UnloadDTM = IConv(OConv({DATE_OUT}, 'D'):' ':OConv({TIME_OUT}, 'MT'), 'DT') Begin Case Case UnloadEx2DTM NE '' Runtime = UnloadEx2DTM - LoadEx3DTM Case UnloadEx1DTM NE '' Runtime = UnloadEx1DTM - LoadEx2DTM Case Otherwise$ Runtime = UnloadDTM - LoadDTM End Case ActionFlow = Runtime return HOT_LOT: ActionFlow = Xlate('WO_LOG', {WO}, 'HOT_FLAG', 'X') return // ----- MFS calls ----------------------------------------------------------------------------------------------------- READ_RECORD_PRE: // In order to stop a record from being read in this action these lines of code must be used: // // OrigFileError = 100 : @FM : KeyID // Status = 0 // Record = '' // ActionFlow = ACTION_STOP$ * This code prevents an anomaly where an @SVM appears when the value is read * and causes an error when copying the record to SQL. WafersIn = Record WafersIn = WafersIn<1, 1, 1> Record = WafersIn return READ_RECORD: // In order to stop a record from being read in this action these lines of code must be used: // // OrigFileError = 100 : @FM : KeyID // Status = 0 // Record = '' Shift = Record If Num(Shift) then Begin Case Case Shift EQ 1 Record = 'A' Case Shift EQ 2 Record = 'B' Case Shift EQ 3 Record = 'C' Case Shift EQ 4 Record = 'D' Case Otherwise$ Null End Case end return READONLY_RECORD_PRE: // In order to stop a record from being read in this action these lines of code must be used: // // OrigFileError = 100 : @FM : KeyID // Status = 0 // Record = '' // ActionFlow = ACTION_STOP$ return READONLY_RECORD: // In order to stop a record from being read in this action these lines of code must be used: // // OrigFileError = 100 : @FM : KeyID // Status = 0 // Record = '' Shift = Record If Num(Shift) then Begin Case Case Shift EQ 1 Record = 'A' Case Shift EQ 2 Record = 'B' Case Shift EQ 3 Record = 'C' Case Shift EQ 4 Record = 'D' Case Otherwise$ Null End Case end return WRITE_RECORD_PRE: Shift = Record If Num(Shift) then Begin Case Case Shift EQ 1 Record = 'A' Case Shift EQ 2 Record = 'B' Case Shift EQ 3 Record = 'C' Case Shift EQ 4 Record = 'D' Case Otherwise$ Null End Case end SaveRecord = Record RDSNo = Name RDSKeyID = Name OrigReactor = OrigRecord NewReactor = Record // Verify / Pre-Epi Signature OrigVerSig = Trim(OrigRecord) OrigVerDate = Trim(OrigRecord) OrigVerTime = Trim(OrigRecord) NewVerSig = Trim(Record) NewVerDate = Trim(Record) NewVerTime = Trim(Record) If Not(Num(NewVerDate)) then Record = IConv(NewVerDate, 'D') If Not(Num(NewVerTime)) then Record = IConv(NewVerTime, 'MT') // Load Signature OrigLoadSig = Trim(OrigRecord) OrigLoadDate = Trim(OrigRecord) OrigLoadTime = Trim(OrigRecord) NewLoadSig = Trim(Record) NewLoadDate = Trim(Record) NewLoadTime = Trim(Record) If Not(Num(NewLoadDate)) then Record = IConv(NewLoadDate, 'D') If Not(Num(NewLoadTime)) then Record = IConv(NewLoadTime, 'MT') // Unload signature OrigDateOut = OrigRecord OrigTimeOut = OrigRecord OrigTimeOutSig = OrigRecord DateOut = Record TimeOut = Record TimeOutSig = Record If Not(Num(DateOut)) then Record = IConv(DateOut, 'D') If Not(Num(TimeOut)) then Record = IConv(TimeOut, 'MT') // FQA signature OrigFQADate = OrigRecord OrigFQATime = OrigRecord OrigFQASig = OrigRecord FQADate = Record FQATime = Record FQASig = Record If Not(Num(FQADate)) then Record = IConv(FQADate, 'D') If Not(Num(FQATime)) then Record = IConv(FQATime, 'MT') CurrDTM = Datetime() VerDTM = IConv(OConv(NewVerDate, 'D'):' ':OConv(NewVerTime, 'MT'), 'DT') LoadDTM = IConv(OConv(NewLoadDate, 'D'):' ':OConv(NewLoadTime, 'MT'), 'DT') LoadEx2DTM = IConv(OConv({OP_IN_EX2_DATE}, 'D'):' ':OConv({OP_IN_EX2_TIME}, 'MT'), 'DT') LoadEx3DTM = IConv(OConv({OP_IN_EX3_DATE}, 'D'):' ':OConv({OP_IN_EX3_TIME}, 'MT'), 'DT') UnloadEx1DTM = IConv(OConv({OP_OUT_EX1_DATE}, 'D'):' ':OConv({OP_OUT_EX1_TIME}, 'MT'), 'DT') UnloadEx2DTM = IConv(OConv({OP_OUT_EX2_DATE}, 'D'):' ':OConv({OP_OUT_EX2_TIME}, 'MT'), 'DT') UnloadDTM = IConv(OConv(DateOut, 'D'):' ':OConv(TimeOut, 'MT'), 'DT') PostDTM = IConv(OConv({POST_EPI_SIG_DATE}, 'D'):' ':OConv({POST_EPI_SIG_TIME}, 'MT'), 'DT') FQADTM = IConv(OConv({SUP_VER_SIG_DATE}, 'D'):' ':OConv({SUP_VER_SIG_TIME}, 'MT'), 'DT') If NewLoadSig EQ '' then // Audit the LOT_EVENT table for missing LOAD event (i.e., signature) ExistingNGLotId = Lot_Services('GetLotIdByLegacyLotIdAndType', RDSNo, 'RDS') If RowExists('LOT', ExistingNGLotId) then LotEvents = Lot_Services('GetLotEventsInSequence', ExistingNGLotId) If LotEvents NE '' then LotEventsRev = SRP_Array('Reverse', LotEvents, @FM) LotEventsTypesRev = Xlate('LOT_EVENT', LotEventsRev, LOT_EVENT_LOT_EVENT_TYPE$, 'X') If LotEventsTypesRev NE '' then Done = False$ For each LotEventType in LotEventsTypesRev using @FM setting EventPos Begin Case Case LotEventType EQ 'LOAD' Done = True$ If NewLoadSig EQ '' then // Load signature is missing from RDS record NewLoadSig = Xlate('LOT_EVENT', LotEventsRev, LOT_EVENT_EVENT_OPERATOR_ID$, 'X') NewLoadSigDtm = Xlate('LOT_EVENT', LotEventsRev, LOT_EVENT_EVENT_DATETIME$, 'X') NewLoadDate = SRP_DateTime("Date", NewLoadSigDtm) NewLoadTime = SRP_DateTime("Time", NewLoadSigDtm) Record = NewLoadSig Record = NewLoadDate Record = NewLoadTime LogData = '' LogData<1> = LoggingDTM LogData<2> = @User4 LogData<3> = RDSKeyID LogData<4> = 'Detected missing LOAD signature from RDS record. Restored signature from LOT_EVENT table.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end Case LotEventType EQ 'UNSIGN_LOAD' Done = True$ // No need to check for missing load signature End Case Until Done Next LotEventType end end end end Begin Case Case LoadDTM NE '' and UnloadDTM EQ '' and UnloadEx1DTM EQ '' // Cassette still running... Runtime = 0 Case LoadEx2DTM NE '' and UnloadEx2DTM EQ '' // Cassette still running... Runtime = 0 Case LoadEx3DTM NE '' and UnloadDTM EQ '' // Cassette still running... Runtime = 0 Case UnloadDTM NE '' and LoadEx3DTM EQ '' // No extra load/unload (typical path) Runtime = UnloadDTM - LoadDTM Case UnloadDTM NE '' and LoadEx3DTM NE '' // Three extra load/unloads RunTime = UnloadDTM - LoadEx3DTM Case UnloadEx2DTM NE '' // Two extra load/unloads Runtime = UnloadEx2DTM - LoadEx2DTM Case UnloadEx1DTM NE '' // One extra load/unload Runtime = UnloadEx1DTM - LoadDTM Case Otherwise$ Runtime = 0 End Case // Look for UNLOAD_DTM override Override = Override_Services('GetOverride', 'RDS', RDSNo, 'UNLOAD_DTM') Begin Case Case ( (OrigLoadSig NE '') and (OrigReactor NE NewReactor) ) LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = RDSKeyID LogData<4> = 'Reactor number cannot be changed or removed once the load signature is set!' Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$) // User is attempting to erase data that is prohibited from being erased Set the FS104 error and block the write. Error_Services('Add', 'Reactor number cannot be changed or removed once the load signature is set!') OrigFileError = 104:': Reactor number cannot be changed or removed once the load signature is set!' Status = 0 Record = '' ActionFlow = ACTION_STOP$ Case ( (OrigVerSig NE '') and (NewVerSig EQ '') ) or ( (OrigVerDate NE '') and (NewVerDate EQ '') ) | or ( (OrigVerTime NE '') and (NewVerTime EQ '') ) or ( (NewVerDate EQ '') and (NewVerTime NE '') ) | or ( (NewVerDate NE '') and (NewVerTime EQ '') ) LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = RDSKeyID LogData<4> = 'Signature data cannot be removed!' Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$) // User is attempting to erase data that is prohibited from being erased Set the FS104 error and block the write. Error_Services('Add', 'Signature data cannot be removed!') OrigFileError = 104:': Signature data cannot be removed!' Status = 0 Record = '' ActionFlow = ACTION_STOP$ Case ( (VerDTM GT CurrDTM) or (LoadDTM GT CurrDTM) or (LoadEx2DTM GT CurrDTM) or (LoadEx3DTM GT CurrDTM) | or (UnloadEx1DTM GT CurrDTM) or (UnloadEx2DTM GT CurrDTM) or (UnloadDTM GT CurrDTM) | or (PostDTM GT CurrDTM) or (FQADTM GT CurrDTM) ) RDSKeyID = Name LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = RDSKeyID LogData<4> = 'Signature datetime is greater than current datetime!' Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$) Error_Services('Add', 'Signature datetime is greater than current datetime!') OrigFileError = 104:': Signature datetime is greater than current datetime!' Status = 0 Record = '' ActionFlow = ACTION_STOP$ Case ( ((VerDTM NE '' and LoadDTM NE '') and (LoadDTM LE VerDTM)) | or (LoadDTM NE '' and UnloadDTM NE '') and (UnloadDTM LT LoadDTM) | or (UnloadEx1DTM NE '' and LoadDTM NE '') and (UnloadEx1DTM LT LoadDTM) | or (LoadEx2DTM NE '' and UnloadEx1DTM NE '') and (LoadEx2DTM LT UnloadEx1DTM) | or (UnloadEx2DTM NE '' and LoadEx3DTM NE '') and (LoadEx3DTM LT UnloadEx2DTM) | or (UnloadDTM NE '' and LoadEx3DTM NE '') and (UnloadDTM LT LoadEx3DTM) ) // QA > POST > Unload > LoadEx3 > UnloadEx2 > LoadEx2 > UnloadEx1 > Load RDSKeyID = Name LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = RDSKeyID LogData<4> = 'Signature datetime is less than a previous signature datetime!' Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$) Error_Services('Add', 'Signature datetime is less than a previous signature datetime!') OrigFileError = 104:': Signature datetime is less than a previous signature datetime!' Status = 0 Record = '' ActionFlow = ACTION_STOP$ Case ( (RunTime GT 3) and (Override EQ False$) ) RDSKeyID = Name LogData = '' LogData<1> = LoggingDTM LogData<2> = @USER4 LogData<3> = RDSKeyID LogData<4> = 'Cassette runtime exceeds three days!' Logging_Services('AppendLog', ObjLog, LogData, @RM, @FM, False$) Error_Services('Add', 'Cassette runtime exceeds three days!') OrigFileError = 104:': Cassette runtime exceeds three days!' Status = 0 Record = '' ActionFlow = ACTION_STOP$ Case Otherwise$ SaveRecord = Record End Case return WRITE_RECORD: WONo = Record ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X') EpiPro = (ReactType EQ 'EPP') GaN = (ReactType EQ 'GAN') NonEpiPro = ( (ReactType NE 'EPP') and (ReactType NE 'GAN') ) If NonEpiPro then // Sync up VER, LOAD, UNLOAD, POST, and QA signatures with WO_MAT signature profile. // The goal of signature services was to remove any dependency on the WO_MAT signature profile, // however Fabtime relies on this data being replicated to the Scrape SQL DB. WOMatKey = {WO_MAT_KEY} WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) WOMatSigProf = obj_WO_Mat('CassSigProfile', WOMatKey) WOMatSig = WOMatRec WOMatSigDTM = WOMatRec // Update WO_MAT signature profile to match for the "1VER" stage Stage = '1VER' Locate Stage in WOMatSigProf using @VM setting vPos then WOMatSig<0, vPos> = Record PreEpiDate = Record If PreEpiDate NE '' then PreEpiTime = Record PreEpiSigDTM = PreEpiDate + (PreEpiTime/86400) end else PreEpiSigDTM = '' end WOMatSigDTM<0, vPos> = PreEpiSigDTM end // Update WO_MAT signature profile to match for "1LOAD" stage Stage = '1LOAD' Locate Stage in WOMatSigProf using @VM setting vPos then WOMatSig<0, vPos> = Record DateIn = Record If DateIn NE '' then LoadTime = Record LoadSigDTM = DateIn + (LoadTime/86400) end else LoadSigDTM = '' end WOMatSigDTM<0, vPos> = LoadSigDTM end // Update WO_MAT signature profile to match for the "1UNLOAD" stage Stage = '1UNLOAD' Locate Stage in WOMatSigProf using @VM setting vPos then WOMatSig<0, vPos> = Record DateOut = Record If DateOut NE '' then TimeOut = Record TimeOutSigDTM = DateOut + (TimeOut/86400) end else TimeOutSigDTM = '' end WOMatSigDTM<0, vPos> = TimeOutSigDTM end // Update WO_MAT signature profile to match for the "1POST" stage Stage = '1POST' Locate Stage in WOMatSigProf using @VM setting vPos then WOMatSig<0, vPos> = Record PostSigDate = Record If PostSigDate NE '' then PostSigTime = Record PostSigDTM = PostSigDate + (PostSigTime/86400) end else PostSigDTM = '' end WOMatSigDTM<0, vPos> = PostSigDTM end // Update WO_MAT signature profile to match for the "1QA" stage Stage = '1QA' Locate Stage in WOMatSigProf using @VM setting vPos then WOMatSig<0, vPos> = Record FQADate = Record If FQADate NE '' then FQASigTime = Record FQASigDTM = FQADate + (FQASigTime/86400) end else FQASigDTM = '' end WOMatSigDTM<0, vPos> = FQASigDTM end WOMatRec = WOMatSigProf WOMatRec = WOMatSig WOMatRec = WOMatSigDTM Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) end OrigDateOut = OrigRecord NewDateOut = Record If ( ( (OrigDateOut EQ '') and (NewDateOut NE '') ) ) then // Mark this cassette as processed in the schedule event record DatetimeOut = {DATETIME_OUT} If EpiPro then WMIKeys = {WM_IN_KEY} For each WMIKey in WMIKeys using @VM setting vPos CassNo = Field(WMIKey, '*', 3) Service_Services('PostProcedure', 'SCHEDULE_SERVICES', 'MarkCassProcessed':@VM:WONo:@VM:CassNo:@VM:DatetimeOut) Next WMIKey end else CassNo = Record Service_Services('PostProcedure', 'SCHEDULE_SERVICES', 'MarkCassProcessed':@VM:WONo:@VM:CassNo:@VM:DatetimeOut) end end return DELETE_RECORD_PRE: Notes = RetStack() Swap @FM with ' | ' in Notes LogData = '' LogData<1> = LoggingDTM LogData<2> = @User4 LogData<3> = Name LogData<4> = Notes Logging_Services('AppendLog', objLog, LogData, @RM, @FM) return DELETE_RECORD: return //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ClearCursors: For counter = 0 to 8 ClearSelect counter Next counter return Initialize_System_Variables: // Save these for restoration later SaveDict = @DICT SaveID = @ID SaveRecord = @RECORD OrigFileError = @FILE.ERROR // Now make sure @DICT, ID, and @RECORD are populated CurrentDictName = '' If @DICT then DictHandle = @DICT<1, 2> Locate DictHandle in @TABLES(5) Using @FM Setting fPos then CurrentDictName = Field(@TABLES(0), @FM, fPos, 1) end end If CurrentDictName NE DictName then Open DictName to @DICT else Status = 'Unable to initialize @DICT' end @ID = KeyID If Record else // Record might not have been passed in. Read the record from the database table just to make sure. @FILE.ERROR = '' Open TableName to hTable then FullFSList = hTable[1, 'F' : @VM] BFS = FullFSList[-1, 'B' : @SVM] LastHandle = hTable[-1, 'B' : \0D\] FileHandle = \0D\ : LastHandle[1, @VM] Call @BFS(READO.RECORD, BFS, FileHandle, KeyID, FMC, Record, ReadOStatus) end end @RECORD = Record return Restore_System_Variables: Transfer SaveDict to @DICT Transfer SaveID to @ID Transfer SaveRecord to @RECORD @FILE.ERROR = OrigFileError return