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 Equ COMMA$ to ',' Declare function Error_Services, Database_Services, obj_RDS_Test, Logging_Services, Environment_Services, SRP_Math Declare function Tool_Parms_Services, Signature_Services, obj_WO_Mat_QA, Datetime, Override_Services, obj_WO_Mat Declare function Rds_Services Declare subroutine Error_Services, Database_Services, Logging_Services, Set_Status, Schedule_Services Declare subroutine Work_Order_Services, Material_Services, Set_FSError 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$) LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\RDS_LAYER' LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' RDS_LAYER Log.csv' Headers = 'Logging DTM' : @FM : 'Results' ColumnWidths = 20 : @FM : 100 objLog2 = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, 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 = '' 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 = '' return WRITE_RECORD_PRE: RDSNo = Name RDSKeyID = Name // 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') 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 ( (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 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 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 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 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) Schedule_Services('MarkCassProcessed', WONo, CassNo, DatetimeOut) Next WMIKey end else CassNo = Record Schedule_Services('MarkCassProcessed', WONo, CassNo, 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