Initial commit. Create FQASignatureReady service in QA_SERVICES. Create SignFQA service in SIGNATURE_SERVICES. Commit remaining portion of project. Implement changes requested in review meeting. Fix typo. Add new MU logic to final entry point. Restrict logic to only apply to 'THICK' inspections. Bypass new logic if Biorad 4 and 5 are down.
2924 lines
140 KiB
Plaintext
2924 lines
140 KiB
Plaintext
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 SRP_Array
|
|
Declare function Database_Services, obj_WO_Mat, Dialog_Box, MemberOf, Msg, QA_Services, Datetime, Supplement_Services
|
|
Declare function Environment_Services, GetTickCount
|
|
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, Obj_Rds, Lot_Event_Services, Mona_Services
|
|
|
|
PSNKey = ServiceKeyID
|
|
ReactorKey = ServiceKeyID
|
|
|
|
IsProd = Environment_Services('IsProd')
|
|
If IsProd EQ True$ then
|
|
MonaResource = 'GRP_OPENINSIGHT_MES_OP_FE_SIGNATURESERVICES'
|
|
end else
|
|
MonaResource = 'GRP_OPENINSIGHT_MES_OP_FE_DEV_SIGNATURESERVICES'
|
|
end
|
|
|
|
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<WO_MAT_INV_LOCATION$>
|
|
actionRec = rec<WO_MAT_INV_ACTION$>
|
|
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<WO_MAT_INV_USER$, idx> NE '' AND rec<WO_MAT_INV_DTM$, idx> NE '') then
|
|
retVal = 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
Response = retVal
|
|
|
|
end service
|
|
|
|
|
|
Service GetSigProfile(WOMatKey, UseCaching, RDSNo)
|
|
StartTick = GetTickCount()
|
|
MetricName = 'GetSigProfile'
|
|
|
|
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
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
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)
|
|
StartTick = GetTickCount()
|
|
MetricName = 'CheckSigOrder'
|
|
|
|
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
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
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<SS_PASS$> = ( (VerSig NE '') and (VerifyQty NE '') )
|
|
StageSummary<SS_SIG$> = (VerSig NE '')
|
|
StageSummary<SS_DATA$> = (VerifyQty NE '')
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = 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<SS_PASS$> = (SupplFlag EQ True$) and (SupplAckReq EQ False$)
|
|
StageSummary<SS_SIG$> = (SupplSig NE '')
|
|
StageSummary<SS_DATA$> = (SupplFlag EQ True$)
|
|
StageSummary<SS_NA$> = (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<SS_PASS$> = ( (LoadSig NE '') and (WafersIn NE '') )
|
|
StageSummary<SS_SIG$> = (LoadSig NE '')
|
|
StageSummary<SS_DATA$> = (WafersIn NE '')
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = 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<SS_PASS$> = (UnloadSig NE '')
|
|
StageSummary<SS_SIG$> = (UnloadSig NE '')
|
|
StageSummary<SS_DATA$> = True$ ; // No data for this stage entered by user
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = 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<SS_PASS$> = (PostEpiSig NE '')
|
|
StageSummary<SS_SIG$> = (PostEpiSig NE '')
|
|
StageSummary<SS_DATA$> = True$ ; // No data for this stage entered by user
|
|
StageSummary<SS_NA$> = 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<SS_PASS$> = (FQASig NE '')
|
|
StageSummary<SS_SIG$> = (FQASig NE '')
|
|
StageSummary<SS_DATA$> = True$ ; //Signature_Services('QASigReady', RDSNo)
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = 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<SS_PASS$> = (TWSigned and TestComp and Not(OutOfSpec))
|
|
StageSummary<SS_SIG$> = TestComp
|
|
StageSummary<SS_DATA$> = TestComp
|
|
StageSummary<SS_NA$> = False$ ; // I think RDS metrology is always required.
|
|
end
|
|
end
|
|
Case Stage EQ 'PREI'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'PREC'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'PRES'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
CINo = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X')
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'FWII'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'FWIC'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'FWIS'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
CINo = Xlate('RDS', RDSNo, 'FWI_CI_NO', 'X')
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
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<WO_MAT_QA_STAGE$>
|
|
QAMetSigs = WOMatQARec<WO_MAT_QA_SIG$>
|
|
QAMetOOSs = WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
|
|
QAMetResults = WOMatQARec<WO_MAT_QA_RESULT$>
|
|
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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = NotApplicable
|
|
Case Stage EQ 'LWII'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'LWIC'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'LWIS'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
CINo = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X')
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
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<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
StageSummary<SS_NA$> = False$
|
|
Case ( (ROTRAction EQ 'F') and (CISig EQ '') and (ROTRActionReason EQ 'SurfScan signature is missing.') )
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
StageSummary<SS_NA$> = False$
|
|
Case ( (ROTRAction EQ 'F') and (CISig EQ '') )
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
StageSummary<SS_NA$> = False$
|
|
Case Otherwise$
|
|
// Pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
StageSummary<SS_NA$> = False$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
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<WO_MAT_QA_STAGE$>
|
|
QAMetSigs = WOMatQARec<WO_MAT_QA_SIG$>
|
|
QAMetOOSs = WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
|
|
QAMetResults = WOMatQARec<WO_MAT_QA_RESULT$>
|
|
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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = NotApplicable
|
|
Case Stage EQ 'PSTI'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'PSTC'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
end
|
|
end
|
|
Case Stage EQ 'PSTS'
|
|
Locate Stage in SigProfStages using @VM setting vPos then
|
|
StageSummary<SS_NA$> = False$
|
|
end else
|
|
StageSummary<SS_NA$> = True$
|
|
end
|
|
CINo = Xlate('RDS', RDSNo, 'POST_CI_NO', 'X')
|
|
StageRx = StageSummary<SS_NA$>
|
|
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<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = (CISig NE '')
|
|
StageSummary<SS_PASS$> = False$
|
|
Case ( (CITool NE '') and (CISig EQ '') )
|
|
// Data is present, but signature missing
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
Case Otherwise$
|
|
// Full pass
|
|
StageSummary<SS_DATA$> = True$
|
|
StageSummary<SS_SIG$> = True$
|
|
StageSummary<SS_PASS$> = True$
|
|
End Case
|
|
end else
|
|
If StageRx then
|
|
// Data is missing
|
|
StageSummary<SS_DATA$> = False$
|
|
StageSummary<SS_SIG$> = False$
|
|
StageSummary<SS_PASS$> = False$
|
|
end else
|
|
// Stage not applicable
|
|
StageSummary<SS_DATA$> = ''
|
|
StageSummary<SS_SIG$> = ''
|
|
StageSummary<SS_PASS$> = ''
|
|
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<WO_MAT_QA_STAGE$>
|
|
QAMetSigs = WOMatQARec<WO_MAT_QA_SIG$>
|
|
QAMetOOSs = WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
|
|
QAMetResults = WOMatQARec<WO_MAT_QA_RESULT$>
|
|
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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = 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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = 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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = 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<SS_DATA$> = DataComp
|
|
StageSummary<SS_SIG$> = SigsComp
|
|
StageSummary<SS_PASS$> = (DataComp and SigsComp)
|
|
StageSummary<SS_NA$> = 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<fPos, 1> = Stage
|
|
CassSummary<fPos, 2> = StageSummary<SS_PASS$>
|
|
CassSummary<fPos, 3> = StageSummary<SS_SIG$>
|
|
CassSummary<fPos, 4> = StageSummary<SS_DATA$>
|
|
CassSummary<fPos, 5> = StageSummary<SS_NA$>
|
|
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<RDS_WO$>
|
|
CassNo = RDSRec<RDS_CASS_NO$>
|
|
Reactor = RDSRec<RDS_REACTOR$>
|
|
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<RDS_WO$>
|
|
CassNo = RDSRec<RDS_CASS_NO$>
|
|
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<COL$LOG_FILE> = 'WO_MAT'
|
|
EventParms<COL$LOG_DTM> = SigDt:' ':SigTm
|
|
EventParms<COL$ACTION> = WOStep:'POST'
|
|
EventParms<COL$WH_CD> = 'CR'
|
|
EventParms<COL$LOC_CD> = 'POST'
|
|
EventParms<COL$WO_NOS> = WONo
|
|
EventParms<COL$CASS_NOS> = CassNo
|
|
EventParms<COL$USER_ID> = User
|
|
EventParms<COL$TAGS> = ''
|
|
EventParms<COL$TOOL_ID> = ''
|
|
|
|
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<COL$LOG_FILE> = 'WO_MAT'
|
|
EventParms<COL$LOG_DTM> = SigDt:' ':SigTmPlusTwo
|
|
EventParms<COL$ACTION> = 'RTU'
|
|
EventParms<COL$WH_CD> = 'CR'
|
|
EventParms<COL$LOC_CD> = 'MU'
|
|
EventParms<COL$WO_NOS> = WONo
|
|
EventParms<COL$CASS_NOS> = CassNo
|
|
EventParms<COL$USER_ID> = User
|
|
EventParms<COL$TAGS> = ''
|
|
EventParms<COL$TOOL_ID> = ''
|
|
|
|
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<RDS_POST_EPI_SIG$> = User
|
|
RDSRec<RDS_POST_EPI_SIG_DATE$> = IConv(SigDt, 'D')
|
|
RDSRec<RDS_POST_EPI_SIG_TIME$> = 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<WM_OUT_POST_EPI_SIG$> = User
|
|
WMORec<WM_OUT_POST_EPI_SIG_DTM$> = 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<RDS_WO$>
|
|
CassNo = RDSRec<RDS_CASS_NO$>
|
|
Reactor = RDSRec<RDS_REACTOR$>
|
|
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<COMPANY_WAFER_FLAT_WAFER_SIZE_INCH$>
|
|
WaferFlatLengthMins = Oconv(CompanyRow<COMPANY_WAFER_FLAT_LENGTH_MIN$>, 'MD1')
|
|
WaferFlatLengthMaxes = Oconv(CompanyRow<COMPANY_WAFER_FLAT_LENGTH_MAX$>, '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<RDS_FLATFINDER_WAFER_CNT$>
|
|
FlatFinderWaferLength = RDSRec<RDS_FLATFINDER_FLAT_LENGTH$>
|
|
|
|
|
|
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<COMPANY_WAFER_FLAT_WAFER_SIZE_INCH$>
|
|
WaferFlatLengthMins = Oconv(CompanyRow<COMPANY_WAFER_FLAT_LENGTH_MIN$>, 'MD1')
|
|
WaferFlatLengthMaxes = Oconv(CompanyRow<COMPANY_WAFER_FLAT_LENGTH_MAX$>, '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<RDS_WAFER_OUT_SIG$> = Username
|
|
RDSRec<RDS_WAFER_OUT_DATE$> = Date()
|
|
RDSRec<RDS_WAFER_OUT_TIME$> = 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<RDS_SHIFT$>
|
|
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
|
|
WOMatQAKey = WOMatKey
|
|
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
|
|
OutOfSpec = WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
|
|
OutOfSpec = Sum(OutOfSpec)
|
|
If OutOfSpec GT 0 then
|
|
FailReasons = WOMatQARec<WO_MAT_QA_FAIL_REASON$>
|
|
ErrorMessage = 'Error in ':Service:' service. '
|
|
For each FailReason in FailReasons using @VM
|
|
ErrorMessage := FailReason:' '
|
|
Next FailReason
|
|
end
|
|
end
|
|
|
|
************************************************************************
|
|
* Prompt user to validate the Process Specification Stage Instructions *
|
|
************************************************************************
|
|
If ErrorMessage EQ '' then
|
|
PSNo = RDSRec<RDS_PROD_SPEC_ID$>
|
|
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<RDS_WO$>
|
|
CassNo = RDSRec<RDS_CASS_NO$>
|
|
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<COL$LOG_FILE> = 'WO_MAT'
|
|
EventParms<COL$LOG_DTM> = SigDt:' ':SigTm
|
|
EventParms<COL$ACTION> = WOStep:'QA'
|
|
EventParms<COL$WH_CD> = 'CR'
|
|
EventParms<COL$LOC_CD> = 'QA'
|
|
EventParms<COL$WO_NOS> = WONo
|
|
EventParms<COL$CASS_NOS> = CassNo
|
|
EventParms<COL$USER_ID> = User
|
|
EventParms<COL$TAGS> = ''
|
|
EventParms<COL$TOOL_ID> = ''
|
|
|
|
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<COL$LOG_FILE> = 'WO_MAT'
|
|
EventParms<COL$LOG_DTM> = SigDt:' ':SigTmPlusTwo
|
|
EventParms<COL$ACTION> = 'RTU'
|
|
EventParms<COL$WH_CD> = 'CR'
|
|
EventParms<COL$LOC_CD> = 'MU'
|
|
EventParms<COL$WO_NOS> = WONo
|
|
EventParms<COL$CASS_NOS> = CassNo
|
|
EventParms<COL$USER_ID> = User
|
|
EventParms<COL$TAGS> = ''
|
|
EventParms<COL$TOOL_ID> = ''
|
|
|
|
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<RDS_SUP_VER_SIG$> = User
|
|
RDSRec<RDS_SUP_VER_SIG_DATE$> = IConv(SigDt, 'D')
|
|
RDSRec<RDS_SUP_VER_SIG_TIME$> = 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<CLEAN_INSP_INSP_TOOL$>
|
|
InspLPDs = CIRow<CLEAN_INSP_INSP_LPD$>
|
|
InspScratches = CIRow<CLEAN_INSP_INSP_SCRATCHES$>
|
|
InspScratchLengths = CIRow<CLEAN_INSP_INSP_SCRATCH_LEN$>
|
|
InspPits = CIRow<CLEAN_INSP_INSP_PITS$>
|
|
InspMounds = CIRow<CLEAN_INSP_INSP_MOUNDS$>
|
|
InspStackFaults = CIRow<CLEAN_INSP_INSP_STACK_FAULTS$>
|
|
InspSpikes = CIRow<CLEAN_INSP_INSP_SPIKES$>
|
|
InspSpots = CIRow<CLEAN_INSP_INSP_SPOTS$>
|
|
InspFOVs = CIRow<CLEAN_INSP_INSP_FOV$>
|
|
InspBLDefects = CIRow<CLEAN_INSP_INSP_BL_DEFECTS$>
|
|
InspSigs = CIRow<CLEAN_INSP_INSP_SIG$>
|
|
InspSigDTMs = CIRow<CLEAN_INSP_INSP_SIG_DTM$>
|
|
// Front side specs
|
|
SpecLPD = CIRow<CLEAN_INSP_SPEC_LPD$>
|
|
SpecScratches = CIRow<CLEAN_INSP_SPEC_SCRATCHES$>
|
|
SpecScratchLen = CIRow<CLEAN_INSP_SPEC_SCRATCH_LEN$>
|
|
SpecPits = CIRow<CLEAN_INSP_SPEC_PITS$>
|
|
SpecMounds = CIRow<CLEAN_INSP_SPEC_MOUNDS$>
|
|
SpecStackFaults = CIRow<CLEAN_INSP_SPEC_STACK_FAULTS$>
|
|
SpecSpikes = CIRow<CLEAN_INSP_SPEC_SPIKES$>
|
|
SpecSpots = CIRow<CLEAN_INSP_SPEC_SPOTS$>
|
|
SpecFOV = CIRow<CLEAN_INSP_SPEC_FOV$>
|
|
SpecBLDefects = CIRow<CLEAN_INSP_SPEC_BL_DEFECTS$>
|
|
// Backside data
|
|
InspBsideScratches = CIRow<CLEAN_INSP_INSP_BSIDE_SCRATCHES$>
|
|
InspBsideScratchLen = CIRow<CLEAN_INSP_INSP_BSIDE_SCRATCH_LEN$>
|
|
InspBsideNodules = CIRow<CLEAN_INSP_INSP_BSIDE_NODULES$>
|
|
InspBsideSpikes = CIRow<CLEAN_INSP_INSP_BSIDE_SPIKES$>
|
|
// Backside specs
|
|
SpecBsideScratches = CIRow<CLEAN_INSP_SPEC_BSIDE_SCRATCHES$>
|
|
SpecBsideScratchLen = CIRow<CLEAN_INSP_SPEC_BSIDE_SCRATCH_LEN$>
|
|
SpecBsideNodules = CIRow<CLEAN_INSP_SPEC_BSIDE_NODULES$>
|
|
SpecBsideSpikes = CIRow<CLEAN_INSP_SPEC_BSIDE_SPIKES$>
|
|
// 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<CLEAN_INSP_CLEAN_TOOL$>
|
|
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<CLEAN_INSP_SCAN_TOOL$>
|
|
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<CLEAN_INSP_INSP_TOOL$>
|
|
InspSigs = CIRow<CLEAN_INSP_INSP_SIG$>
|
|
InspSigDTMs = CIRow<CLEAN_INSP_INSP_SIG_DTM$>
|
|
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<CLEAN_INSP_INSP_SIG$> = InspSigs
|
|
CIRow<CLEAN_INSP_INSP_SIG_DTM$> = InspSigDTMs
|
|
Case ( (Stage EQ 'PREC') or (Stage EQ 'FWIC') or (Stage EQ 'LWIC') or (Stage EQ 'PSTC') )
|
|
CleanTools = CIRow<CLEAN_INSP_CLEAN_TOOL$>
|
|
CleanSigs = CIRow<CLEAN_INSP_CLEAN_SIG$>
|
|
CleanSigDTMs = CIRow<CLEAN_INSP_CLEAN_SIG_DTM$>
|
|
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<CLEAN_INSP_CLEAN_SIG$> = CleanSigs
|
|
CIRow<CLEAN_INSP_CLEAN_SIG_DTM$> = CleanSigDTMs
|
|
Case ( (Stage EQ 'PRES') or (Stage EQ 'FWIS') or (Stage EQ 'LWIS') or (Stage EQ 'PSTS') )
|
|
ScanTools = CIRow<CLEAN_INSP_SCAN_TOOL$>
|
|
SurfSigs = CIRow<CLEAN_INSP_SCAN_SIG$>
|
|
SurfSigDTMs = CIRow<CLEAN_INSP_SCAN_SIG_DTM$>
|
|
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<CLEAN_INSP_SCAN_SIG$> = SurfSigs
|
|
CIRow<CLEAN_INSP_SCAN_SIG_DTM$> = 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<WO_MAT_QA_STAGE$>
|
|
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<WO_MAT_QA_SLOT$>
|
|
|
|
// 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<WO_MAT_WMO_KEY$>
|
|
WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
|
|
MUWfrIDs = WOMatRec<WO_MAT_EPOS_REP_WAFER_ID$>
|
|
MUWfrResults = WMORec<WM_OUT_MU_WAFER_THK_RESULT$>
|
|
end else
|
|
MUWfrIDs = WOMatRec<WO_MAT_SLOT_REP_WAFER_ID$>
|
|
MUWfrResults = WOMatRec<WO_MAT_MU_WAFER_THK_RESULT$>
|
|
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<WO_MAT_QA_PROP$, vPos>
|
|
MetResult = WOMatQARec<WO_MAT_QA_RESULT$, vPos>
|
|
MetMin = WOMatQARec<WO_MAT_QA_MIN$, vPos>
|
|
MetMax = WOMatQARec<WO_MAT_QA_MAX$, vPos>
|
|
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<WO_MAT_QA_STD_RESULT$, vPos>
|
|
StdDevMax = WOMatQARec<WO_MAT_QA_STD_MAX$, vPos>
|
|
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<WO_MAT_QA_FAIL_REASON$, vPos>
|
|
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<WO_MAT_QA_STAGE$>
|
|
WOMatQASlots = WOMatQARec<WO_MAT_QA_SLOT$>
|
|
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<WO_MAT_QA_SIG$, vPos> EQ '' then
|
|
WOMatQARec<WO_MAT_QA_SIG$, vPos> = User
|
|
WOMatQARec<WO_MAT_QA_SIG_DTM$, vPos> = 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<CLEAN_INSP_ROTR_ACTION$>
|
|
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<CLEAN_INSP_SIGN_ROTR_SIGNATURE$>
|
|
If ROTRSig EQ '' then
|
|
// Only sign ROTR Acceptance if no signature present.
|
|
LWICIRec<CLEAN_INSP_SIGN_ROTR_SIGNATURE$> = User
|
|
LWICIRec<CLEAN_INSP_SIGN_ROTR_DTM$> = Datetime()
|
|
LWICIRec<CLEAN_INSP_SIGN_ROTR_REASON$> = ROTRReason
|
|
LWICIRec<CLEAN_INSP_ROTR_ACTION$> = '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<NCR_AUTH_SHIP_SIG$> = User
|
|
NCRRec<NCR_AUTH_REJ_SIG$> = User
|
|
NCRRec<NCR_AUTH_SHIP_SIG_DTM$> = SigDTM
|
|
NCRRec<NCR_STATUS$> = 'C'
|
|
Database_Services('WriteDataRow', 'NCR', NCRKey, NCRRec)
|
|
If Error_Services('NoError') then
|
|
// Sign WO_MAT NCR sig column
|
|
Locate NCRKey in WOMatRec<WO_MAT_NCR_KEYS$> using @VM setting Pos then
|
|
CurrSig = Trim(WOMatRec<WO_MAT_NCR_FINAL_SIG$, Pos>)
|
|
If CurrSig EQ '' then
|
|
WOMatRec<WO_MAT_NCR_FINAL_SIG$, Pos> = User
|
|
WOMatRec<WO_MAT_NCR_FINAL_SIG_DTM$, Pos> = 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<RDS_SUPPL_SIG$> = User
|
|
RDSRec<RDS_SUPPL_SIG_DATE$> = Date()
|
|
RDSRec<RDS_SUPPL_SIG_TIME$> = Time()
|
|
RDSRec<RDS_SUPPL_ACK$> = 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
|
|
|
|
|
|
Service UnsignFQAStage(RDSNo)
|
|
|
|
IsEPP = Rds_Services('IsEpiPro', RDSNo)
|
|
If IsEpp EQ False$ then
|
|
Database_Services('ActivateRecord', 'RDS', RDSNo)
|
|
If Error_Services('NoError') then
|
|
Valid = ''
|
|
CurRdsNo = RDSNo
|
|
WONo = {WO}
|
|
CassNo = {CASS_NO}
|
|
WOStep = {WO_STEP}
|
|
WOMatKey = WONo:'*':CassNo
|
|
WOMatRec = XLATE('WO_MAT',WOMatKey,'','X')
|
|
// Unsign WO_MAT
|
|
InvWH = WOMatRec<WO_MAT_INV_WH$>
|
|
InvLoc = WOMatRec<WO_MAT_INV_LOCATION$>
|
|
InvAction = WOMatRec<WO_MAT_INV_ACTION$>
|
|
InvDTM = WOMatRec<WO_MAT_INV_DTM$>
|
|
InvUser = WOMatRec<WO_MAT_INV_USER$>
|
|
// Get List of keys to delete
|
|
InvCount = Dcount(InvWH, @VM)
|
|
DeleteList = ''
|
|
For I = 1 to InvCount
|
|
ThisLoc = InvAction<1,I>
|
|
If ThisLoc EQ '1QA' or ThisLoc EQ 'POST' then
|
|
DeleteList<-1> = I
|
|
end
|
|
Next I
|
|
// Reverse array to work backwards through deletions
|
|
DeleteList = SRP_Array('Reverse', DeleteList, @FM)
|
|
If DeleteList NE '' then
|
|
For Each Item in DeleteList Using @FM
|
|
WOMatRec = Delete(WOMatRec, WO_MAT_INV_WH$, Item, 0)
|
|
WOMatRec = Delete(WOMatRec, WO_MAT_INV_LOCATION$, Item, 0)
|
|
WOMatRec = Delete(WOMatRec, WO_MAT_INV_ACTION$, Item, 0)
|
|
WOMatRec = Delete(WOMatRec, WO_MAT_INV_DTM$, Item, 0)
|
|
WOMatRec = Delete(WOMatRec, WO_MAT_INV_USER$, Item, 0)
|
|
Next Item
|
|
Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, False$)
|
|
end
|
|
|
|
// Unsign RDS
|
|
{SUP_VER_SIG} = ''
|
|
{SUP_VER_SIG_DATE} = ''
|
|
{SUP_VER_SIG_TIME} = ''
|
|
Database_Services('WriteDataRow', 'RDS', RDSNo, @Record, True$, False$, False$)
|
|
** Create LOT_EVENT **
|
|
Lot_Event_Services('CreateLotEvent', RDSNo, Datetime(), 'UNSIGN_FQA', '', '', @USER4, True$, 'RDS')
|
|
end else
|
|
Error_Services('Add', 'Error accessing RDS.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'This service is currently only available for non-EpiPro lots.')
|
|
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
|
|
|
|
|
|
|
|
|
|
|