Compile function Signature_Services(@Service, @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 SRP Computer Solutions, Inc. Name : Signature_Services Description : Handler program for all module related services. Notes : Service module to support environmental state issues. Environmental refers to the state of the operating system, which includes version, client vs. server, and path to critical systems. Parameters : Service [in] -- Name of the service being requested Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 11/07/19 djs Original programmer. 08/21/20 djs Updated GetSigInfo to support multiple CLEAN_INSP scans. The code will return the signature info for the most recently signed scan. 07/13/21 djs Removed caching code (Memory_Services) so that users can sign multiple stages in quick succession without causing issues related to caching the signature profile. 08/03/21 djs Restored caching code because it was causing the application to perform very poorly during certain operations (e.g. releasing material). Added a UseCaching variable to all services, so that developers can choose to use caching or not. 06/13/24 djm Add support for EPP signature profile. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert POPUP_EQUATES $INSERT LOGICAL $Insert WO_MAT_EQUATES $insert SERVICE_SETUP $insert RLIST_EQUATES $insert WO_MAT_QA_EQUATES $insert RDS_EQUATES $insert COMPANY_EQUATES $insert APP_INSERTS $insert CLEAN_INSP_EQUATES $insert NCR_EQUATES $insert WM_OUT_EQUATES Equ SS_PASS$ To 1 Equ SS_SIG$ To 2 Equ SS_DATA$ To 3 Equ SS_NA$ To 4 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 Declare function obj_Prod_Spec, RDS_Services, Error_Services, Signature_Services, Memory_Services, obj_RDS_Test Declare function Database_Services, obj_WO_Mat, Dialog_Box, MemberOf, Msg, QA_Services, Datetime, Supplement_Services Declare subroutine Error_Services, Popup, Memory_Services, SRP_Stopwatch, Set_Status, Database_Services, obj_WO_Mat Declare subroutine Obj_Notes, Signature_Services, Obj_WO_Mat_Log, ErrMsg PSNKey = ServiceKeyID ReactorKey = ServiceKeyID GoToService Return Response or "" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Service Parameter Options //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Options CI_STAGES = 'PREI,PREC,PRES,FWII,FWIC,FWIS,LWII,LWIC,LWIS,PSTI,PSTC,PSTS' Options QA_STAGES = 'LOAD,UNLOAD,QA' Options SLOTS = '1,2,3,4,5,6,F,L,A' ; // From SYSREPOSPOPUPS LSL2**TEST_SLOTS //----------------------------------------------------------------------------- // SERVICES //----------------------------------------------------------------------------- Service FQAReady(WOMatKey, UseCaching) If UseCaching EQ '' then UseCaching = True$ Response = False$ SigProfile = Signature_Services('GetSigProfile', WOMatKey, UseCaching) Stages = SigProfile<1> Sigs = SigProfile<2> SigDTMs = SigProfile<3> NumStages = DCount(Stages, @VM) If NumStages GT 1 then Done = False$ For StageIndex = 1 to (NumStages - 1) Stage = Stages<0, StageIndex> StageComp = Signature_Services('CheckSignature', WOMatKey, Stage) If StageComp EQ False$ then Done = True$ ErrorMsg = 'Unable to sign FQA due to incomplete Signature Profile at ':Stage:' stage.' Error_Services('Add', ErrorMsg) end Until Done EQ True$ Next StageIndex end If Error_Services('NoError') then Response = True$ end service Service CheckQALabelStatus(WOMatKey) rec = Xlate('WO_MAT', WoMatKey,'', '') locRec = rec actionRec = rec retVal = 0 Locate 'LBLCHK' In actionRec Using @VM Setting locIdx Then Locate 'PKO' in locRec Using @VM Setting idx Then if idx GE 1 then If (rec NE '' AND rec NE '') then retVal = 1 end end end end Response = retVal end service Service GetSigProfile(WOMatKey, UseCaching, RDSNo) If UseCaching EQ '' then UseCaching = True$ SigProfile = '' Signatures = '' SigDTMs = '' If RDSNo NE '' then WONo = Xlate('RDS', RDSNo, 'WO', 'X') end else WONo = Field(WOMatKey, '*', 1) end PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') SigProfKey = PSNo:'*':WOMatKey:'*':RDSNo ReactorKey = PSNo :'*Reactor' If UseCaching and Memory_Services('IsValueCurrent', SigProfKey, 60, True$) then SigProfile = Memory_Services('GetValue', SigProfKey) end else SigProfile = obj_Prod_Spec('GetSigProfile', PSNo:@RM:'':@RM:WOMatKey:@RM:RDSNo) Memory_Services('SetValue', SigProfKey, SigProfile) end If UseCaching and Memory_Services('IsValueCurrent', ReactorKey, 60, True$) then ReactorType = Memory_Services('GetValue', ReactorKey) end else ReactorType = Xlate('PROD_SPEC', PSNo, 'REACTOR_TYPE', 'X') Memory_Services('SetValue', ReactorKey, ReactorType) end For each Stage in SigProfile using @VM setting LineNo SigInfo = Signature_Services('GetSigInfo', WOMatKey, Stage, UseCaching, RDSNo) Signatures<0, LineNo> = SigInfo<1> SigDTMs<0, LineNo> = SigInfo<2> Next Stage SigDTMs = OCONV(SigDTMs,'DT4/^S') Response = SigProfile:@FM:Signatures:@FM:SigDTMs end service Service FinalSigComp(WOMatKey, UseCaching) If UseCaching EQ '' then UseCaching = True$ Response = False$ WONo = Field(WOMatKey, '*', 1) ReactorType = Xlate('WO_LOG', WONo, 'REACTOR_TYPE', 'X') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') ReactorType = Xlate('PROD_SPEC', PSNo, 'REACTOR_TYPE', 'X') SigProfile = Signature_Services('GetSigProfile', WOMatKey, UseCaching) NumStages = DCount(SigProfile, @VM) FinalStage = SigProfile<0, NumStages> Response = Signature_Services('CheckSignature', WOMatKey, FinalStage, UseCaching) end service Service FinalSigDTM(WOMatKey, UseCaching) If UseCaching EQ '' then UseCaching = True$ Response = False$ WONo = Field(WOMatKey, '*', 1) ReactorType = Xlate('WO_LOG', WONo, 'REACTOR_TYPE', 'X') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') ReactorType = Xlate('PROD_SPEC', PSNo, 'REACTOR_TYPE', 'X') SigProfile = Signature_Services('GetSigProfile', WOMatKey, UseCaching) NumStages = DCount(SigProfile, @VM) FinalStage = SigProfile<0, NumStages> Response = Signature_Services('GetSigInfo', WOMatKey, FinalStage, UseCaching)<2> end service Service CheckSigOrder(WOMatKey, CurrStage, UseCaching, RDSNo) If UseCaching EQ '' then UseCachine = True$ Response = False$ If RDSNo NE '' then WONo = Xlate('RDS', RDSNo, 'WO', 'X') end else WONo = Field(WOMatKey, '*', 1) end ReactorType = Xlate('WO_LOG', WONo, 'REACTOR_TYPE', 'X') PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') SigProfile = obj_Prod_Spec('GetSigProfile', PSNo:@RM:'':@RM:WOMatKey:@RM:RDSNo) Locate CurrStage in SigProfile using @VM setting sPos then If sPos GT 1 then PrevStage = SigProfile<0, sPos-1> end else // There is no previous stage PrevStage = '' end // Check previous stage is complete If PrevStage NE '' then PrevStageSigInfo = Signature_Services('GetSigInfo', WOMatKey, PrevStage, UseCaching, RDSNo) PrevStageSig = PrevStageSigInfo<1> PrevStageComp = (PrevStageSig NE '') end else PrevStageSig = '' PrevStageComp = True$ end CurrStageComp = Signature_Services('CheckSignature', WOMatKey, CurrStage, UseCaching, RDSNo) Begin Case Case ( Not(MemberOf(@User4, 'BYPASS') ) and ( (CurrStage EQ 'QA') or (CurrStage EQ 'MO_QA') ) and (PrevStageSig EQ @User4) ) ErrorMsg = 'FQA stage signature cannot match previous step ':PrevStage:' signature. ':WOMatKey:' (':Service:')' Error_Services('Add', ErrorMsg) Case PrevStageComp EQ False$ ErrorMsg = 'Previous step ':PrevStage:' is not signed. ':WOMatKey:' (':Service:')' Error_Services('Add', ErrorMsg) Case CurrStageComp EQ True$ // Allow user to re-sign. This may be necessary in certain cases such as when multiple surfscans // have taken place and one still needs to be signed. Response = True$ Case Error_Services('HasError') EQ True$ // Error message already in stack. Null Case Otherwise$ // Ok Response = True$ End Case end else // Stage not prescribed in the PSN, so ignore the signature order. Response = True$ end End Service Service CheckSignature(WOMatKey, Stage, UseCaching, RDSNo) If UseCaching EQ '' then UseCaching = True$ Response = False$ SigInfo = Signature_Services('GetSigInfo', WOMatKey, Stage, UseCaching, RDSNo) If Error_Services('NoError') then Signature = SigInfo<1> SigDTM = SigInfo<2> If Signature NE '' then Response = True$ end end service Service GetSigInfo(WOMatKey, Stage, UseCaching, RDSNo) If UseCaching EQ '' then UseCaching = True$ Signature = '' SigDTM = '' If RDSNo NE '' then WONo = Xlate('RDS', RDSNo, 'WO', 'X') end else WONo = Field(WOMatKey, '*', 1) end PSNo = Xlate('WO_LOG', WONo, 'PS_NO', 'X') SigProfKey = PSNo:'*':WOMatKey:'*':RDSNo ReactorKey = PSNo:'*Reactor' If UseCaching and Memory_Services('IsValueCurrent', SigProfKey, 60, True$) then SigProfile = Memory_Services('GetValue', SigProfKey) end else SigProfile = obj_Prod_Spec('GetSigProfile', PSNo:@RM:'':@RM:WOMatKey:@RM:RDSNo) Memory_Services('SetValue', SigProfKey, SigProfile) end If UseCaching and Memory_Services('IsValueCurrent', ReactorKey, 60, True$) then ReactorType = Memory_Services('GetValue', ReactorKey) end else ReactorType = Xlate('PROD_SPEC', PSNo, 'REACTOR_TYPE', 'X') Memory_Services('SetValue', ReactorKey, ReactorType) end Locate Stage in SigProfile using @VM setting sPos then Begin Case * * EpiPro * * Case ( (ReactorType EQ 'EPP') or (ReactorType EQ 'P') ) CassNo = Field(WOMatKey, '*', 2) WMOKey = WONo:'*1*':CassNo PostCINo = Xlate('WM_OUT', WMOKey, 'EPO_CI_NO', 'X') Begin Case * * Verify wafer quantity stage (aka PRE) * * Case Stage EQ 'VER' Signature = Xlate('RDS', RDSNo, 'PRE_EPI_SIG', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'PRE_EPI_SIG_DT', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'PRE_EPI_SIG_TIME', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Pre Epi Cleaning and Inspection Stages * * Case Stage EQ 'PREC' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PREI' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PRES' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig * * Reactor Load * * Case Stage EQ 'LOAD' Signature = Xlate('RDS', RDSNo, 'OPERATOR_IN', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'DATE_IN', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'TIME_IN', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * First Wafer Inspection and Surfscan Stages * * Case Stage EQ 'FWII' FWICINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', FWICINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', FWICINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', FWICINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'FWIS' FWICINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', FWICINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', FWICINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', FWICINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig * * Reactor Unload * * Case Stage EQ 'UNLOAD' Signature = Xlate('RDS', RDSNo, 'OPERATOR_OUT', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'DATE_OUT', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'TIME_OUT', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Last Wafer Inspection and Surfscan Stages * * Case Stage EQ 'LWII' LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', LWICINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', LWICINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', LWICINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'LWIS' LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', LWICINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', LWICINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', LWICINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'POST' Signature = Xlate('RDS', RDSNo, 'POST_EPI_SIG', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'POST_EPI_SIG_DATE', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'POST_EPI_SIG_TIME', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Post Epi Clean and Inspection Stages * * Case Stage EQ 'PSTC' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PSTI' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PSTS' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'MO_PSTC' StageRows = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'MO_PSTI' StageRows = Xlate('CLEAN_INSP', PostCINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'MO_PSTS' StageRows = Xlate('CLEAN_INSP', PostCINo, 'SCAN_RECIPE', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'MO_QA' Signature = Xlate('WM_OUT', WMOKey, 'SUP_VER_SIG', 'X') SigDTM = Xlate('WM_OUT', WMOKey, 'SUP_VER_SIG_DTM', 'X') End Case * * GaN * * Case (ReactorType EQ 'GAN') If Stage EQ 'G_FQA' then Signature = Xlate('WO_MAT', WOMatKey, 'CASS_FINAL_SIG', 'X') SigDTM = Xlate('WO_MAT', WOMatKey, 'CASS_FINAL_SIG_DTM', 'X') end * * Silicon (aka Non-EpiPro) * * Case Otherwise$ RDSNo = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X') Begin Case * * Verify wafer quantity stage (aka PRE) * * Case Stage EQ 'VER' Signature = Xlate('RDS', RDSNo, 'PRE_EPI_SIG', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'PRE_EPI_SIG_DT', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'PRE_EPI_SIG_TIME', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Pre Epi Cleaning and Inspection Stages * * Case Stage EQ 'PREC' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'CLEAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PREI' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PRES' PreCINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PreCINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PreCINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PreCINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig * * Reactor Load * * Case Stage EQ 'LOAD' Signature = Xlate('RDS', RDSNo, 'OPERATOR_IN', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'DATE_IN', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'TIME_IN', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * First Wafer Inspection and Surfscan Stages * * Case Stage EQ 'FWII' FWICINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', FWICINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', FWICINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', FWICINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'FWIS' FWICINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', FWICINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', FWICINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', FWICINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig * * Reactor Unload * * Case Stage EQ 'UNLOAD' Signature = Xlate('RDS', RDSNo, 'OPERATOR_OUT', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'DATE_OUT', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'TIME_OUT', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Last Wafer Inspection and Surfscan Stages * * Case Stage EQ 'LWII' LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', LWICINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', LWICINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', LWICINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'LWIS' LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', LWICINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', LWICINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', LWICINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'POST' Signature = Xlate('RDS', RDSNo, 'POST_EPI_SIG', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'POST_EPI_SIG_DATE', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'POST_EPI_SIG_TIME', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') * * Post Epi Clean and Inspection Stages * * Case Stage EQ 'PSTC' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'CLEAN_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PSTI' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'INSP_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'INSP_SIG_DTM', 'X') GoSub GetMostRecentSig Case Stage EQ 'PSTS' PostCINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRows = Xlate('CLEAN_INSP', PostCINo, 'SCAN_TOOL', 'X') Signatures = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG', 'X') SigDTMs = Xlate('CLEAN_INSP', PostCINo, 'SCAN_SIG_DTM', 'X') GoSub GetMostRecentSig * * Final QA Stage * * Case Stage EQ 'QA' Signature = Xlate('RDS', RDSNo, 'SUP_VER_SIG', 'X') SigDate = OConv(Xlate('RDS', RDSNo, 'SUP_VER_SIG_DATE', 'X'), 'D') SigTime = OConv(Xlate('RDS', RDSNo, 'SUP_VER_SIG_TIME', 'X'), 'MTS') SigDTM = IConv(SigDate:' ':SigTime, 'DT') End Case End Case end else ErrorMsg = Stage:' stage not found in signature profile. ':WOMatKey:' (':Service:')' Error_Services('Add', ErrorMsg) end Response = Signature:@FM:SigDTM end service //---------------------------------------------------------------------------------------------------------------------- // GetStageSummary // // Input: // WOMatKey - [Required] // Stage - [Required] // // Output: // Response<1> - True$ if stage passes all requirements, False$ otherwise. // Response<2> - True$ if stage has been signed, False$ otherwise. // Response<3> - True$ if stage requires data and has data, False$ otherwise. // Response<4> - True$ if stage not defined in the PSN, False$ otherwise. // //---------------------------------------------------------------------------------------------------------------------- Service GetStageSummary(WOMatKey, Stage) StageSummary = '' Error = '' RDSNo = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X') SigProf = Signature_Services('GetSigProfile', WOMatKey, False$) SigProfStages = SigProf<1> SigProfSigs = SigProf<2> If (RowExists('WO_MAT', WOMatKey) and (Stage NE '') ) then Begin Case Case Stage EQ 'VER' // Ensure "Verify Wafers" quantity is not null // Ensure VER signature is not null If RDSNo NE '' then VerSig = Xlate('RDS', RDSNo, 'PRE_EPI_SIG', 'X') VerifyQty = Xlate('RDS', RDSNo, 'VERIFY_QTY', 'X') StageSummary = ( (VerSig NE '') and (VerifyQty NE '') ) StageSummary = (VerSig NE '') StageSummary = (VerifyQty NE '') Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'SUPP' // Verify RDS supplement information has been acknowledged If RDSNo NE '' then SupplFlag = Xlate('RDS', RDSNo, 'SUPPLEMENT', 'X') SupplAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ', 'X') SupplSig = Xlate('RDS', RDSNo, 'SUPPL_SIG', 'X') StageSummary = (SupplFlag EQ True$) and (SupplAckReq EQ False$) StageSummary = (SupplSig NE '') StageSummary = (SupplFlag EQ True$) StageSummary = (SupplFlag NE True$) ; // Stage only applicable if supplement flag is true end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'LOAD' // Verify "Wafers In" quantity is not null // Ensure LOAD signature is not null If RDSNo NE '' then LoadSig = Xlate('RDS', RDSNo, 'OPERATOR_IN', 'X') WafersIn = Xlate('RDS', RDSNo, 'WAFERS_IN', 'X') StageSummary = ( (LoadSig NE '') and (WafersIn NE '') ) StageSummary = (LoadSig NE '') StageSummary = (WafersIn NE '') Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'UNLOAD' // Ensure UNLOAD signature is not null If RDSNo NE '' then UnloadSig = Xlate('RDS', RDSNo, 'OPERATOR_OUT', 'X') StageSummary = (UnloadSig NE '') StageSummary = (UnloadSig NE '') StageSummary = True$ ; // No data for this stage entered by user Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'POST' // Ensure POST signature is not null If RDSNo NE '' then PostEpiSig = Xlate('RDS', RDSNo, 'POST_EPI_SIG', 'X') StageSummary = (PostEpiSig NE '') StageSummary = (PostEpiSig NE '') StageSummary = True$ ; // No data for this stage entered by user StageSummary = False$ ; // This stage is essentially never required by the PSN, but is required by some code. end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'QA' // Verify QA signature is not null If RDSNo NE '' then FQASig = Xlate('RDS', RDSNo, 'SUP_VER_SIG', 'X') StageSummary = (FQASig NE '') StageSummary = (FQASig NE '') StageSummary = True$ ; //Signature_Services('QASigReady', RDSNo) Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end end else Error = 'Error in ':Service:' service. Null RDSNo for WO_MAT record ':WOMatKey:'!' end Case Stage EQ 'RDS_TEST' // Gather RDS metrology information StageComplete = False$ If RDSNo NE '' then MetNo = Xlate('RDS', RDSNo, 'MET_KEYS', 'X') If MetNo NE '' then MetRec = Database_Services('ReadDataRow', 'RDS_TEST', MetNo) TWSigned = obj_RDS_Test('TWSignedOff', MetNo:@RM:MetRec) TestComp = obj_RDS_Test('TestComplete', MetNo:@RM:MetRec) OutOfSpec = obj_RDS_Test('OutOfSpec', MetNo:@RM:MetRec) StageSummary = (TWSigned and TestComp and Not(OutOfSpec)) StageSummary = TestComp StageSummary = TestComp StageSummary = False$ ; // I think RDS metrology is always required. end end Case Stage EQ 'PREI' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') If CINo NE '' then CITool = Xlate('CLEAN_INSP', CINo, 'INSP_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'INSP_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'PREC' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'CLEAN_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'CLEAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'PRES' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') StageRx = StageSummary If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'SPEC_SURFSCAN_RECIPE', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'SCAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'FWII' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') If CINo NE '' then CITool = Xlate('CLEAN_INSP', CINo, 'INSP_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'INSP_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'FWIC' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'CLEAN_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'CLEAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'FWIS' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') StageRx = StageSummary If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'SPEC_SURFSCAN_RECIPE', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'SCAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'LOAD_QA_MET' // Gather load QA metrology information NumTests = 0 TestSigs = '' TestOOSs = '' TestResults = '' Error = '' NotApplicable = True$ StageComplete = False$ DataComp = False$ SigsComp = False$ WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') If RowExists('WO_MAT', WOMatKey) then WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey) QAMetStages = WOMatQARec QAMetSigs = WOMatQARec QAMetOOSs = WOMatQARec QAMetResults = WOMatQARec For each QAMetStage in QAMetStages using @VM setting vPos If QAMetStage EQ 'FWI' then NumTests += 1 NotApplicable = False$ TestSig = QAMetSigs<0, vPos> TestOOS = QAMetOOSs<0, vPos> TestResult = QAMetResults<0, vPos> TestSigs<0, vPos> = (TestSig NE '') TestOOSs<0, vPos> = TestOOS TestResults<0, vPos> = (TestResult NE '') end Next QAMetStage DataComp = ( ( NumTests EQ Sum(TestResults) ) and (NumTests GT 0) ) SigsComp = ( ( NumTests EQ Sum(TestSigs) ) and (NumTests GT 0) ) end StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = NotApplicable Case Stage EQ 'LWII' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') If CINo NE '' then CITool = Xlate('CLEAN_INSP', CINo, 'INSP_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'INSP_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'LWIC' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'CLEAN_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'CLEAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'LWIS' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') StageRx = StageSummary If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'SPEC_SURFSCAN_RECIPE', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'SCAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'ROTR' CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'SPEC_SURFSCAN_RECIPE', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'SCAN_SIG', 'X') ROTRAction = Xlate('CLEAN_INSP', CINo, 'RDS_ROTR_ACTION', 'X') ROTRActionReason = Xlate('CLEAN_INSP', CINo, 'ROTR_ACTION_REASON', 'X') Begin Case Case ( (ROTRAction EQ 'F' ) and (CISig NE '') ) // ROTR Acceptance required StageSummary = True$ StageSummary = False$ StageSummary = False$ StageSummary = False$ Case ( (ROTRAction EQ 'F') and (CISig EQ '') and (ROTRActionReason EQ 'SurfScan signature is missing.') ) StageSummary = True$ StageSummary = False$ StageSummary = False$ StageSummary = False$ Case ( (ROTRAction EQ 'F') and (CISig EQ '') ) StageSummary = False$ StageSummary = False$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Pass StageSummary = True$ StageSummary = True$ StageSummary = True$ StageSummary = False$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'UNLOAD_QA_MET' // Gather unload QA metrology information NumTests = 0 TestSigs = '' TestOOSs = '' TestResults = '' Error = '' NotApplicable = True$ StageComplete = False$ DataComp = False$ SigsComp = False$ WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') If RowExists('WO_MAT', WOMatKey) then WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey) QAMetStages = WOMatQARec QAMetSigs = WOMatQARec QAMetOOSs = WOMatQARec QAMetResults = WOMatQARec For each QAMetStage in QAMetStages using @VM setting vPos If QAMetStage EQ 'UNLOAD' then NumTests += 1 NotApplicable = False$ TestSig = QAMetSigs<0, vPos> TestOOS = QAMetOOSs<0, vPos> TestResult = QAMetResults<0, vPos> TestSigs<0, vPos> = (TestSig NE '') TestOOSs<0, vPos> = TestOOS TestResults<0, vPos> = (TestResult NE '') end Next QAMetStage DataComp = ( ( NumTests EQ Sum(TestResults) ) and (NumTests GT 0) ) SigsComp = ( ( NumTests EQ Sum(TestSigs) ) and (NumTests GT 0) ) end StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = NotApplicable Case Stage EQ 'PSTI' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') If CINo NE '' then CITool = Xlate('CLEAN_INSP', CINo, 'INSP_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'INSP_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'PSTC' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end StageRx = StageSummary CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'CLEAN_TOOL', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'CLEAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'PSTS' Locate Stage in SigProfStages using @VM setting vPos then StageSummary = False$ end else StageSummary = True$ end CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') StageRx = StageSummary If (CINo NE '') then CITool = Xlate('CLEAN_INSP', CINo, 'SPEC_SURFSCAN_RECIPE', 'X') CISig = Xlate('CLEAN_INSP', CINo, 'SCAN_SIG', 'X') Begin Case Case ( (CITool EQ '') and (StageRx EQ True$) ) // Required data is missing StageSummary = False$ StageSummary = (CISig NE '') StageSummary = False$ Case ( (CITool NE '') and (CISig EQ '') ) // Data is present, but signature missing StageSummary = True$ StageSummary = False$ StageSummary = False$ Case Otherwise$ // Full pass StageSummary = True$ StageSummary = True$ StageSummary = True$ End Case end else If StageRx then // Data is missing StageSummary = False$ StageSummary = False$ StageSummary = False$ end else // Stage not applicable StageSummary = '' StageSummary = '' StageSummary = '' end end Case Stage EQ 'POST_QA_MET' // Gather post-epi QA metrology information NumTests = 0 TestSigs = '' TestOOSs = '' TestResults = '' Error = '' NotApplicable = True$ StageComplete = False$ DataComp = False$ SigsComp = False$ If RowExists('WO_MAT', WOMatKey) then WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey) QAMetStages = WOMatQARec QAMetSigs = WOMatQARec QAMetOOSs = WOMatQARec QAMetResults = WOMatQARec For each QAMetStage in QAMetStages using @VM setting vPos If QAMetStage EQ 'QA' then NumTests += 1 NotApplicable = False$ TestSig = QAMetSigs<0, vPos> TestOOS = QAMetOOSs<0, vPos> TestResult = QAMetResults<0, vPos> TestSigs<0, vPos> = (TestSig NE '') TestOOSs<0, vPos> = TestOOS TestResults<0, vPos> = (TestResult NE '') end Next QAMetStage DataComp = ( ( NumTests EQ Sum(TestResults) ) and (NumTests GT 0) ) SigsComp = ( ( NumTests EQ Sum(TestSigs) ) and (NumTests GT 0) ) end StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = NotApplicable Case Stage EQ 'LBLCHK' // Verify LBLCHK inv action exists in WO_MAT material log. NotApplicable = False$ InvActions = Xlate('WO_MAT', WOMatKey, 'INV_ACTION', 'X') Locate Stage in InvActions using @VM setting vPos then DataComp = True$ SigsComp = True$ end else DataComp = False$ SigsComp = False$ end StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = NotApplicable Case Stage EQ 'NCR' // Gather NCR information NotApplicable = True$ DataComp = False$ SigsComp = False$ NumSigs = 0 NumData = 0 NCRKeys = Xlate('WO_MAT', WOMatKey, 'NCR_KEYS', 'X') NCRSigs = Xlate('WO_MAT', WOMatKey, 'NCR_FINAL_SIG', 'X') If NCRKeys NE '' then NotApplicable = False$ NumKeys = DCount(NCRKeys, @VM) For each NCRNo in NCRKeys using @VM setting vPos Sig = Xlate('NCR', NCRNo, 'AUTH_REJ_SIG', 'X') If Sig NE '' then NumSigs += 1 Error = False$ ReqFields = 'SHIFT,DEPT,DEPT_RESP,LOSS_CODE,LOSS_COMMENTS,CONTAIN_ACTIONS,LOSS_STAGE,LOSS_BY' For each ReqField in ReqFields using ',' setting cPos Val = Xlate('NCR', NCRNo, ReqField, 'X') If Val EQ '' then Error = True$ Until Error Next ReqField If Error EQ False$ then NumData += 1 Next NCRNo SigsComp = (NumKeys EQ NumSigs) DataComp = (NumKeys EQ NumData) end StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = NotApplicable Case Stage EQ 'SAP_BATCH_ID' // Verify SAP Batch ID is not null SAPBatchNo = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X') DataComp = (SapBatchNo NE '') SigsComp = DataComp StageSummary = DataComp StageSummary = SigsComp StageSummary = (DataComp and SigsComp) StageSummary = False$ Case Otherwise$ // Check stage signature to determine if it is complete. StageComplete = True$ SigInfo = Signature_Services('GetSigInfo', WOMatKey, Stage, False$) If Error_Services('NoError') then Sig = SigInfo<1> StageComplete = (Sig NE '') end else // Stage may not apply to this cassette ErrorMessage = Error_Services('GetMessage') NotApplicable = (IndexC(ErrorMessage, 'signature profile', 1) GT 0) If NotApplicable EQ True$ then StageComplete = 2 end If StageComplete EQ 0 then Error = Stage:' not signed.' End Case end Response = StageSummary end service Service GetCassSummary(WOMatKey) CassSummary = '' If RowExists('WO_MAT', WOMatKey) then // Collect signature and metrology pass/fail data. Stages = Database_Services('ReadDataRow', 'APP_INFO', 'SILICON_STAGE_LIST') For each Stage in Stages using @FM setting fPos StageSummary = Signature_Services('GetStageSummary', WOMatKey, Stage) CassSummary = Stage CassSummary = StageSummary CassSummary = StageSummary CassSummary = StageSummary CassSummary = StageSummary Next Stage end Response = CassSummary end service Service GetStageIDs() Response = Database_Services('ReadDataRow', 'APP_INFO', 'SILICON_STAGE_LIST') end service Service PostEpiSigReady(RDSNo) ErrCode = '' ErrorMessage = '' RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) WONo = RDSRec CassNo = RDSRec Reactor = RDSRec WOStep = 1 WOMatKey = WONo:'*':CassNo ReprocessedMat = XLATE('WO_MAT', WOMatKey, 'REPROCESSED_MAT', 'X') WOMatCurrStatus = obj_WO_Mat('CurrStatus', WOMatKey) If (WOMatCurrStatus NE 'HOLD') then Set_Status(0) obj_WO_Mat('MQAComp', WOMatKey:@RM:WOStep:@RM:'UNLOAD') If Not(Get_Status(ErrCode)) then Response = True$ end else ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode end end else ErrorMessage = 'Cassette is on hold and may not be signed off.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end service Service SignPostEpiStage(RDSNo, User, WMOKey) ErrorMessage = '' Begin Case Case (User EQ '') ErrorMessage = 'Error in ':Service:' service. Null User passed into service.' Case ( (RDSNo NE '') and (WMOKey NE '') ) ErrorMessage = 'Error in ':Service:' service. RDSNo and WMOKey cannot both be passed in.' Case ( (RDSNo NE '') and (WMOKey EQ '') ) // Sign RDS post-epi signature RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) WONo = RDSRec CassNo = RDSRec WOMatKey = WONo:'*':CassNo MakeupBox = Xlate('RDS', RDSNo, 'MAKEUP_BOX', 'X') RawSigDt = Date() RawSigTm = Time() SigDt = OConv(Date(), 'D2/') SigTm = Time() SigTmPlusOne = OConv(SigTm + 1, 'MTS') SigTmPlusTwo = OConv(SigTm + 2, 'MTS') SigTmPlusFive = OConv(SigTm + 5, 'MTS') SigTmPlusTen = OConv(SigTm + 10, 'MTS') SigTm = OConv(SigTm,'MTS') SigBy = User WOStep = 1 EventParms = '' EventCnt = 1 ToolID = '' WHCd = 'CR' LocCD = 'QA' Tag = '' EventParms = 'WO_MAT' EventParms = SigDt:' ':SigTm EventParms = WOStep:'POST' EventParms = 'CR' EventParms = 'POST' EventParms = WONo EventParms = CassNo EventParms = User EventParms = '' EventParms = '' CONVERT @FM TO @RM IN EventParms obj_WO_Mat_Log('Create', EventParms) IF Get_Status(ErrCode) THEN ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode END If ErrorMessage EQ '' then IF MakeupBox EQ True$ THEN EventParms = 'WO_MAT' EventParms = SigDt:' ':SigTmPlusTwo EventParms = 'RTU' EventParms = 'CR' EventParms = 'MU' EventParms = WONo EventParms = CassNo EventParms = User EventParms = '' EventParms = '' CONVERT @FM TO @RM IN EventParms obj_WO_Mat_Log('Create', EventParms) ;* * * * * INV EVENT LOG * * * * * IF Get_Status(ErrCode) THEN ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode END END If ErrorMessage EQ '' then RDSRec = User RDSRec = IConv(SigDt, 'D') RDSRec = IConv(SigTm, 'MT') + 1 Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, False$) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end end Case ( (RDSNo EQ '') and (WMOKey NE '') ) // Sign WM_OUT post-epi signature WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey) If Error_Services('NoError') then WMORec = User WMORec = Datetime() Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec, True$, False$, True$) end End Case If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end service Service QASigReady(RDSNo) ErrCode = '' ErrorMessage = '' RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) WONo = RDSRec CassNo = RDSRec Reactor = RDSRec WOStep = 1 WOMatKey = WONo:'*':CassNo ReactorType = Xlate('RDS', RDSNo, 'REACTOR_TYPE', 'X') ****************************************** * Verify if the Post-EPI has been signed * ****************************************** PostEpiSig = Xlate('RDS', RDSNo, 'POST_EPI_SIG', 'X') IF (PostEpiSig = '') THEN ErrorMessage = 'Process Error':@SVM:'Technician Signature Required before Final QA Verification.' END If ErrorMessage EQ '' then IF Not(MemberOf(@USER4,'BYPASS')) THEN IF (PostEpiSig EQ @USER4) THEN ErrorMessage = 'User ':QUOTE(PostEpiSig):' has signed this RDS for Post-Epi.' ErrorMessage := 'Another qualified user must sign FQA verification' END END end *************************************** * Verify Metrology has been completed * *************************************** If ErrorMessage EQ '' then Set_Status(0) obj_WO_Mat('MQAComp',WONo:'*':CassNo:@RM:WOStep:@RM:'QA') ErrCode = '' IF Get_Status(ErrCode) THEN ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode END end *********************************************** * Verify RDS_TEST record has measurement data * *********************************************** If ErrorMessage EQ '' then ThickAvg = Xlate('RDS', RDSNo, 'TTHICK_AVG_ALL', 'X') If ThickAvg EQ '' then ErrorMessage = 'RDS metrology measurement data is missing. FQA cannot be signed.' end ResAvg = Xlate('RDS', RDSNo, 'TRES_AVG_ALL', 'X') If ResAvg EQ '' then ErrorMessage = 'RDS Resistivity measurement data is missing. FQA cannot be signed.' Recipients = XLATE('SEC_GROUPS', 'OI_ADMIN', 'USER', 'X') SentFrom = 'OI Admin' Subject = 'Missing Resistivity Avg data' Message = RDSNo: ' failed FQA due to missing resistivity average data.' AttachWindow = '' AttachKey = '' SendToGroup = '' Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup obj_Notes('Create',Parms) end end ************************************************ * Verify Signatures Profile has been fulfilled * ************************************************ If ErrorMessage EQ '' then Signature_Services('CheckSigOrder', WOMatKey, 'QA') If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end If ErrorMessage EQ '' then Signature_Services('FQAReady', WOMatKey) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end WafersOut = Xlate('RDS', RDSNo, 'WFRS_OUT', 'X') ********************************************** * Verify the FlatFinder information * ********************************************** If ErrorMessage EQ '' then EpiPartNo = Xlate('RDS', RDSNo, 'EPI_PART_NO', 'X') WaferSize = Xlate('EPI_PART', EpiPartNo, 'SUB_WAFER_SIZE', 'X') WaferSizeInch = Field(WaferSize, ' ', 3, 1) CustNo = Xlate('RDS', RDSNo, 'CUST_NO', 'X') CompanyRow = Xlate('COMPANY', CustNo, '', 'X') WaferFlatSizeInches = CompanyRow WaferFlatLengthMins = Oconv(CompanyRow, 'MD1') WaferFlatLengthMaxes = Oconv(CompanyRow, 'MD1') Locate 6 in WaferFlatSizeInches using @VM setting vPos then WaferFlatLengthMin = WaferFlatLengthMins<0, vPos> WaferFlatLengthMax = WaferFlatLengthMaxes<0, vPos> end else WaferFlatLengthMin = '' WaferFlatLengthMax = '' end WafersOut = Xlate('RDS', RDSNo, 'WFRS_OUT', 'X') // Get FlatFinder Read Value * FlatFinderWafersQty = RDSRec FlatFinderWaferLength = RDSRec If (WaferSizeInch EQ 6) then **************************************** * FlatFinder - Wafers Quantity Section * **************************************** * If (FlatFinderWafersQty NE '') then * If (FlatFinderWafersQty NE WafersOut) then * ErrMsg('Unable to sign FQA because Flat Finder and Wafers Out quantities do not match.') * RETURN 0 * end * end else * ErrMsg('Unable to sign FQA because the Flat Finder quantity is missing.') * RETURN 0 * end ************************************ * FlatFinder - Flat Length Section * ************************************ If (WaferFlatLengthMin NE '') AND (WaferFlatLengthMax NE '') then If (FlatFinderWaferLength NE '') then If (FlatFinderWaferLength GE WaferFlatLengthMin) AND (FlatFinderWaferLength LE WaferFlatLengthMax) then end else ErrMsg('Unable to sign FQA because Flat Finder wafer lengths are out of bounds.') RETURN 0 end end else ErrMsg('Unable to sign FQA because the Flat Finder wafer length is missing.') RETURN 0 end end end Begin Case Case WaferSizeInch = '6' WaferFlatSizeInches = CompanyRow WaferFlatLengthMins = Oconv(CompanyRow, 'MD1') WaferFlatLengthMaxes = Oconv(CompanyRow, 'MD1') Locate WaferSizeInch in WaferFlatSizeInches using @VM setting vPos then WaferFlatLengthMin = WaferFlatLengthMins<0, vPos> WaferFlatLengthMax = WaferFlatLengthMaxes<0, vPos> end else WaferFlatLengthMin = '' WaferFlatLengthMax = '' end *************************************** * FlatFinder - Wafers Quatity Section * *************************************** * If (FlatFinderWafersQty NE '') then * If (FlatFinderWafersQty NE WafersOut) then * ErrorMessage = 'Unable to sign FQA because Flat Finder and Wafers Out quantities do not match.' * end * end else * ErrorMessage = 'Unable to sign FQA because the Flat Finder quantity is missing.' * end ************************************ * FlatFinder - Flat Length Section * ************************************ If (WaferFlatLengthMin NE '') AND (WaferFlatLengthMax NE '') then If (FlatFinderWaferLength NE '') then If (FlatFinderWaferLength GE WaferFlatLengthMin) AND (FlatFinderWaferLength LE WaferFlatLengthMax) then end else ErrorMessage = 'Unable to sign FQA because Flat Finder wafer lengths are out of bounds.' end end else ErrorMessage = 'Unable to sign FQA because the Flat Finder wafer length is missing.' end end Case WaferSizeInch = '8' // Get NotchFinder Read Value * NotchFinderWafersQty = FlatFinderWafersQty *************************************** * NotchFinder - Wafers Quatity Section * *************************************** * If (NotchFinderWafersQty NE '') then * If (NotchFinderWafersQty NE WafersOut) then * ErrorMsg = 'Unable to sign FQA because Notch Finder and Wafers Out quantities do not match.' * Error_Services('Add', ErrorMsg) * return * end * end else * ErrorMsg = 'Unable to sign FQA because the Notch Finder quantity is missing.' * Error_Services('Add', ErrorMsg) * return * end Case Otherwise$ End Case end ************************* * Verify Wafer Quantity * ************************* If ErrorMessage EQ '' then CassSchedWafers = Xlate('RDS', RDSNo, 'WAFERS_SCHEDULED', 'X') If CassSchedWafers NE WafersOut then Message = 'Unable to sign FQA because the Scheduled' : CRLF$ : 'Qty does not equal the ' Message := 'Wafers Out Qty.' : CRLF$ : 'Lead or supervisor must override.' LeadMessage = 'Scheduled Wafers Quantity does not equal the Wafers Out Quantity.' If NOT( MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') ) then Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', Message) end else Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', LeadMessage) end 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 Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : 'LEAD' : @VM : 'SUPERVISOR') Valid = Response<1> Username = Response<2> If Valid then RDSRec = Username RDSRec = Date() RDSRec = Time() Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Unable to sign FQA because the Scheduled' : CRLF$ : 'Qty does not equal the ' ErrorMessage := 'Wafers Out Qty.' : CRLF$ : 'Lead or supervisor must override.' end end else ErrorMessage = 'Unable to sign FQA because the Scheduled' : CRLF$ : 'Qty does not equal the ' ErrorMessage := 'Wafers Out Qty.' : CRLF$ : 'Lead or supervisor must override.' end end end ********************************* * Verify NCR total >= USL Fails * ********************************* If ErrorMessage EQ '' then ROTREnabled = Xlate('REACTOR', Reactor, 'ENABLE_ROTR', 'X') If (ROTREnabled EQ True$) then LWICIKey = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') NumUSLFailValues = Xlate('CLEAN_INSP', LWICIKey, 'NUM_FAILED_WAFERS', 'X') NumUSLFailCount = COUNT(NumUSLFailValues,@VM) + (NumUSLFailValues NE '') NumUSLFail = NumUSLFailValues<1,NumUSLFailCount> If NumUSLFail EQ '' then NumUSLFail = 0 TotalNCR = Xlate('RDS', RDSNo, 'TOT_REJ', 'X') If TotalNCR EQ '' then TotalNCR = 0 If NumUSLFail GT TotalNCR then Message = 'Unable to sign FQA because the total quantity of NCR wafers':CRLF$:'is less than the '| : 'number of wafers above the USL threshold.' : CRLF$ : 'A lead or supervisor must override.' LeadMessage = 'Total quantity of NCR wafers is less than the number of wafers above the USL threshold.' If NOT( MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') ) then Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', Message) end else Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', LeadMessage) end 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 Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4:@FM:'LEAD':@VM:'SUPERVISOR':@VM:'ENGINEER') Valid = Response<1> If NOT(Valid) then ErrorMessage = Message end end else ErrorMessage = Message end end end end ******************************************** * Verify NCR wafer qty >= Failed wafer qty * ******************************************** If ErrorMessage EQ '' then NCRReq = QA_Services('GetNCRRequired', WOMatKey) If NCRReq then Message = 'Unable to sign FQA because the total quantity of NCR wafers':CRLF$:'is less than the '| : 'number of wafers that failed surfscan.' : CRLF$ : 'A lead or supervisor must override.' LeadMessage = 'Total quantity of NCR wafers is less than the number of wafers that failed surfscan.' If NOT( MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') ) then Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', Message) end else Response = Msg(@Window, '', 'POST_EPI_WAFER_OUT', '', LeadMessage) end 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 Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4:@FM:'LEAD':@VM:'SUPERVISOR':@VM:'ENGINEER') Valid = Response<1> If NOT(Valid) then ErrorMessage = Message end end else ErrorMessage = Message end end end ************************* * Verify if Shift exist * ************************* If ErrorMessage EQ '' then Shift = RDSRec IF Shift EQ '' THEN ErrorMessage = 'Error in ':Service:' servce. Shift is required before signing.' END end **************************** * Verify if lot is on Hold * **************************** If ErrorMessage EQ '' then WOMatCurrStatus = obj_WO_Mat('CurrStatus', WOMatKey) IF WOMatCurrStatus EQ 'HOLD' THEN ErrorMessage = 'Error in ':Service:' service. Cassette is on Hold and may not be signed off.' END end ********************** * Check ROTR Failure * ********************** If ErrorMessage EQ '' then ROTRAction = Xlate('RDS', RDSNo, 'ROTR_ACTION', 'X') If (ROTRAction NE 'P') AND (ROTRAction NE 'A') AND (ROTRAction NE '') then ErrorMessage = 'Error in ':Service:' service. ROTR does not meet all requirements.' end end *************************************** * Verify Metrology has been completed * *************************************** If ErrorMessage EQ '' then QAMetTests = Xlate('RDS', RDSNo, 'MET_TEST_QA', 'X') If QAMetTests NE '' then QAMetMins = Xlate('RDS', RDSNo, 'MET_MIN_QA', 'X') QAMetMaxes = Xlate('RDS', RDSNo, 'MET_MAX_QA', 'X') QAMetResults = Xlate('RDS', RDSNo, 'MET_RESULT_QA', 'X') QAMetSigs = Xlate('RDS', RDSNo, 'MET_SIG_QA', 'X') For each QAMetTest in QAMetTests using @VM setting vPos QAMetMin = QAMetMins<0, vPos> QAMetMax = QAMetMaxes<0, vPos> QAMetResult = QAMetResults<0, vPos> QAMetSig = QAMetSigs<0, vPos> If QAMetTest NE '' then Begin Case Case ( (QAMetMin EQ '') and (QAMetMax EQ '') ) Null Case (QAMetResult EQ '') ErrorMessage = 'Error in ':Service:' service. Required QA Metrology results have not been entered.' Case ( (QAMetResult LT QAMetMin) or (QAMetResult GT QAMetMax) ) ErrorMessage = 'Error in ':Service:' service. One or more QA Metrology results is out of specification.' Case ( (QAMetResult NE '') and (QAMetSig EQ '') ) ErrorMessage = 'Error in ':Service:' service. One or more QA Metrology results are not signed off.' End Case end Next QAMetTest end end ****************************************** * Verify Unload Stage QA Metrology Tests * ****************************************** If ErrorMessage EQ '' then DevelopmentFlag = Xlate('DEVELOPMENT', 'HGCV', 'STATUS', 'X') If (DevelopmentFlag EQ True$) then WOMatQAKey = WOMatKey WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey) OutOfSpec = WOMatQARec OutOfSpec = Sum(OutOfSpec) If OutOfSpec GT 0 then FailReasons = WOMatQARec ErrorMessage = 'Error in ':Service:' service. ' For each FailReason in FailReasons using @VM ErrorMessage := FailReason:' ' Next FailReason end end end ************************************************************************ * Prompt user to validate the Process Specification Stage Instructions * ************************************************************************ If ErrorMessage EQ '' then PSNo = RDSRec VerInst = Xlate('PRS_STAGE', PSNo:'*QA', 'INST', 'X') VerInst = Trim(VerInst) IF LEN(VerInst) > 5 THEN Yes = Dialog_Box( 'RDS_VER', @WINDOW, VerInst ) IF NOT(Yes) THEN ErrorMessage = 'Error in ':Service:'. PRS_STAGE instructions must be accepted.' END END end If ErrorMessage NE '' then Response = False$ Error_Services('Add', ErrorMessage) end else Response = True$ end end service Service SignQAStage(RDSNo, User) ErrorMessage = '' If RDSNo NE '' then RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) WONo = RDSRec CassNo = RDSRec WOMatKey = WONo:'*':CassNo MakeupBox = Xlate('RDS', RDSNo, 'MAKEUP_BOX', 'X') RawSigDt = Date() RawSigTm = Time() SigDt = OConv(Date(), 'D2/') SigTm = Time() SigTmPlusOne = OConv(SigTm + 1, 'MTS') SigTmPlusTwo = OConv(SigTm + 2, 'MTS') SigTmPlusFive = OConv(SigTm + 5, 'MTS') SigTmPlusTen = OConv(SigTm + 10, 'MTS') SigTm = OConv(SigTm,'MTS') SigBy = User WOStep = 1 EventParms = '' EventCnt = 1 ToolID = '' WHCd = 'CR' LocCD = 'QA' Tag = '' EventParms = 'WO_MAT' EventParms = SigDt:' ':SigTm EventParms = WOStep:'QA' EventParms = 'CR' EventParms = 'QA' EventParms = WONo EventParms = CassNo EventParms = User EventParms = '' EventParms = '' CONVERT @FM TO @RM IN EventParms obj_WO_Mat_Log('Create', EventParms) IF Get_Status(ErrCode) THEN ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode END If ErrorMessage EQ '' then IF MakeupBox EQ True$ THEN EventParms = 'WO_MAT' EventParms = SigDt:' ':SigTmPlusTwo EventParms = 'RTU' EventParms = 'CR' EventParms = 'MU' EventParms = WONo EventParms = CassNo EventParms = User EventParms = '' EventParms = '' CONVERT @FM TO @RM IN EventParms obj_WO_Mat_Log('Create', EventParms) ;* * * * * INV EVENT LOG * * * * * IF Get_Status(ErrCode) THEN ErrorMessage = 'Error in ':Service:' service. Error code: ':ErrCode END END If ErrorMessage EQ '' then RDSRec = User RDSRec = IConv(SigDt, 'D') RDSRec = IConv(SigTm, 'MT') + 1 Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, False$) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end service Service CleanInspSigReady(RDSNo, Stage) ErrorMessage = '' If ( (RDSNo NE '') and (Stage NE '') ) then WONo = Xlate('RDS', RDSNo, 'WO', 'X') CassNo = Xlate('RDS', RDSNo, 'CASS_NO', 'X') WOMatKey = WONo:'*':CassNo Signature_Services('CheckSigOrder', WOMatKey, Stage) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') Begin Case Case ( (Stage EQ 'PREI') or (Stage EQ 'PREC') or (Stage EQ 'PRES') ) CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') Case ( (Stage EQ 'FWII') or (Stage EQ 'FWIC') or (Stage EQ 'FWIS') ) CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') Case ( (Stage EQ 'LWII') or (Stage EQ 'LWIC') or (Stage EQ 'LWIS') ) CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') Case ( (Stage EQ 'PSTI') or (Stage EQ 'PSTC') or (Stage EQ 'PSTS') ) CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') Case Otherwise$ ErrorMessage = 'Error in ':Service:' service. Invalid stage ID passed into service.' End Case If ErrorMessage EQ '' then If RowExists('CLEAN_INSP', CINo) then CIRow = Database_Services('ReadDataRow', 'CLEAN_INSP', CINo) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. No ':Stage:' record on file for RDS ':RDSNo:'!' end end Begin Case Case ErrorMessage NE '' Null Case ( (Stage EQ 'PREI') or (Stage EQ 'FWII') or (Stage EQ 'LWII') or (Stage EQ 'PSTI') ) // Verify each inspection row has data. // Front side data InspTools = CIRow InspLPDs = CIRow InspScratches = CIRow InspScratchLengths = CIRow InspPits = CIRow InspMounds = CIRow InspStackFaults = CIRow InspSpikes = CIRow InspSpots = CIRow InspFOVs = CIRow InspBLDefects = CIRow InspSigs = CIRow InspSigDTMs = CIRow // Front side specs SpecLPD = CIRow SpecScratches = CIRow SpecScratchLen = CIRow SpecPits = CIRow SpecMounds = CIRow SpecStackFaults = CIRow SpecSpikes = CIRow SpecSpots = CIRow SpecFOV = CIRow SpecBLDefects = CIRow // Backside data InspBsideScratches = CIRow InspBsideScratchLen = CIRow InspBsideNodules = CIRow InspBsideSpikes = CIRow // Backside specs SpecBsideScratches = CIRow SpecBsideScratchLen = CIRow SpecBsideNodules = CIRow SpecBsideSpikes = CIRow // Verify front side and back side data NumRows = DCount(InspTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows RowLPD = InspLPDs<0, RowIndex> RowScratches = InspScratches<0, RowIndex> RowScratchLen = InspScratchLengths<0, RowIndex> RowPits = InspPits<0, RowIndex> RowMounds = InspMounds<0, RowIndex> RowStackFaults = InspStackFaults<0, RowIndex> RowSpikes = InspSpikes<0, RowIndex> RowSpots = InspSpots<0, RowIndex> RowFOV = InspFOVs<0, RowIndex> RowBLDefects = InspBLDefects<0, RowIndex> RowBsideScratches = InspBsideScratches<0, RowIndex> RowBsideScratchLen = InspBsideScratchLen<0, RowIndex> RowBsideNodules = InspBsideNodules<0, RowIndex> RowBsideSpikes = InspBsideSpikes<0, RowIndex> If ( (SpecLPD NE '') and (RowLPD EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection LPD data is missing.' end If ( (ErrorMessage EQ '') and (SpecScratches NE '') and (RowScratches EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection scratches data is missing.' end If ( ( ErrorMessage EQ '') and (SpecScratchLen NE '') and (RowScratchLen EQ '' ) ) then ErrorMessage = 'Error in ':Service:' service. Inspection scratches data is missing.' end If ( (ErrorMessage EQ '') and (SpecPits NE '') and (RowPits EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection pits data is missing.' end If ( (ErrorMessage EQ '') and (SpecMounds NE '') and (RowMounds EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection mounds data is missing.' end If ( (ErrorMessage EQ '') and (SpecStackFaults NE '') and (RowStackFaults EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection stack faults data is missing.' end If ( (ErrorMessage EQ '') and (SpecSpikes NE '') and (RowSpikes EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection spikes data is missing.' end If ( (ErrorMessage EQ '') and (SpecSpots NE '') and (RowSpots EQ '' ) ) then ErrorMessage = 'Error in ':Service:' service. Inspection spots data is missing.' end If ( (ErrorMessage EQ '') and (SpecFOV NE '') and (RowFOV EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection FOV data is missing.' end If ( (ErrorMessage EQ '') and (SpecBLDefects NE '') and (RowBLDefects EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection BL defects data is missing.' end If ( (ErrorMessage EQ '') and (SpecBsideScratches NE '') and (RowBsideScratches EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection back side scratches data is missing.' end If ( (ErrorMessage EQ '') and (SpecBsideScratchLen NE '') and (RowBsideScratchLen EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection back side scratch length data is missing.' end If ( (ErrorMessage EQ '') and (SpecBsideNodules NE '') and (RowBsideNodules EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection back side nodules data is missing.' end If ( (ErrorMessage EQ '') and (SpecBsideSpikes NE '') and (RowBsideSpikes EQ '') ) then ErrorMessage = 'Error in ':Service:' service. Inspection back side spikes data is missing.' end Until ErrorMessage NE '' Next RowIndex end Case ( (Stage EQ 'PREC') or (Stage EQ 'FWIC') or (Stage EQ 'LWIC') or (Stage EQ 'PSTC') ) // Verify each cleans row has a tool. CleanTools = CIRow NumRows = DCount(CleanTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows RowTool = CleanTools<0, RowIndex> If RowTool EQ '' then ErrorMessage = 'Error in ':Service:' service. Clean tool ID is missing.' end Until ErrorMessage NE '' Next RowIndex end Case ( (Stage EQ 'PRES') or (Stage EQ 'FWIS') or (Stage EQ 'LWIS') or (Stage EQ 'PSTS') ) // Verify surfscan row has a tool. ScanTools = CIRow NumRows = DCount(ScanTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows RowTool = ScanTools<0, RowIndex> If RowTool EQ '' then ErrorMessage = 'Error in ':Service:' service. Scan tool ID is missing.' end Until ErrorMessage NE '' Next RowIndex end End Case end If ErrorMessage EQ '' then Response = True$ end else Error_Services('Add', ErrorMessage) Response = False$ end end service Service SignCleanInsp(RDSNo, Stage=CI_STAGES, User) ErrorMessage = '' If ( (RDSNo NE '') and (Stage NE '') and (User NE '') ) then SigDTM = Datetime() WONo = Xlate('RDS', RDSNo, 'WO', 'X') CassNo = Xlate('RDS', RDSNo, 'CASS_NO', 'X') WOMatKey = WONo:'*':CassNo Begin Case Case ( (Stage EQ 'PREI') or (Stage EQ 'PREC') or (Stage EQ 'PRES') ) CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') Case ( (Stage EQ 'FWII') or (Stage EQ 'FWIC') or (Stage EQ 'FWIS') ) CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X') Case ( (Stage EQ 'LWII') or (Stage EQ 'LWIC') or (Stage EQ 'LWIS') ) CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') Case ( (Stage EQ 'PSTI') or (Stage EQ 'PSTC') or (Stage EQ 'PSTS') ) CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X') Case Otherwise$ ErrorMessage = 'Error in ':Service:' service. Invalid stage ID passed into service.' End Case If ErrorMessage EQ '' then If RowExists('CLEAN_INSP', CINo) then CIRow = Database_Services('ReadDataRow', 'CLEAN_INSP', CINo) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end else OrigCIRow = CIRow end end else ErrorMessage = 'Error in ':Service:' service. No ':Stage:' record on file for RDS ':RDSNo:'!' end end Begin Case Case ErrorMessage NE '' Null Case ( (Stage EQ 'PREI') or (Stage EQ 'FWII') or (Stage EQ 'LWII') or (Stage EQ 'PSTI') ) InspTools = CIRow InspSigs = CIRow InspSigDTMs = CIRow NumRows = DCount(InspTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows // Sign each row if no signature present If InspSigs<0, RowIndex> EQ '' then InspSigs<0, RowIndex> = User InspSigDTMs<0, RowIndex> = SigDTM end Until ErrorMessage NE '' Next RowIndex end CIRow = InspSigs CIRow = InspSigDTMs Case ( (Stage EQ 'PREC') or (Stage EQ 'FWIC') or (Stage EQ 'LWIC') or (Stage EQ 'PSTC') ) CleanTools = CIRow CleanSigs = CIRow CleanSigDTMs = CIRow NumRows = DCount(CleanTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows // Sign each row if no signature present If CleanSigs<0, RowIndex> EQ '' then CleanSigs<0, RowIndex> = User CleanSigDTMs<0, RowIndex> = SigDTM end Until ErrorMessage NE '' Next RowIndex end CIRow = CleanSigs CIRow = CleanSigDTMs Case ( (Stage EQ 'PRES') or (Stage EQ 'FWIS') or (Stage EQ 'LWIS') or (Stage EQ 'PSTS') ) ScanTools = CIRow SurfSigs = CIRow SurfSigDTMs = CIRow NumRows = DCount(ScanTools, @VM) If NumRows GT 0 then For RowIndex = 1 to NumRows // Sign each row if no signature present If SurfSigs<0, RowIndex> EQ '' then SurfSigs<0, RowIndex> = User SurfSigDTMs<0, RowIndex> = SigDTM end Until ErrorMessage NE '' Next RowIndex end CIRow = SurfSigs CIRow = SurfSigDTMs End Case end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo, user, or stage passed in.' end If ErrorMessage EQ '' then If CIRow NE OrigCIRow then Database_Services('WriteDataRow', 'CLEAN_INSP', CINo, CIRow) If Error_Services('NoError') then Response = True$ end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') Error_Services('Add', ErrorMessage) Response = False$ end end else Error_Services('Add', ErrorMessage) Response = False$ end end service Service QAMetSigReady(RDSNo, QAStage=QA_STAGES, Slot=SLOTS, WOMatQAKey) ErrorMessage = '' If ( (RDSNo NE '' or WOMatQAKey NE '') and (QAStage NE '') and (Slot NE '') ) then If RDSNo NE '' then WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') end else WOMatKey = WOMatQAKey end If WOMatKey NE '' then If RowExists('WO_MAT_QA', WOMatKey) then WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey) If Error_Services('HasError') then ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end else WOMatQAStages = WOMatQARec end end else ErrorMessage = 'Error in ':Service:' service. No WO_MAT_QA record on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null WO_MAT_KEY returned for RDS ':RDSNo:'!' end Begin Case Case ErrorMessage NE '' Null Case ( (QAStage EQ 'LOAD') or (QAStage EQ 'QA') or (QAStage EQ 'MO_QA') ) Done = False$ WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) ReactorType = Xlate('WO_MAT', WOMatKey, 'REACTOR_TYPE', 'X') TestSlots = WOMatQARec // Check for QA Stage Supplements UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'WO_MAT', WOMatKey, 'QA') If UnacknowledgedSupp NE FALSE$ then ErrorMessage = 'The QA stage supplements must be acknowledged before the load operation can be signed.' end If ReactorType EQ 'EPP' then WMOKey = WOMatRec WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey) MUWfrIDs = WOMatRec MUWfrResults = WMORec end else MUWfrIDs = WOMatRec MUWfrResults = WOMatRec end For each WOMatQAStage in WOMatQAStages using @VM setting vPos TestSlot = TestSlots<0, vPos> If ( (WOMatQAStage EQ QAStage) and (Slot EQ TestSlot) ) then Done = True$ // Compare Met Result to Met Min and Met Max TestProp = WOMatQARec MetResult = WOMatQARec MetMin = WOMatQARec MetMax = WOMatQARec Begin Case Case MetResult EQ '' ErrorMessage = 'Error in ':Service:' service. Metrology result for stage ':QAStage:' slot ':Slot:' is missing.' Case ( (MetResult LT MetMin) or (MetResult GT MetMax) ) ErrorMessage = 'Error in ':Service:' service. Metrology result is out of spec for stage ':QAStage:' slot ':Slot:'.' End Case // Compare Std Dev Result to Std Dev Max StdDevResult = WOMatQARec StdDevMax = WOMatQARec Begin Case Case StdDevResult EQ '' // Std Dev data is not always supplied. Null Case StdDevResult GT StdDevMax ErrorMessage = 'Error in ':Service:' service. StdDev exceeds spec for stage ':QAStage:'.' End Case If TestProp EQ 'THICK' then // Ensure makeup wafer thickness values are in spec and that at least one wafer // from each makeup box has a thickness result. // Build a list of unique makeup boxes MUBoxes = '' MUThickTests = '' If MUWfrIDs NE '' then For each MUWfrID in MUWfrIDs using @VM setting vPos If MUWfrID NE '' then MUBox = Field(MUWfrID, '.', 1, 2) Locate MUBox in MUBoxes using @VM setting MUIndex else MUBoxes<0, -1> = MUBox end end Next MUWfrID // Verify makeup wafers are also within spec For each MUWfrID in MuWfrIDs using @VM setting vPos If MUWfrID NE '' then MUBox = Field(MUWfrID, '.', 1, 2) MUWfrResult = MUWfrResults<0, vPos> Locate MUBox in MUBoxes using @VM setting MUIndex then MUThickTests<0, MUIndex> = True$ end If MUWfrResult NE '' then If ( (MUWfrResult LT MetMin) or (MUWfrResult GT MetMax) ) then ErrorMessage = 'Error in ':Service:' service. Metrology result is out of spec for stage ':QAStage:' makeup wafer ID ':MUWfrID:'.' end end end Next MUWfrID end If MUBoxes NE '' then // Verify each MU Box has at least one thickness result For each MUBox in MUBoxes using @VM setting MUBoxIndex If MUThickTests<0, MUBoxIndex> NE True$ then ErrorMessage = 'Error in ':Service:' service. At least one metrology result is required for stage ':QAStage:' makeup box ID ':MUBox:'.' end Next MUBox end end end Until ( (ErrorMessage NE '') or (Done EQ True$) ) Next WOMatQAStage Case QAStage EQ 'UNLOAD' // Leverage fail reason column calculated by WO_MAT_QA_ACTIONS For each WOMatQAStage in WOMatQAStages using @VM setting vPos If WOMatQAStage EQ QAStage then FailReason = WOMatQARec If ( (FailReason NE '') | and (FailReason NE 'THICK_ONLY UNLOAD product measurement test has not been signed.') | and (FailReason NE 'CRES UNLOAD product measurement test has not been signed.') | and (FailReason NE 'UNLOAD LW_RHO product measurement test has not been signed.' ) ) then ErrorMessage = 'Error in ':Service:' service. ':FailReason end end Until ErrorMessage NE '' Next WOMatQAStage End Case end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo or stage passed in.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service SignQAMet(RDSNo, QAStage=QA_STAGES, User, Slot=SLOTS, WOMatQAKey) ErrorMessage = '' If ( (RDSNo NE '' or WOMatQAKey NE '') and (QAStage NE '') ) then If RDSNo NE '' then WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') end else WOMatKey = WOMatQAKey end If WOMatKey NE '' then If RowExists('WO_MAT_QA', WOMatKey) then WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey) If Error_Services('HasError') then ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end else WOMatQAStages = WOMatQARec WOMatQASlots = WOMatQARec end end else ErrorMessage = 'Error in ':Service:' service. No WO_MAT_QA record on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null WO_MAT_KEY returned for RDS ':RDSNo:'!' end If ErrorMessage EQ '' then SigDTM = Datetime() For each WOMatQAStage in WOMatQAStages using @VM setting vPos TestSlot = WOMatQASlots<0, vPos> If ( (WOMatQAStage EQ QAStage) and (TestSlot EQ Slot) ) then // Sign each row if no signature present. If WOMatQARec EQ '' then WOMatQARec = User WOMatQARec = SigDTM end end Next WOMatQAStage Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatKey, WOMatQARec) If Error_Services('HasError') then ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo or stage passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service ROTRSigReady(RDSNo) ErrorMessage = '' If RDSNo NE '' then LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') If LWICINo NE '' then LWICIRec = Database_Services('ReadDataRow', 'CLEAN_INSP', LWICINo) If Error_Services('NoError') then ROTRAction = LWICIRec If ROTRAction NE 'F' then ErrorMessage = 'Error in ':Service:' service. ROTR does not require acceptance.' end end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. No LWI CLEAN_INSP record on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service SignROTR(RDSNo, User, ROTRReason) ErrorMessage = '' If ( (RDSNo NE '') and (User NE '') and (ROTRReason NE '') ) then LWICINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X') If LWICINo NE '' then LWICIRec = Database_Services('ReadDataRow', 'CLEAN_INSP', LWICINo) If Error_Services('NoError') then ROTRSig = LWICIRec If ROTRSig EQ '' then // Only sign ROTR Acceptance if no signature present. LWICIRec = User LWICIRec = Datetime() LWICIRec = ROTRReason LWICIRec = 'A' ; // Accepted Database_Services('WriteDataRow', 'CLEAN_INSP', LWICINo, LWICIRec) If Error_Services('HasError') then ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. No LWI CLEAN_INSP record on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service NCRSigReady(RDSNo) ErrorMessage = '' If RDSNo NE '' then WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') If WOMatKey NE '' then NCRKeys = Xlate('WO_MAT', WOMatKey, 'NCR_KEYS', 'X') If NCRKeys NE '' then For each NCRKey in NCRKeys using @VM setting vPos Error = False$ ReqFields = 'SHIFT,DEPT,DEPT_RESP,LOSS_CODE,LOSS_COMMENTS,CONTAIN_ACTIONS,LOSS_STAGE,LOSS_BY' For each ReqField in ReqFields using ',' setting cPos Val = Xlate('NCR', NCRKey, ReqField, 'X') If Val EQ '' then ErrorMessage = 'Error in ':Service:' service. No NCRs on file for RDS ':RDSNo:'!' end Until ErrorMessage NE '' Next ReqField Until ErrorMessage NE '' Next NCRKey end else ErrorMessage = 'Error in ':Service:' service. No NCRs on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. No WO_MAT_KEY on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service SignNCRs(RDSNo, User) ErrorMessage = '' If RDSNo NE '' then WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X') If WOMatKey NE '' then NCRKeys = Xlate('WO_MAT', WOMatKey, 'NCR_KEYS', 'X') If NCRKeys NE '' then SigDTM = Datetime() WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) If Error_Services('NoError') then For each NCRKey in NCRKeys using @VM setting vPos // Sign each NCR NCRRec = Database_Services('ReadDataRow', 'NCR', NCRKey) If Error_Services('NoError') then NCRRec = User NCRRec = User NCRRec = SigDTM NCRRec = 'C' Database_Services('WriteDataRow', 'NCR', NCRKey, NCRRec) If Error_Services('NoError') then // Sign WO_MAT NCR sig column Locate NCRKey in WOMatRec using @VM setting Pos then CurrSig = Trim(WOMatRec) If CurrSig EQ '' then WOMatRec = User WOMatRec = SigDTM Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec) If Error_Services('HasError') then ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end end else ErrorMessage = 'Error in ':Service:' service. Failed to locate NCR key ':NCRKey:' in WO_MAT record ':WOMatKey:'!' end end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end Until ErrorMessage NE '' Next NCRKey end else ErrorMessage = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. No NCRs on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. No WO_MAT_KEY on file for RDS ':RDSNo:'!' end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service Service SignSupplement(RDSNo, User) ErrorMessage = '' If RDSNo NE '' then RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) If Error_Services('NoError') then RDSRec = User RDSRec = Date() RDSRec = Time() RDSRec = True$ Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$) If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Error in ':Service:' service. Null RDSNo passed into service.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) Response = False$ end else Response = True$ end end service //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GetMostRecentSig: NumRows = DCount(StageRows, @VM) SignatureFound = False$ For RowIndex = NumRows to 1 Step -1 Signature = Signatures<0, RowIndex> SigDTM = SigDTMs<0, RowIndex> If Signature NE '' then SignatureFound = True$ Until SignatureFound EQ True$ Next RowIndex return