open-insight/LSL2/STPROC/CLEAN_INSP.txt
2024-12-13 22:39:22 +01:00

1964 lines
85 KiB
Plaintext

COMPILE FUNCTION Clean_Insp(EntID,Event,Parm1,Parm2,Parm3,Parm4,Parm5)
#pragma precomp SRP_PreCompiler
/*
Commuter module for CLEAN_INSP (Clean & Inspection) window
08/05/2009 - John C. Henry, J.C. Henry & Co., Inc.
03/07/2017 - djs - Changed the SCAN_RESULTS.GOT_FOCUS event to a CHAR event instead to allow users to select
the scan results row of their choice (to view those individual wafer results) without being
prompted for a manual entry data override.
10/29/2019 - djs - Fixed "SigRow EQ 1" to 'SelectedRow EQ 1' logic check within SignClean, SignInsp,
and SignScan subroutines
04/23/2021 - djs - Updated SIGN_ROTR_ACCEPTANCE.CLICK event to not block acceptance signatures when a 100%
failure scan is required.
05/13/2024 - djs - Replaced Ole Tab control (OLE_TAB_ROTR) with a groupbox control (ROTR_GROUP) to mitigate
form behavior bugs in OI 10 post migration.
06/13/2024 djm Add new stage-specific supplement system.
*/
DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status, Center_Window, Post_Event, Comm_RDS
DECLARE SUBROUTINE ErrMsg, Send_Message, Set_Property, Send_Event, Btree.Extract, obj_AppWindow, Signature_Services
DECLARE SUBROUTINE obj_Notes, Security_Err_Msg, End_Window, Forward_Event, Start_Window, Create_Note
DECLARE SUBROUTINE obj_WO_Mat_Log, obj_WO_Mat, obj_Clean_Insp, Unlock, Lock, Database_Services, Yield
DECLARE SUBROUTINE Override_Log_Services, Dialog_Box, obj_WO_Wfr, Error_Services, Hold_Services
DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, Utility, Popup, Collect.Ixvals, Environment_Services
DECLARE FUNCTION Send_Message, Msg, Security_Check, obj_React_Run_CI, Select_Into, MemberOf, Database_Services
DECLARE FUNCTION Start_Window, Create_Dialog, Database_Services, Set_Property, Error_Services, SRP_DateTime
DECLARE FUNCTION obj_NCR, SRP_Array, Supplement_Services
$INSERT LOGICAL
$INSERT MSG_EQUATES
$INSERT APPCOLORS
$INSERT LSL_USERS_EQU
$INSERT SECURITY_RIGHTS_EQU
$INSERT REACT_EVENT_EQUATES
$INSERT POPUP_EQUATES
$INSERT RTI_STYLE_EQUATES
$INSERT CLEAN_INSP_EQUATES
$INSERT TOOL_CLASS_EQUATES
$INSERT TOOL_EQUATES
$INSERT WO_MAT_EQUATES
$INSERT WO_LOG_EQUATES
$INSERT SPC_QUEUE_EQUATES
$INSERT WM_OUT_EQUATES
$INSERT REACTOR_EQUATES
$INSERT NOTIFICATION_EQUATES
EQU PROTECTED$ TO 8
EQU CRLF$ TO \0D0A\
EQU TAB$ TO \09\
Equ ESC$ TO Char(27)
EQU COL$CLEAN_TOOL TO 1
EQU COL$CLEAN_BOAT_ID TO 2
EQU COL$CLEAN_SRD_NO TO 3
EQU COL$CLEAN_SIG TO 4
EQU COL$CLEAN_SIG_DTM TO 5
EQU COL$DUMMY_1_PIXEL_WIDE TO 1 ;* Used for both INSP_SPEC and INSP controls
EQU COL$INSP_SPEC_LPD TO 2
EQU COL$INSP_SPEC_SCRATCHES TO 3
EQU COL$INSP_SPEC_SCRATCH_LEN TO 4
EQU COL$INSP_SPEC_PITS TO 5
EQU COL$INSP_SPEC_MOUNDS TO 6
EQU COL$INSP_SPEC_STACK_FAULTS TO 7
EQU COL$INSP_SPEC_SPIKES TO 8
EQU COL$INSP_SPEC_SPOTS TO 9
EQU COL$INSP_SPEC_FOV TO 10
EQU COL$INSP_SPEC_BL_DEFECTS TO 11
EQU COL$INSP_TOOL TO 2 ;* Added INSP_TOOL column 10/29/2012 JCH
EQU COL$INSP_LPD TO 3
EQU COL$INSP_SCRATCHES TO 4
EQU COL$INSP_SCRATCH_LEN TO 5
EQU COL$INSP_PITS TO 6
EQU COL$INSP_MOUNDS TO 7
EQU COL$INSP_STACK_FAULTS TO 8
EQU COL$INSP_SPIKES TO 9
EQU COL$INSP_SPOTS TO 10
EQU COL$INSP_FOV TO 11
EQU COL$INSP_BL_DEFECTS TO 12
EQU COL$INSP_SIG TO 13
EQU COL$INSP_SIG_DTM TO 14
EQU COL$INSP_SPEC_BSIDE_SCRATCHES TO 1
EQU COL$INSP_SPEC_BSIDE_SCRATCH_LEN TO 2
EQU COL$INSP_SPEC_BSIDE_NODULES TO 3
EQU COL$INSP_SPEC_BSIDE_SPIKES TO 4
EQU COL$INSP_BSIDE_SCRATCHES TO 1
EQU COL$INSP_BSIDE_SCRATCH_LEN TO 2
EQU COL$INSP_BSIDE_NODULES TO 3
EQU COL$INSP_BSIDE_SPIKES TO 4
EQU COL$SCAN_SPEC_SURF_RECIPE$ TO 1
EQU COL$SCAN_SPEC_SURF_DEFECTS$ TO 2
EQU COL$SCAN_SPEC_SURF_HAZE$ TO 3
EQU COL$SCAN_SPEC_SCRATCHES$ TO 4
EQU COL$SCAN_RECIPE TO 1
EQU COL$SCAN_TOOL TO 2
EQU COL$SCAN_SUM_OF_DEF_MIN TO 3
EQU COL$SCAN_SUM_OF_DEF_MAX TO 4
EQU COL$SCAN_SUM_OF_DEF_AVG TO 5
EQU COL$SCAN_HAZE_AVG_AVG TO 6
EQU COL$SCAN_DCNMM2 TO 7
EQU COL$SCAN_REASON TO 8
EQU COL$SCAN_SIG TO 9
EQU COL$SCAN_SIG_DTM TO 10
EQU COL$SCAN_TEST_RUN_DTM TO 11
EQU COL$SLOT TO 1
EQU COL$WAFER_ID TO 2
EQU COL$SLOT_NCR TO 3
EQU COL$MET_NO$ TO 4
EQU COL$MOVED_TO_SLOT TO 5
EQU COL$MU_WAFER_ID TO 6
EQU COL$MOVED_FROM_SLOT TO 7
EQU COL$REPLACED_BY TO 8
EQU COL$MU_ADD_DATE TO 9
EQU COL$MU_REM_DATE TO 10
EQU COL$EPP_SLOT TO 1
EQU COL$EPP_RDS_NO TO 2
EQU COL$EPP_REACT_NO TO 3
EQU COL$EPP_RDS_STATUS TO 4
EQU COL$EPP_POCKET TO 5
EQU COL$EPP_ZONE TO 6
EQU COL$EPP_IN_CASS TO 7
EQU COL$EPP_IN_SLOT TO 8
EQU COL$EPP_SLOT_NCR TO 9
EQU COL$EPP_MU_WO_NO TO 10
EQU COL$EPP_MU_WO_STEP TO 11
EQU COL$EPP_MU_CASS_NO TO 12
EQU COL$EPP_MU_SLOT_NO TO 13
EQU COL$EPP_UMW_CASS_ID TO 14
EQU COL$EPP_UMW_SLOT_NO TO 15
EQU COL$EPP_MU_BY TO 16
EQU COL$EPP_MU_ADD_DATE TO 17
EQU COL$EPP_MU_REM_DATE TO 18
EQU HIDDEN$ TO 32
EQU SKIPPED$ TO 4100
ErrTitle = 'Error in CleanInsp'
ErrorMsg = ''
Result = ''
BEGIN CASE
CASE EntID = @WINDOW
BEGIN CASE
CASE Event = 'CLEAR' ; GOSUB Clear
CASE Event = 'CREATE' ; GOSUB Create
CASE Event = 'CLOSE' ; GOSUB Close
CASE Event = 'WRITE' ; GOSUB Write
CASE Event = 'READ' ; GOSUB Read
CASE Event = 'VSCROLL' ; GOSUB VScroll
CASE Event[1,3] = 'QBF' ; GOSUB Refresh
END CASE
CASE EntID = @WINDOW:'.SIGN_CLEAN' AND Event = 'CLICK' ; GOSUB SignClean
CASE EntID = @WINDOW:'.SIGN_INSP' AND Event = 'CLICK' ; GOSUB SignInsp
CASE EntID = @WINDOW:'.SIGN_SCAN' AND Event = 'CLICK' ; GOSUB SignScan
CASE EntID = @WINDOW:'.SIGN_ROTR_ACCEPTANCE' AND Event = 'CLICK' ; GOSUB SIGN_ROTR_ACCEPTANCE.CLICK
CASE EntID = @WINDOW:'.BTN_WAFER_DETAILS' AND Event = 'CLICK' ; GOSUB BTN_WAFER_DETAILS.CLICK
CASE EntID = @WINDOW:'.SCAN_RESULTS' AND Event = 'CHAR' ; GOSUB SCAN_RESULTS.CHAR
CASE EntID = @WINDOW:'.SCAN_RESULTS' AND Event = 'POSCHANGED' ; GOSUB SCAN_RESULTS.POSCHANGED
CASE EntID = @WINDOW:'.SPEC_BRIGHTLIGHT' AND Event = 'CLICK' ; GOSUB Refresh
CASE EntID = @WINDOW:'.SPEC_MICROSCOPE' AND Event = 'CLICK' ; GOSUB Refresh
CASE EntID = @WINDOW:'.CHK_EDGE' AND Event = 'CLICK' ; GOSUB Refresh
CASE EntID = @WINDOW:'.REFRESH_SPEC' AND Event = 'CLICK' ; GOSUB RefreshSpec
CASE EntID = @WINDOW:'.CI_TAB' AND Event = 'CLICK' ; GOSUB Page
CASE EntID = @WINDOW:'.INSP_RESULTS' AND Event = 'POSCHANGED' ; GOSUB InspPC
CASE EntID = @WINDOW:'.INSP_RESULTS_BSIDE' AND Event = 'POSCHANGED' ; GOSUB BSideInspPC
CASE EntID = @WINDOW:'.SEND_SPC' AND Event = 'CLICK' ; GOSUB SendSPC
CASE 1
ErrorMsg = 'Unknown Parameters ':EntID:' - ':Event:' passed to commuter'
ErrMsg(ErrorMsg)
END CASE
IF ErrorMsg NE '' THEN
ErrMsg(ErrTitle:@SVM:ErrorMsg)
END
RETURN Result
* * * * * * *
Create:
* * * * * * *
obj_Appwindow('Create',@WINDOW)
IF MemberOf(@USER4, 'OI_SUPERUSER') THEN
Set_Property(@WINDOW:'.SEND_SPC','VISIBLE',1)
Set_Property(@WINDOW:'.SPC_DTM','VISIBLE',1)
END ELSE
Set_Property(@WINDOW:'.SEND_SPC','VISIBLE',0)
Set_Property(@WINDOW:'.SPC_DTM','VISIBLE',0)
END
CIKey = Get_Property(@Window : '.CI_NO', 'TEXT')
* Setup Cleans Section
CleanStyles = Send_Message(@WINDOW:'.CLEAN_RESULTS','COLSTYLE',0,'')
CleanStyles<COL$CLEAN_TOOL> = BitOr(CleanStyles<COL$CLEAN_TOOL>,DTCS_DROPDOWN$)
CleanStyles<COL$CLEAN_BOAT_ID> = BitOr(CleanStyles<COL$CLEAN_BOAT_ID>,DTCS_DROPDOWN$)
CleanStyles<COL$CLEAN_SRD_NO> = BitOr(CleanStyles<COL$CLEAN_SRD_NO>,DTCS_DROPDOWN$)
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLSTYLE',0,CleanStyles) ;* Set Styles
* Setup Inspection Section
InspStyles = Send_Message(@WINDOW:'.INSP_RESULTS','COLSTYLE',0,'')
InspStyles<COL$INSP_TOOL> = BitOr(InspStyles<COL$INSP_TOOL>,DTCS_DROPDOWN$)
Send_Message(@WINDOW:'.INSP_RESULTS','COLSTYLE',0,InspStyles)
InspTools = 'SCOPE':@VM:'FF EDGE INSP':@VM:'SCOPE/FF EDGE INSP'
Send_Message(@WINDOW:'.INSP_RESULTS','COLFORMAT',COL$INSP_TOOL,InspTools)
* Setup Scan Section
ScanStyles = Send_Message(@WINDOW:'.SCAN_RESULTS','COLSTYLE',0,'')
ScanStyles<COL$SCAN_RECIPE> = BitOr(ScanStyles<COL$SCAN_RECIPE>,DTCS_DROPDOWN$)
ScanStyles<COL$SCAN_TOOL> = BitOr(ScanStyles<COL$SCAN_TOOL>,DTCS_DROPDOWN$)
Send_Message(@WINDOW:'.SCAN_RESULTS','COLSTYLE',0,ScanStyles)
ScanTools = XLATE('TOOL_CLASS','TENCOR',TOOL_CLASS_TOOL$,'X') ;* Tencor class tools
Send_Message(@WINDOW:'.SCAN_RESULTS','COLFORMAT',COL$SCAN_TOOL,ScanTools)
IF MemberOf(@USER4, 'OI_SUPERUSER') THEN
Set_Property(@WINDOW:'.REFRESH_SPEC','VISIBLE',1)
END ELSE
Set_Property(@WINDOW:'.REFRESH_SPEC','VISIBLE',0)
END
CIKey = Get_Property(@Window : '.CI_NO', 'TEXT')
ReactorNo = Xlate('CLEAN_INSP', CIKey, 'REACT_NO', 'X')
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
If Stage EQ 'LWI' then
CanEdit = Memberof(@USER4, 'ENGINEERING') or Memberof(@USER4, 'LEAD') or Memberof(@USER4, 'SUPERVISOR') |
or Memberof(@USER4, 'FINAL_QA') or Memberof(@USER4, 'ROTR_OVERRIDE')
// Check if manual entry lock is temporarily disabled for all users due to ROTR queue overflow.
ManualEntryLock = Xlate('APP_INFO', 'ROTR_DATA_ENTRY_LOCK', 1, 'X')
If (ManualEntryLock EQ False$) then CanEdit = True$
Set_Property(@Window, '@CAN_EDIT', CanEdit)
If Not(CanEdit) then
// Disable manual entry of data.
ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, '')
For column = 1 to 7
ScanStyles<column> = BitOr( ScanStyles<column>, PROTECTED$ )
Next column
// Disable dropdown menus for recipe and tool columns.
ScanStyles<COL$SCAN_RECIPE> = BitAnd(ScanStyles<COL$SCAN_RECIPE>, BitNot(DTCS_DROPDOWN$) )
ScanStyles<COL$SCAN_TOOL> = BitAnd(ScanStyles<COL$SCAN_TOOL>, BitNot(DTCS_DROPDOWN$) )
ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, ScanStyles)
end
end
RETURN
* * * * * * *
Page:
* * * * * * *
Page = Get_Property(@WINDOW:'.CI_TAB', 'VALUE')
Set_Property(@WINDOW,'VPOSITION', Page)
RETURN
* * * * * * *
VScroll:
* * * * * * *
Page = Parm1
Set_Property(@WINDOW:'.CI_TAB','VALUE', Page)
RETURN
* * * * * * *
Clear:
* * * * * * *
Send_Event(@WINDOW,'PAGE',1)
* * * * * * *
Refresh:
* * * * * * *
CIKey = Get_Property(@WINDOW:'.CI_NO', 'TEXT')
// Hide or show the Cass No label and edit line based on the whether the reactor is EpiPro or not. - 04/10/2018 - dmb
WONo = Get_Property(@Window : '.WO_NO', 'TEXT')
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo)
ReactType = WOLogRow<WO_LOG_REACT_TYPE$>
If ReactType NE 'EPP' then
Visible = True$
end else
Visible = False$
end
Set_Property(@Window : '.CASS_NO_LABEL', 'VISIBLE', Visible)
Set_Property(@Window : '.CASS_NO', 'VISIBLE', Visible)
Stage = Get_Property(@WINDOW:'.STAGE','TEXT')
* * * * *
Ctrls = @WINDOW:'.STAGE':@RM ; Props = 'TEXT':@RM
Ctrls := @WINDOW:'.SPEC_FWI_LWI':@RM ; Props := 'TEXT':@RM
Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL_REP':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SPEC_BRIGHTLIGHT':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_MICROSCOPE':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.CHK_EDGE':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL' ; Props := 'DEFPROP'
Vals = Get_Property(Ctrls,Props)
Stage = Vals[1,@RM]
SpecFwiLwi = Vals[COL2()+1,@RM]
SpecCleanToolRep = Vals[COL2()+1,@RM]
SpecBrightlight = Vals[COL2()+1,@RM]
SpecMicroscope = Vals[COL2()+1,@RM]
SpecEdge = Vals[COL2()+1,@RM]
SpecCleanTool = Vals[COL2()+1,@RM]
SpecCleanTools = Get_Property(@WINDOW:'.SPEC_CLEAN_TOOL$','ARRAY')
IF SpecCleanTools = '' THEN
AkrionCleanTools = XLATE('TOOL_CLASS','AKRION',TOOL_CLASS_TOOL$,'X')
WetBenchTools = XLATE('TOOL_CLASS','WET BENCH',TOOL_CLASS_TOOL$,'X')
BEGIN CASE
CASE AkrionCleanTools NE '' AND WetBenchTools NE '' ; SpecCleanTools = AkrionCleanTools:@VM:WetBenchTools
CASE AkrionCleanTools NE '' AND WetBenchTools = '' ; SpecCleanTools = AkrionCleanTools
CASE AkrionCleanTools = '' AND WetBenchTools NE '' ; SpecCleanTools = WetBenchTools
CASE 1 ; NULL
END CASE
END
LOOP
UNTIL SpecCleanTools[-1,1] NE @VM OR SpecCleanTools = ''
SpecCleanTools[-1,1] = ''
REPEAT
ScanRecipes = Get_Property(@WINDOW:'.SPEC_SURFSCAN','ARRAY')<COL$SCAN_SPEC_SURF_RECIPE$> ;* 1/22/2013 JCH ***********
Send_Message(@WINDOW:'.SCAN_RESULTS','COLFORMAT',COL$SCAN_RECIPE,ScanRecipes)
BEGIN CASE
CASE Stage = 'PRE'
LabelText = 'Pre Epi Cleaning && Inspection'
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_TOOL,SpecCleanTools)
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_BOAT_ID,XLATE('LISTBOX_CONFIG','PRECLEANCASSID',1,'X'))
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_SRD_NO,XLATE('LISTBOX_CONFIG','PRECLEANSRD',1,'X'))
CASE Stage = 'POST'
LabelText = 'Post Epi Cleaning && Inspection'
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_TOOL,SpecCleanTools)
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_BOAT_ID,XLATE('LISTBOX_CONFIG','POSTCLEANCASSID',1,'X'))
Send_Message(@WINDOW:'.CLEAN_RESULTS','COLFORMAT',COL$CLEAN_SRD_NO,XLATE('LISTBOX_CONFIG','POSTCLEANSRD',1,'X'))
CASE Stage = 'FWI' ; LabelText = 'First Wafer Inspection'
CASE Stage = 'LWI' ; LabelText = 'Last Wafer Inspection'
CASE Stage = 'WFR' AND SpecFwiLwi = 'FWI' ; LabelText = 'First Wafer Inspection'
CASE Stage = 'WFR' AND SpecFwiLwi = 'LWI' ; LabelText = 'Last Wafer Inspection'
CASE Stage[1,3] = 'WFR' ; LabelText = 'Wafer ':Stage[4,99]:' Extra Inspection'
CASE 1 ; LabelText = 'Cleaning && Inspection'
END CASE
Set_Property(@WINDOW:'.WINDOW_LABEL_FIX','TEXT',LabelText)
Ctrls = @WINDOW:'.SPEC_CLEAN_SUBOXIDE':@RM ; Props = 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_CLEAN_TOOL':@RM ; Props := 'TEXT':@RM
Ctrls := @WINDOW:'.SPEC_CLEAN_AKRION_RECIPE':@RM ; Props := 'TEXT':@RM
Ctrls := @WINDOW:'.SPEC_BRIGHTLIGHT':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_MICROSCOPE':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.CHK_EDGE':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_SURFSCAN' ; Props := 'ARRAY'
Vals = Get_Property(Ctrls,Props)
SCSubOxide = Vals[1,@RM]
SCTool = Vals[COL2()+1,@RM]
SCAkrionRecipe = Vals[COL2()+1,@RM]
SBrightLight = Vals[COL2()+1,@RM]
SMicroscope = Vals[COL2()+1,@RM]
SEdge = Vals[COL2()+1,@RM]
SSurfScanArray = Vals[COL2()+1,@RM]
ScanRecipes = SSurfScanArray<COL$SCAN_SPEC_SURF_RECIPE$>
CONVERT @VM TO '' IN ScanRecipes
SSurfScanRecipe = ScanRecipes
Ctrls = @WINDOW:'.SPEC_CLEAN_REQ':@RM ; Props = 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_INSP_REQ':@RM ; Props := 'CHECK':@RM
Ctrls := @WINDOW:'.SPEC_SURFSCAN_REQ' ; Props := 'CHECK'
Vals = Get_Property(Ctrls,Props)
CleanSigReq = Vals[1,@RM]
InspSigReq = Vals[COL2()+1,@RM]
SurfScanSigReq = Vals[COL2()+1,@RM]
IF SCTool NE '' OR CleanSigReq = 1 then
CleanSigReq = 1
end else
CleanSigReq = 0
end
InspReq = Xlate('CLEAN_INSP', CIKey, 'SPEC_INSP_REQ', 'X')
If InspReq EQ '' then InspReq = Xlate('CLEAN_INSP', CIKey, 'INSP_REQ', 'X')
// Old records may have more than one RDS/CLEAN_INSP key.
InspInterval = Xlate('CLEAN_INSP', CIKey, 'INSP_INTERVAL', 'X')<0, 1>
If InspInterval NE '' then
// Use the stored interval
RDSNo = Xlate('CLEAN_INSP', CIKey, 'RDS_NO', 'X')<0, 1>
PSNo = Xlate('CLEAN_INSP', CIKey, 'PS_NO', 'X')<0, 1>
WONo = Xlate('CLEAN_INSP', CIKey, 'WO_NO', 'X')<0, 1>
WOQty = Xlate('WO_LOG', WONo, 'QTY', 'X')<0, 1>
RunNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X')<0, 1>
StageKey = PSNo:'*LWI'
LastRun = ( (RunNo * 25) EQ WOQty )
InspReq = ( (Mod((RunNo - 1), InspInterval) EQ 0) or LastRun )
end else
// Use the current PRS_STAGE interval
InspReq = Xlate('CLEAN_INSP', CIKey, 'INSP_REQ', 'X')
end
If InspReq EQ False$ then
Set_Property(@WINDOW:'.INSP_RESULT_GROUP', 'TEXT', 'Visual Inspection Not Required')
end
IF SBrightLight = 1 OR SMicroscope = 1 OR SEdge OR InspSigReq = 1 THEN
InspSigReq = 1
end ELSE
InspSigReq = 0
end
IF SSurfScanRecipe NE '' OR SurfScanSigReq = 1 THEN
SurfScanSigReq = 1
end ELSE
SurfScanSigReq = 0
end
DefBack = Get_Property(@WINDOW,'BACKCOLOR')
ReqBackColor = CI_GROUP_BLUE$
* ROTR 2/1/2012
RotrAction = Get_Property(@WINDOW:'.ROTR_ACTION','TEXT')
BEGIN CASE
CASE RotrAction = 'Passed'
RBackColor = GREEN$ ;*LS1_GREEN$
BypassEnabled = False$
CASE RotrAction = 'Failed'
RBackColor = RED$
BypassEnabled = MemberOf(@USER4, 'ENGINEERING') OR MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') OR MemberOf(@USER4, 'OI_ADMIN') OR MemberOf(@USER4, 'ROTR_OVERRIDE')
CASE RotrAction = 'Waived'
RBackColor = YELLOW$ ;*CMB_YELLOW$
BypassEnabled = False$
CASE RotrAction = 'Accepted'
RBackColor = ORANGE$
BypassEnabled = False$
CASE 1
IF SurfScanSigReq THEN
RBackColor = ReqBackColor
END ELSE
RBackColor = DefBack
END
BypassEnabled = False$
END CASE
Ctrls = @WINDOW:'.ROTR_STATUS_LABEL':@FM ; Props = 'BACKCOLOR':@FM ; Vals = RBackColor:@FM
Ctrls := @WINDOW:'.ROTR_REASON_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM
Ctrls := @WINDOW:'.SIGN_ROTR_SIGNATURE_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM
Ctrls := @WINDOW:'.SIGN_ROTR_REASON_LABEL':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM
Ctrls := @WINDOW:'.ROTR_GROUP':@FM ; Props := 'BACKCOLOR':@FM ; Vals := RBackColor:@FM
Ctrls := @WINDOW:'.ROTR_ACTION':@FM ; Props := 'ENABLED':@FM ; Vals := 0:@FM
Ctrls := @WINDOW:'.EDL_ROTR_REASON':@FM ; Props := 'ENABLED':@FM ; Vals := 0:@FM
Ctrls := @WINDOW:'.SIGN_ROTR_ACCEPTANCE':@FM ; Props := 'ENABLED':@FM ; Vals := BypassEnabled:@FM
Ctrls := @WINDOW ; Props := 'REDRAW' ; Vals := 1
Convert @FM to @RM in Ctrls
Convert @FM to @RM in Props
Convert @FM to @RM in Vals
Set_Property(Ctrls,Props,Vals)
Set_Property(@Window:'.OLE_PIC_ROTR', 'OLE.BackgroundColor', RBackColor)
IF Get_Property(@WINDOW:'.SPC_DTM','DEFPROP') = '' THEN
Set_Property(@WINDOW:'.SEND_SPC','TEXT','Send to SPC')
END ELSE
Set_Property(@WINDOW:'.SEND_SPC','TEXT','Resend to SPC')
END
* Check for out of spec on the Inspection
InspSpecs = Get_Property(@WINDOW:'.SPEC_INSP','LIST')
InspResults = Get_Property(@WINDOW:'.INSP_RESULTS','LIST')
BSInspSpecs = Get_Property(@WINDOW:'.SPEC_INSP_BSIDE','LIST')
BSInspResults = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','LIST')
InspComplete = 1
InspOutOfSpec = 0
ResultLineNo = 1
OutOfSpecLine = 0
LOOP
InspResult = InspResults[1,@FM]
InspResults = DELETE(InspResults,1,0,0)
BSInspResult = BSInspResults[1,@FM]
BSInspReults = DELETE(BSInspResults,1,0,0)
UNTIL InspOutOfSpec OR InspResult = '' OR InspResult[1,9] = @VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM:@VM
* Check Frontside columns
FOR Col = COL$INSP_SPEC_LPD TO COL$INSP_SPEC_BL_DEFECTS
ColSpec = InspSpecs<1,Col>
colResult = InspResult<1,Col + 1> ;* Results has the tool column in front of the actual data
IF ColSpec NE '' AND colResult = '' THEN InspComplete = 0
IF colResult > 0 AND ColSpec NE '' THEN
BEGIN CASE
CASE Col = COL$INSP_SPEC_SCRATCH_LEN
IF ColResult GT ColSpec THEN InspOutOfSpec = 1
CASE Col = COL$INSP_SPEC_FOV
IF ColResult GT ColSpec THEN InspOutOfSpec = 1
CASE 1
IF ColResult GE ColSpec THEN InspOutOfSpec = 1
END CASE
END
NEXT Col
* Check Backside columns
FOR Col = COL$INSP_SPEC_BSIDE_SCRATCHES TO COL$INSP_SPEC_BSIDE_SPIKES
ColSpec = BSInspSpecs<1,Col>
colResult = BSInspResult<1,Col>
IF ColSpec NE '' AND colResult = '' THEN InspComplete = 0
IF colResult > 0 AND ColSpec NE '' THEN
BEGIN CASE
CASE Col = COL$INSP_SPEC_BSIDE_SCRATCH_LEN
IF ColResult GT ColSpec THEN InspOutOfSpec = 1
CASE 1
IF ColResult GE ColSpec THEN InspOutOfSpec = 1
END CASE
END
NEXT Col
IF NOT(InspOutOfSpec) THEN
ResultLineNo += 1
END
REPEAT
IF InspOutOfSpec THEN
Set_Property(@WINDOW:'.INSP_RESULTS','BACKCOLOR',RED$)
Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','BACKCOLOR',RED$)
Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',0)
END ELSE
Set_Property(@WINDOW:'.INSP_RESULTS','BACKCOLOR',WHITE$)
Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','BACKCOLOR',WHITE$)
Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',1)
END
IF NOT(InspComplete) THEN
Set_Property(@WINDOW:'.SIGN_INSP','ENABLED',0)
END
* Check for out of spec on the Surface Scan results *******************************
SSurfRecipes = SSurfScanArray<COL$SCAN_SPEC_SURF_RECIPE$>
SSurfDefects = SSurfScanArray<COL$SCAN_SPEC_SURF_DEFECTS$>
SSurfHazes = SSurfScanArray<COL$SCAN_SPEC_SURF_HAZE$>
LOOP
SSurfRecipe = SSurfRecipes[-1,'B':@VM]
UNTIL SSurfRecipe NE '' OR SSurfRecipes = ''
SSurfRecipes[COL1(),1] = ''
REPEAT
SurfResults = Get_Property(@WINDOW:'.SCAN_RESULTS','LIST')
* Remove empty lines from control
LOOP
SurfResLine = SurfResults[-1,'B':@FM]
CONVERT @VM TO '' IN SurfResLine
UNTIL SurfResLine NE '' OR SurfResults = ''
SurfResults[COL1(),99] = ''
REPEAT
CurrRec = Get_Property(@Window, 'RECORD')
ScanResults = CurrRec<CLEAN_INSP_SCAN_RESULT$>
CtrlName = @WINDOW:'.SCAN_RESULTS'
For each ScanResult in ScanResults using @VM setting Line
Begin Case
Case ScanResult EQ 'P'
Color = GREEN$:@FM:BLACK$:@FM:BGREEN$:@FM:BLACK$
Case ScanResult EQ 'F'
Color = RED$:@FM:BLACK$:@FM:BRED$:@FM:BLACK$
Case Otherwise$
Null
End Case
// Color the row
stat = Send_Message(CtrlName, 'COLOR_BY_POS', 0, Line, Color)
Next ScanResult
Set_Property(@Window:'.SPEC_MICROSCOPE', 'ENABLED', False$)
Set_Property(@Window:'.CHK_EDGE', 'ENABLED', False$)
* QBF buttons
Ctrls = @WINDOW:'.QBF_FIRST_FIX':@RM ; Props = 'ENABLED':@RM
Ctrls := @WINDOW:'.QBF_PREV_FIX':@RM ; Props := 'ENABLED':@RM
Ctrls := @WINDOW:'.QBF_ABS_FIX':@RM ; Props := 'ENABLED':@RM
Ctrls := @WINDOW:'.QBF_NEXT_FIX':@RM ; Props := 'ENABLED':@RM
Ctrls := @WINDOW:'.QBF_LAST_FIX':@RM ; Props := 'ENABLED':@RM
Ctrls := @WINDOW:'.QBF_STOP_FIX' ; Props := 'ENABLED'
IF Get_Property(@WINDOW,'QBFLIST') = '' THEN
Vals = 0:@RM:0:@RM:0:@RM:0:@RM:0:@RM:0
END ELSE
Vals = 1:@RM:1:@RM:1:@RM:1:@RM:1:@RM:1
END
Set_Property(Ctrls,Props,Vals)
* Turn edit table symbolic column backgrounds to green **************************************************
ETSymbolics = Get_Property(@WINDOW,'@ET_SYMBOLICS') ;* Loaded during 'Create' in obj_Appwindow
ETCtrls = ETSymbolics<1>
ETCols = ETSymbolics<2>
FOR I = 1 TO COUNT(ETCtrls,@VM) + (ETCtrls NE '')
ETCtrl = ETCtrls<1,I>
ETList = Get_Property(ETCtrl,'LIST')
FOR Line = 1 TO COUNT(ETList,@FM) + (ETList NE '')
IF ETList<Line,1> NE '' THEN
FOR N = 1 TO COUNT(ETCols<1,I>,@SVM) + (ETCols<1,I> NE '')
stat = Send_Message(ETCtrl,'COLOR_BY_POS',ETCols<1,I,N>,Line,GREEN$)
NEXT N
END
NEXT I
NEXT I
ScanResultsArray = Get_Property(@Window : '.SCAN_RESULTS', 'ARRAY')
TestDTMs = ScanResultsArray<COL$SCAN_TEST_RUN_DTM>
Done = False$
For each DTM in TestDTMs using @VM setting vPos
If DTM NE '' then Done = True$
Until Done EQ True$
Next DTM
Convert @VM to '' in TestDTMs
TestDTMs = Trim(TestDTMs)
If TestDTMs EQ '' then
Set_Property(@Window : '.BTN_WAFER_DETAILS', 'ENABLED', False$)
end else
Set_Property(@Window : '.SCAN_RESULTS', 'SELPOS', 1:@FM:vPos)
end
RETURN
* * * * * * *
Read:
* * * * * * *
GOSUB Refresh
RETURN
* * * * * * *
Write:
* * * * * * *
DontClose = Get_Property(@WINDOW,'@DONT_CLOSE')
IF NOT(DontClose) THEN
Forward_Event()
Post_Event(@WINDOW,'CLOSE')
END ELSE
Set_Property(@WINDOW,'@DONT_CLOSE',0)
Result = 1
END
RETURN
* * * * * * *
Close:
* * * * * * *
obj_Appwindow('DetailReturn',@WINDOW)
RETURN
* * * * * * *
Delete:
* * * * * * *
RETURN
* * * * * * *
SignClean:
* * * * * * *
CtrlID = @WINDOW:'.CLEAN_RESULTS'
CtrlList = Get_Property(CtrlID,'LIST')
SlotSelection = Get_Property(CtrlID,'SELPOS')
SelectedRow = SlotSelection<2>
SigRow = CtrlList<SelectedRow>
IF SigRow<1,COL$CLEAN_TOOL> = '' THEN
ErrMsg('Process Error':@SVM:'Clean Tool column is required.')
Set_Property(CtrlID,'SELPOS',COL$CLEAN_TOOL:@FM:SelectedRow)
RETURN
END
CONVERT @VM TO '' IN SigRow
****
Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM
Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP'
Vals = Get_Property(Ctrls,Props)
WONo = Vals[1,@RM]
WOStep = Vals[COL2()+1,@RM]
CassNo = Vals[COL2()+1,@RM]
Stage = Vals[COL2()+1,@RM]
RDSNo = Vals[COL2()+1,@RM]
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo)
ReactType = WOLogRow<WO_LOG_REACT_TYPE$>
IF Stage = 'POST' THEN
IF RDSNo = '' THEN
* Epi Pro wafers
SigAction = WOStep:'MO_PSTC'
SigStage = 'MO_PSTC'
END ELSE
SigAction = WOStep:'PSTC'
SigStage = 'PSTC'
END
END ELSE
SigAction = WOStep:Stage:'C'
SigStage = Stage:'C'
END
IF SigRow NE '' AND CtrlList<SelectedRow,COL$CLEAN_SIG> = '' THEN
If SelectedRow EQ 1 then
WOMatKey = WONo:'*':CassNo
Signature_Services('CheckSigOrder', WOMatKey, SigStage, RDSNo)
If Error_Services('HasError') then
ErrMsg(Error_Services('GetMessage'))
return
end
end
// Add check for supplement signatures
ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo)
If Count(ValidStages, SigStage) NE 0 then
UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage)
If UnacknowledgedSupp NE FALSE$ then
Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$)
If Response EQ False$ then return
end
End
IF MemberOf(@USER4, 'OI_SUPERUSER') THEN
Valid = 1
END ELSE
Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) )
END
IF Valid = 1 THEN
CurrDate = OCONV(Date(),'D4/')
CurrTime = OCONV(Time(),'MTHS')
CurrDTM = CurrDate:' ':CurrTime
Signer = @USER4
ToolID = CtrlList<SelectedRow,COL$INSP_TOOL>
ToolRec = XLATE('TOOL',ToolID,'','X')
ToolWHCd = ToolRec<TOOL_TOOL_WH$>
ToolLoc = ToolRec<TOOL_TOOL_LOC$>
Tag = ''
owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTC signature
IF Get_Status(errCode) THEN
CALL ErrMsg(ErrCode)
RETURN
END
ToolID = CtrlList<SelectedRow,COL$CLEAN_TOOL>
ToolRec = XLATE('TOOL',ToolID,'','X')
ToolWHCd = ToolRec<TOOL_TOOL_WH$>
ToolLoc = ToolRec<TOOL_TOOL_LOC$>
LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM
LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM
Action = SigAction ; WOMLParms := Action:@RM
WhCd = ToolWHCd ; WOMLParms := WhCd:@RM
LocCd = ToolLoc ; WOMLParms := LocCd:@RM
WONos = WONo ; WOMLParms := WONos:@RM
CassNos = CassNo ; WOMLParms := CassNos:@RM
UserID = Signer ; WOMLParms := UserID:@RM
Tags = Tag ; WOMLParms := Tags:@RM
ToolID = ToolID ; WOMLParms := ToolID
obj_WO_Mat_Log('Create',WOMLParms) ;* Stage PSTC log entry
IF Get_Status(errCode) THEN
ErrMsg(errCode)
RETURN
END
Set_Property(CtrlID,'CELLPOS',Signer,COL$CLEAN_SIG:@FM:SelectedRow)
Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$CLEAN_SIG_DTM:@FM:SelectedRow)
CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP')
Set_Property(@WINDOW,'@DONT_CLOSE',1)
Send_Event(@WINDOW,'WRITE')
obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO')
END
END ELSE
IF SigRow = '' THEN
ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.')
RETURN
END
IF CtrlList<SelectedRow,COL$CLEAN_SIG> NE '' THEN
ErrMsg('Process Error':@SVM:'Row is already signed.')
RETURN
END
END
RETURN
* * * * * * *
SignInsp:
* * * * * * *
CtrlID = @WINDOW:'.INSP_RESULTS'
CtrlList = Get_Property(CtrlID,'LIST')
SlotSelection = Get_Property(CtrlID,'SELPOS')
SelectedRows = SlotSelection<2>
SlotSelection = Get_Property(CtrlID,'SELPOS')
SelectedRow = SlotSelection<2>
SigRow = CtrlList<SelectedRow>
BackSigRow = Get_Property(@Window:'.INSP_RESULTS_BSIDE', 'LIST')<SelectedRow>
FrontSpecRow = Get_Property(@Window:'.SPEC_INSP', 'LIST')
BackSpecRow = Get_Property(@Window:'.SPEC_INSP_BSIDE', 'LIST')
InspTools = 'SCOPE':@VM:'FF EDGE INSP':@VM:'SCOPE/FF EDGE INSP'
SelTool = SigRow<1,COL$INSP_TOOL>
IF SelTool = '' THEN
ErrMsg('Process Error':@SVM:'Insp Tool column is required.')
Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow)
RETURN
END
// Ensure tool selected matches that of the prescribed inspection type
EdgeInspReq = Get_Property(@Window:'.CHK_EDGE', 'CHECK')
ScopeInspReq = Get_Property(@Window:'.SPEC_MICROSCOPE', 'CHECK')
Begin Case
Case EdgeInspReq and ScopeInspReq
If SelTool NE 'SCOPE/FF EDGE INSP' then
ErrMsg('Process Error':@SVM:'Edge inspection and scope inspection are required. Selected tool must be "SCOPE/FF EDGE INSP"')
Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow)
return
end
Case ScopeInspReq
If SelTool NE 'SCOPE' then
ErrMsg('Process Error':@SVM:'Microscope inspection is required. Selected tool must be "SCOPE"')
Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow)
return
end
Case EdgeInspReq
If SelTool NE 'FF EDGE INSP' then
ErrMsg('Process Error':@SVM:'Edge inspection is required. Selected tool must be "FF EDGE INSP"')
Set_Property(CtrlID,'SELPOS',COL$INSP_TOOL:@FM:SelectedRow)
return
end
End Case
// Verify frontside inspection data
For Col = COL$INSP_SPEC_LPD to COL$INSP_SPEC_BL_DEFECTS
ColSpec = FrontSpecRow<1, Col>
ColVal = SigRow<1, Col + 1> ;* Results has the tool column in front of the actual data
If ( (ColSpec NE '') and (ColVal EQ '') ) then
ErrMsg('Process Error':@SVM:'Data is missing in column number ':Col-1:'.')
Set_Property(CtrlID,'SELPOS',Col:@FM:SelectedRow)
RETURN
end
Next Col
// Verify backside inspection data
For Col = COL$INSP_SPEC_BSIDE_SCRATCHES to COL$INSP_SPEC_BSIDE_SPIKES
ColSpec = BackSpecRow<1, Col>
ColVal = BackSigRow<1, Col>
If ( (ColSpec NE '') and (ColVal EQ '') ) then
ErrMsg('Process Error':@SVM:'Data is missing in column number ':Col-1:'.')
Set_Property(CtrlID,'SELPOS',Col:@FM:SelectedRow)
RETURN
end
Next Col
CONVERT @VM TO '' IN SigRow
Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM
Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP'
Vals = Get_Property(Ctrls,Props)
WONo = Vals[1,@RM]
WOStep = Vals[COL2()+1,@RM]
CassNo = Vals[COL2()+1,@RM]
Stage = Vals[COL2()+1,@RM]
RDSNo = Vals[COL2()+1,@RM]
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo)
ReactType = WOLogRow<WO_LOG_REACT_TYPE$>
IF Stage = 'POST' THEN
IF RDSNo = '' THEN
* Epi Pro wafers
SigAction = WOStep:'MO_PSTI'
SigStage = 'MO_PSTI'
END ELSE
SigAction = WOStep:'PSTI'
SigStage = 'PSTI'
END
END ELSE
SigAction = WOStep:Stage:'I'
SigStage = Stage:'I'
END
IF SigRow NE '' AND CtrlList<SelectedRow,COL$INSP_SIG> = '' THEN
If SelectedRow EQ 1 then
WOMatKey = WONo:'*':CassNo
Signature_Services('CheckSigOrder', WOMatKey, SigStage, False$, RDSNo)
If Error_Services('HasError') then
ErrMsg(Error_Services('GetMessage'))
return
end
END ;* End of check for 1st Signature row
// Add check for supplement signatures
ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo)
If Count(ValidStages, SigStage) NE 0 then
UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage)
If UnacknowledgedSupp NE FALSE$ then
Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$)
If Response EQ False$ then return
end
End
// Check if edge inspection is prescribed. If so, prompt user whether or not edge defects are present.
If EdgeInspReq then
// If edge defects are present, present user with a wafer selection dialog and create an NCR for those wafers.
Response = Msg(@Window, '', 'YESNO', '', 'Edge Defects':@FM:'Are any edge defects present?')
If Response EQ True$ then
// Display a popup of wafers in the RDS or WM_OUT cassette
WONo = Get_Property(@Window : '.WO_NO', 'TEXT')
WOStepNo = Get_Property(@Window:'.WO_STEP', 'TEXT')
ReactType = Xlate('WO_LOG', WONo, 'REACT_TYPE', 'X')
CassNo = Get_Property(@Window:'.CASS_NO', 'TEXT')
WOMatKey = WONo:'*':CassNo
If ReactType NE 'EPP' then
// Non-EpiPro
// Loop until user successfully creates an NCR
Loop
ErrFlag = False$
// Prompt user to select affected wafers
Response = Dialog_Box('DBW_WO_MAT_WAFER_SELECT', @Window, WOMatKey)
If Response EQ 'Cancel' then
ErrMsg('Signature operation aborted.')
return
end
SelRowData = SRP_Array('Rotate', Response, @FM, @VM)
SlotNos = SelRowData<COL$SLOT>
WfrIDs = SelRowData<COL$WAFER_ID>
PrevNCRs = SelRowData<COL$SLOT_NCR>
MetNos = SelRowData<COL$MET_NO$>
MUWfrIDs = SelRowData<COL$MU_WAFER_ID>
IneligibleSlots = ''
For each SlotNo in SlotNos using @VM setting vPos
MetNo = MetNos<0, vPos>
WfrID = WfrIDs<0, vPos>
PrevNCR = PrevNCRs<0, vPos>
MUWfrID = MUWfrIDs<0, vPos>
If ( (MetNo NE '') or (WfrID EQ '') or (PrevNCR NE '' and MUWfrID EQ '') ) then
ErrFlag = True$
IneligibleSlots<0, -1> = SlotNo
end
Next SlotNo
If ErrFlag EQ False$ then
// Place the lot on hold if it isn't already.
HoldEntity = 'WO_MAT'
HoldEntityID = WOMatKey
Set_Status(0)
OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X')
* If Not(OnHold) then obj_WO_Mat('ToggleHold',WOMatKey:@RM:HoldEntity:@RM:HoldEntityID:@RM:'')
If Not(OnHold) then Hold_Services('ToggleHold', WOMatKey, HoldEntity, HoldEntityID, '', '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
// Ensure the user didn't cancel the hold operation.
OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X')
If OnHold then
// Set ROTR block on reactor
Reactor = Xlate('RDS', RDSNo, 'REACTOR', 'X')
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor)
ReactorRec<REACTOR_ROTR_STATUS$> = 'F'
ReactorRec<REACTOR_ROTR_STATUS_REASON$> = 'Edge defects reported for RDS ':RDSNo:'.'
Database_Services('WriteDataRow', 'REACTOR', RDSNo, ReactorRec)
Def = ""
Def<MTEXT$> = "Creating NCR...Please wait"
Def<MTYPE$> = "U"
MsgUp = Msg(@window, Def) ;* display the processing message
WOMatKey = WONo:'*':CassNo
ncrParms = WONo:@RM
ncrParms := WOStepNo:@RM
ncrParms := CassNo:@RM
ncrParms := RDSNo:@RM
ncrParms := Reactor:@RM
ncrParms := '':@RM ;* Stage
ncrParms := '':@RM ;* InCassNos
ncrParms := SlotNos:@RM ;* InSlotNos
ncrParms := '':@RM ;* EPP only - PockeNots
ncrParms := '':@RM ;* EPP only - Zones
ncrParms := '':@RM ;* EPP only - OutCassNos
ncrParms := '':@RM ;* EPP only - OutSlotNos
ncrParms := '':@RM ;* EPP only - Multiple RDSNos
ncrParms := WfrIDs:@RM ;* Rejected Wafer ID's
ncrParms := PrevNCRs:@RM ;* Previous NCR Nos
ncrParms := '':@RM ;* EPP only - MU WONos
ncrParms := '':@RM ;* EPP only - MU WO Step Nos
ncrParms := '':@RM ;* EPP only - MU Cass Nos
ncrParms := '':@RM ;* EPP only - MU Slot Nos
ncrParms := 'C':@RM ;* Loss By
ncrParms := 'Wafers removed due to edge defects':@RM ;* Containment Actions
ncrParms := 'Edge defects discovered during post-epi inspection':@RM ;* Loss Comments
ncrParms := '':@RM ;* AC Comments
ncrParms := '':@RM ;* Department Responsible
ncrParms := '':@RM ;* AC Code
ncrParms := 'D63':@RM ;* Loss Code
ncrParms := 'O':@RM ;* NCR Status - Open
ncrParms := '':@RM ;* Shift
ncrParms := '':@RM ;* Shipment Signature
ncrParms := '':@RM ;* Reject Signature
ncrParms := '':@RM ;* Sent to SPC Datetime
ncrParms := '':@RM ;* Shipment Signature Datetime
ncrParms := 'Production' ;* Department Handled
Set_Status(0)
NCRNo = obj_NCR('Create',ncrParms) ;* Create new NCR for this wafer/group of wafers
Msg(@window, MsgUp) ;* take down the processing message
SAPBatchNo = Xlate('WO_MAT', WOMatKey, 'SAP_BATCH_NO', 'X')
IF Not(Get_Status(errCode)) THEN
IF SAPBatchNo NE '' THEN
IF SAPBatchNo[-1,1] NE 'R' THEN
MUFlag = Xlate('NCR', NCRNo, 'MAKEUP_BOX', 'X')
MUFlag = OCONV(MUFlag ,'BYes,')
PartNoID = Xlate('NCR', NCRNo, 'WO_MAT_PART_NO', 'X')
RejCnt = Xlate('NCR', NCRNo, 'REJ_CNT', 'X')
Recipients = XLATE('NOTIFICATION', 'NCR_AFTER_GR', NOTIFICATION_USER_ID$, 'X')
SentFrom = @USER4
Subject = 'SAP Post - GR Scrap Qty - NCR Reported' ;* Modified subject line - dkk 7/17/14
Message = "NCR: ":NCRNo:CRLF$:"Batch_No: ":SAPBatchNo:CRLF$:"MU Box: ":MUFlag:CRLF$:"Epi PN: ":PartNoID:CRLF$:"Qty: ":RejCnt ;* Added Epi PN on the end - dkk 7/17/14
AttachWindow = 'NCR'
AttachKey = NCRNo
SendToGroup = ''
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
END
END
RejDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS')
sCnt = COUNT(SlotNos,@VM) + (SlotNos NE '')
FOR N = 1 TO sCnt
* * * * Added 3/23/2016 JCH - wafer history * * * *
RejWfrID = WfrIDs<1,N>
CurrSlotID = WONo:'*':CassNo:'*':SlotNos<1,N>
Convert '.' To '*' In RejWfrID
Parms = RejWfrID:@RM ;* WfrID
Parms := RejDTM:@RM ;* EventDtm
Parms := @USER4:@RM ;* EventBy
Parms := 'NCR':@RM ;* Event
Parms := '':@RM ;* NewSlotID
Parms := '':@RM ;* RunLoc
Parms := NCRNo:@RM ;* NCRNo
Parms := '':@RM ;* TWUse
Parms := CurrSlotID:@RM ;* CurrSlotID
Parms := '':@RM ;* NewToolID
Parms := '':@RM ;* CurrToolID
Parms := '':@RM ;* NewInvLoc
Parms := '':@RM ;* CurrInvLoc
Parms := 'O' ;* Wfr Side
obj_WO_Wfr('AddEvent',Parms)
* * * * * * * * *
LineNo = SlotNos<1,N>
NEXT N
// Display the new NCR so the user can fill in the details and sign it off.
Dialog_Box('NCR', @Window, NCRNo)
end else
// Bail to force user to contact FI to correct issue.
ErrMsg('Error creating NCR. Error message: ':ErrCode:'. Please contact FI for assistance.')
return
end
end else
// User cancelled the hold operation.
ErrMsg('The lot must be placed on hold. Signature operation cancelled.')
return
end
end else
// Bail to force user to contact FI to correct issue.
ErrMsg('Error placing lot on hold. Error message: ':ErrCode:'. Please contact FI for assistance.')
return
end
end else
// Inform user ineligible wafer(s) were selected and loop to try again.
Swap @VM with ',' in IneligibleSlots
ErrMsg('Selected slot(s) ' : IneligibleSlots : ' are not eligible for NCR.')
end
Until Not(ErrFlag)
Repeat
end else
// EpiPro
WMOKey = WONo:'*':WOStepNo:'*':CassNo
// Loop until user selects at least one eligible wafer to NCR.
Loop
ErrFlag = False$
// Prompt user to select affected wafers.
SelRows = ''
Response = Dialog_Box('DBW_WM_OUT_WAFER_SELECT', @Window, WMOKey)
If Response EQ 'Cancel' then
ErrMsg('Signature operation aborted.')
return
end
SelRowData = SRP_Array('Rotate', Response, @FM, @VM)
NCROutSlotNos = SelRowData<COL$EPP_SLOT>
NCROutCassNos = Str(CassNo:@VM, DCount(NCROutSlotNos, @VM))
NCROutCassNos[-1 ,1] = ''
NCRRDSNos = SelRowData<COL$EPP_RDS_NO>
NCRPocketNos = SelRowData<COL$EPP_POCKET>
NCRZones = SelRowData<COL$EPP_ZONE>
NCRInCassNos = SelRowData<COL$EPP_IN_CASS>
NCRInSlotNos = SelRowData<COL$EPP_IN_SLOT>
NCRSlotNCRs = SelRowData<COL$EPP_SLOT_NCR>
NCRMUWONos = SelRowData<COL$EPP_MU_WO_NO>
NCRMUWOSteps = SelRowData<COL$EPP_MU_WO_STEP>
NCRMUCassIDs = SelRowData<COL$EPP_MU_CASS_NO>
NCRMUSlotNos = SelRowData<COL$EPP_MU_SLOT_NO>
UsedMUCassIDs = SelRowData<COL$EPP_UMW_CASS_ID>
ErrFlag = False$
For each SelSlot in NCROutSlotNos using @VM setting vPos
IF UsedMUCassIDs<0, vPos> = '' THEN
IF NCRRDSNos<0, vPos> NE '' THEN
IF NCRSlotNCRs<0, vPos> = '' OR NCRMUWONos<0, vPos> NE '' THEN
Null
END ELSE
ErrMsg('Slot ':SelSlot:' is empty.')
ErrFlag = True$
END ;* End of check for no Slot NCR (original wafer being rejected) or MU wafer data (makeup wafer being rejected)
END ELSE
ErrMsg('Slot ':SelSlot:' is not used.')
ErrFlag = True$
END ;* End of check for RDS (wafer) present and not used for makeup
END ELSE
ErrMsg('Slot ':SelSlot:' has been used for makeup.')
ErrFlag = True$
END ;* End of check for slot Used for Makeup Wafer
Until ErrFlag
Next SelSlot
// Create an NCR with edge defects loss code
If Not(ErrFlag) then
// Place the lot on hold if it isn't already on hold.
HoldEntity = 'WM_OUT'
HoldEntityID = WMOKey
Set_Status(0)
OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X')
* If Not(OnHold) then obj_WO_Mat('ToggleHold',WOMatKey:@RM:HoldEntity:@RM:HoldEntityID:@RM:'')
If Not(OnHold) then Hold_Services('ToggleHold', WOMatKey, HoldEntity, HoldEntityID, '', '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
// Ensure the user didn't cancel the hold operation.
OnHold = Xlate('WM_OUT', WMOKey, 'HOLD', 'X')
If OnHold then
// Set ROTR block on reactor
ROTRReactNos = SRP_Array('Clean', NCRRDSNos, 'TrimAndMakeUnique', @VM)
If ROTRReactNos NE '' then
For each ROTRReactNo in ROTRReactNos using @VM
Reactor = Xlate('RDS', ROTRReactNo, 'REACTOR', 'X')
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor)
ReactorRec<REACTOR_ROTR_STATUS$> = 'F'
ReactorRec<REACTOR_ROTR_STATUS_REASON$> = 'Edge defects reported for outbound cassette ':WMOKey:'.'
Database_Services('WriteDataRow', 'REACTOR', Reactor, ReactorRec)
Next ROTRReactNo
end
Def = ""
Def<MTEXT$> = "Creating NCR...Please wait"
Def<MTYPE$> = "U"
MsgUp = Msg(@window, Def) ;* display the processing message
ncrParms = WONo:@RM
ncrParms := WOStep:@RM
ncrParms := CassNo:@RM
ncrParms := '':@RM ;* Single RDS field - N/A for EpiPro
ncrParms := '':@RM ;* Reactor No - N/A for EpiPro
ncrParms := 'POST':@RM
ncrParms := NCRInCassNos:@RM
ncrParms := NCRInSlotNos:@RM
ncrParms := NCRPocketNos:@RM
ncrParms := NCRZones:@RM
ncrParms := NCROutCassNos:@RM
ncrParms := NCROutSlotNos:@RM
ncrParms := NCRRDSNos:@RM
ncrParms := '':@RM ;* Placeholder for RejWaferIDS - N/A for EpiPro
ncrParms := NCRSlotNCRs:@RM
ncrParms := NCRMUWONos:@RM
ncrParms := NCRMUWOSteps:@RM
ncrParms := NCRMUCassIDs:@RM
ncrParms := NCRMUSlotNos:@RM
ncrParms := 'C':@RM ;* Loss By
ncrParms := 'Wafers removed due to edge defects':@RM ;* Containment Actions
ncrParms := 'Edge defects discovered during post-epi inspection':@RM ;* Loss Comments
ncrParms := '':@RM ;* AC Comments
ncrParms := '':@RM ;* Department Responsible
ncrParms := '':@RM ;* AC Code
ncrParms := 'D63':@RM ;* Loss Code
ncrParms := 'O':@RM ;* NCR Status - Open
ncrParms := '':@RM ;* Shift
ncrParms := '':@RM ;* Shipment Signature
ncrParms := '':@RM ;* Reject Signature
ncrParms := '':@RM ;* Sent to SPC Datetime
ncrParms := '':@RM ;* Shipment Signature Datetime
ncrParms := 'Production' ;* Department Handled
Set_Status(0)
NCRNo = obj_NCR('Create',ncrParms) ;* Create new NCR for this wafer/group of wafers
Msg(@window, MsgUp) ;* take down the processing message
ErrCode = ''
If Not(Get_Status(ErrCode)) then
WMORec = Database_Services('ReadDataRow', 'WM_OUT', WMOKey)
RejDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS')
RejWfrIDs = ''
FOR N = 1 TO COUNT(NCROutSlotNos,@VM) + (NCROutSlotNos NE '')
* * * * Added 4/23/2016 JCH - wafer history * * * *
CurrSlotID = WONo:'*':NCROutCassNos<1,N>:'*':NCROutSlotNos<1,N>
IF NCRMUWONos<1,N> = '' THEN
RejWfrID = WONo:'*':NCRInCassNos<1,N>:'*':NCRInSlotNos<1,N>
END ELSE
RejWfrID = NCRMUWONos<1,N>:'*':NCRMUCassIDs<1,N>:'*':NCRMUSlotNos<1,N>
END
RejWfrIDs<1,-1> = RejWfrID
Parms = RejWfrID:@RM ;* WfrID
Parms := RejDTM:@RM ;* EventDtm
Parms := @USER4:@RM ;* EventBy
Parms := 'NCR':@RM ;* Event
Parms := '':@RM ;* NewSlotID
Parms := '':@RM ;* RunLoc
Parms := NCRNo:@RM ;* NCRNo
Parms := '':@RM ;* TWUse
Parms := CurrSlotID:@RM ;* CurrSlotID
Parms := '':@RM ;* NewToolID
Parms := '':@RM ;* CurrToolID
Parms := '':@RM ;* NewInvLoc
Parms := '':@RM ;* CurrInvLoc
Parms := 'O' ;* Wfr Side
obj_WO_Wfr('AddEvent',Parms)
// Add NCR details to WM_OUT record
SlotNo = NCROutSlotNos<1,N>
WMORec<WM_OUT_RDS$, SlotNo> = ''
WMORec<WM_OUT_POCKET$, SlotNo> = ''
WMORec<WM_OUT_ZONE$, SlotNo> = ''
WMORec<WM_OUT_IN_CASS_NO$, SlotNo> = ''
WMORec<WM_OUT_IN_SLOT_NO$, SlotNo> = ''
WMORec<WM_OUT_SLOT_NCR$, SlotNo> = NCRNo
WMORec<WM_OUT_MU_WO_NO$, SlotNo> = ''
WMORec<WM_OUT_MU_WO_STEP$, SlotNo> = ''
WMORec<WM_OUT_MU_CASS_NO$, SlotNo> = ''
WMORec<WM_OUT_MU_SLOT_NO$, SlotNo> = ''
NEXT N
Database_Services('WriteDataRow', 'WM_OUT', WMOKey, WMORec)
Dialog_Box('NCR', @Window, NCRNo)
end else
// Bail to force user to contact FI to correct issue.
ErrMsg('Error creating NCR. Error message: ':ErrCode:'. Please contact FI for assistance.')
return
end
end else
// User cancelled the hold operation.
ErrMsg('The lot must be placed on hold. Signature operation cancelled.')
return
end
end else
// Bail to force user to contact FI to correct issue.
ErrMsg('Error placing lot on hold. Error message: ':ErrCode:'. Please contact FI for assistance.')
return
end
end
Until Not(ErrFlag)
Repeat
end
end
end
IF MemberOf(@USER4, 'OI_SUPERUSER') THEN
Valid = 1
END ELSE
Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) )
END
IF Valid = 1 THEN
Def = ""
Def<MTEXT$> = "Updating material log and saving clean && inspection record..."
Def<MTYPE$> = "U"
MsgUp = Msg(@window, Def) ;* display the processing message
CurrDate = OCONV(Date(),'D4/')
CurrTime = OCONV(Time(),'MTHS')
CurrDTM = CurrDate:' ':CurrTime
Signer = @USER4
ToolID = CtrlList<SelectedRow,COL$INSP_TOOL>
If ToolID EQ 'SCOPE' or ToolID EQ 'SCOPE/FF EDGE INSP' then
ToolWHCd = 'CR'
ToolLoc = 'QA'
end else
ToolRec = XLATE('TOOL',ToolID,'','X')
ToolWHCd = ToolRec<TOOL_TOOL_WH$>
ToolLoc = ToolRec<TOOL_TOOL_LOC$>
end
Tag = ''
IF CassNo NE '' THEN
owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTI signature
IF Get_Status(errCode) THEN
CALL ErrMsg(ErrCode)
RETURN 0
END
LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM
LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM
Action = SigAction ; WOMLParms := Action:@RM
WhCd = ToolWHCd ; WOMLParms := WhCd:@RM
LocCd = ToolLoc ; WOMLParms := LocCd:@RM
WONos = WONo ; WOMLParms := WONos:@RM
CassNos = CassNo ; WOMLParms := CassNos:@RM
UserID = @USER4 ; WOMLParms := UserID:@RM
Tags = '' ; WOMLParms := Tags:@RM
ToolID = ToolID ; WOMLParms := ToolID
obj_WO_Mat_Log('Create',WOMLParms) ;* Add WOStep:'PSTI' to WO_MAT Event Log
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
END ;* End of check for null Cass No (EpiPro Reactor runs)
Set_Property(CtrlID,'CELLPOS',Signer,COL$INSP_SIG:@FM:SelectedRow)
Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$INSP_SIG_DTM:@FM:SelectedRow)
CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP')
Set_Property(@WINDOW,'@DONT_CLOSE',1)
Send_Event(@WINDOW,'WRITE')
Msg(@window, MsgUp) ;* take down the processing message
obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO')
END
END ELSE
IF SigRow = '' THEN
ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.')
RETURN
END
IF CtrlList<SelectedRow,COL$INSP_SIG> NE '' THEN
ErrMsg('Process Error':@SVM:'Row is already signed.')
RETURN
END
END
RETURN
* * * * * * *
SignScan:
* * * * * * *
CtrlID = @WINDOW:'.SCAN_RESULTS'
CtrlList = Get_Property(CtrlID,'LIST')
SlotSelection = Get_Property(CtrlID,'SELPOS')
SelectedRows = SlotSelection<2>
SlotSelection = Get_Property(CtrlID,'SELPOS')
SelectedRow = SlotSelection<2>
SigRow = CtrlList<SelectedRow>
IF SigRow<1,COL$SCAN_TOOL> = '' THEN
ErrMsg('Process Error':@SVM:'Scan Tool column is required.')
Set_Property(CtrlID,'SELPOS',COL$SCAN_TOOL:@FM:SelectedRow)
RETURN
END
CONVERT @VM TO '' IN SigRow
***
Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM
Ctrls := @WINDOW:'.WO_STEP':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.CASS_NO':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.RDS_NO' ; Props := 'DEFPROP'
Vals = Get_Property(Ctrls,Props)
WONo = Vals[1,@RM]
WOStep = Vals[COL2()+1,@RM]
CassNo = Vals[COL2()+1,@RM]
Stage = Vals[COL2()+1,@RM]
RDSNo = Vals[COL2()+1,@RM]
WOLogRow = Database_Services('ReadDataRow', 'WO_LOG', WONo)
ReactType = WOLogRow<WO_LOG_REACT_TYPE$>
IF Stage = 'POST' THEN
IF RDSNo = '' THEN
* Epi Pro wafers
SigAction = WOStep:'MO_PSTS'
SigStage = 'MO_PSTS'
END ELSE
SigAction = WOStep:'PSTS'
SigStage = 'PSTS'
END
END ELSE
SigAction = WOStep:Stage:'S'
SigStage = Stage:'S'
END
IF SigRow NE '' AND CtrlList<SelectedRow,COL$SCAN_SIG> = '' AND CtrlList<SelectedRow,COL$SCAN_SIG_DTM> = '' THEN
If SelectedRow EQ 1 then
WOMatKey = WONo:'*':CassNo
Signature_Services('CheckSigOrder', WOMatKey, SigStage, False$, RDSNo)
If Error_Services('HasError') then
ErrMsg(Error_Services('GetMessage'))
return
end
end
// Add check for supplement signatures
ValidStages = Supplement_Services('GetStagesForLot', 'RDS', RDSNo)
If Count(ValidStages, SigStage) NE 0 then
UnacknowledgedSupp = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, SigStage)
If UnacknowledgedSupp NE FALSE$ then
Response = Dialog_Box('NDW_RDS_SUPP_SIG', @Window, RDSNo :@FM: SigStage :@FM: FALSE$)
If Response EQ False$ then return
end
End
// This checks to see if manually entered data is authorized to be signed.
IF (SigRow NE '') AND (CtrlList<SelectedRow,COL$SCAN_TEST_RUN_DTM> = '') AND (Stage NE 'POST') THEN
Authorized = MemberOf(@USER4, 'ENGINEERING') OR MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') OR MemberOf(@USER4, 'ROTR_OVERRIDE')
If Not(Authorized) then
ErrorText = 'Only Leads, Supervisors or Engineers can sign ROTR Tencor data manually entered.'
ErrMsg('Process Error':@SVM:ErrorText)
Return
end
end
IF MemberOf(@USER4, 'OI_SUPERUSER') THEN
Valid = 1
END ELSE
Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) )
END
IF Valid = 1 THEN
CurrDate = OCONV(Date(),'D4/')
CurrTime = OCONV(Time(),'MTHS')
CurrDTM = CurrDate:' ':CurrTime
Signer = @USER4
ToolID = CtrlList<SelectedRow,COL$SCAN_TOOL>
ToolRec = XLATE('TOOL',ToolID,'','X')
ToolWHCd = ToolRec<TOOL_TOOL_WH$>
ToolLoc = ToolRec<TOOL_TOOL_LOC$>
Tag = ''
// Only call if this is non-EpiPro. - 04/09/2018 - dmb
If ReactType NE 'EPP' then
owmParms = WONo:@RM:CassNo:@RM:WOStep:@RM:SigStage:@RM:Signer:@RM:CurrDTM:@RM:ToolID:@RM:ToolWHCd:@RM:ToolLoc:@RM:Tag ;* Sets PSTI signature
IF Get_Status(errCode) THEN
CALL ErrMsg(ErrCode)
RETURN 0
END
LogFile = 'WO_MAT' ; WOMLParms = LogFile:@RM
LogDTM = CurrDTM ; WOMLParms := LogDTM:@RM
Action = SigAction ; WOMLParms := Action:@RM
WhCd = ToolWHCd ; WOMLParms := WhCd:@RM
LocCd = ToolLoc ; WOMLParms := LocCd:@RM
WONos = WONo ; WOMLParms := WONos:@RM
CassNos = CassNo ; WOMLParms := CassNos:@RM
UserID = @USER4 ; WOMLParms := UserID:@RM
Tags = '' ; WOMLParms := Tags:@RM
ToolID = ToolID ; WOMLParms := ToolID
obj_WO_Mat_Log('Create',WOMLParms) ;* Sets PSTI in WO_MAT Event Log
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
end
Set_Property(CtrlID,'CELLPOS',Signer,COL$SCAN_SIG:@FM:SelectedRow)
Set_Property(CtrlID,'CELLPOS',CurrDTM,COL$SCAN_SIG_DTM:@FM:SelectedRow)
CINo = Get_Property(@WINDOW:'.CI_NO','DEFPROP')
Set_Property(@WINDOW,'@DONT_CLOSE',1)
Send_Event(@WINDOW,'WRITE')
obj_AppWindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO')
END
END ELSE
IF SigRow = '' THEN
ErrMsg('Process Error':@SVM:'Must have some information in selected row to sign.')
RETURN
END
IF CtrlList<SelectedRow,COL$SCAN_SIG> NE '' OR CtrlList<SelectedRow,COL$SCAN_SIG_DTM> NE '' THEN
ErrMsg('Process Error':@SVM:'Row is already signed.')
RETURN
END
END
RETURN
SIGN_ROTR_ACCEPTANCE.CLICK:
Valid = Dialog_Box( 'QUOTE_SIG_PWD_ENTRY', @WINDOW, @USER4:@VM:XLATE( 'LSL_USERS', @USER4, LSL_USERS_PASSWORD$, 'X' ) )
If Valid EQ True$ then
OrigReason = Get_Property(@Window : '.SIGN_ROTR_REASON', 'DEFPROP')
Reason = Msg(@Window, '', 'MESSAGE_INPUT', '', 'ROTR Acceptance' : @FM : 'ROTR Acceptance Reason' : @FM : OrigReason)
If Reason NE '' then
Set_Property(@Window : '.SIGN_ROTR_SIGNATURE', 'INVALUE', @USER4)
Set_Property(@Window : '.SIGN_ROTR_DATE_TIME', 'DEFPROP', Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTHS'))
Set_Property(@Window : '.SIGN_ROTR_REASON', 'DEFPROP', Reason)
Send_Event(@Window : '.SIGN_ROTR_SIGNATURE_NAME', 'CALCULATE')
end
end
return
SCAN_RESULTS.CHAR:
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
If Stage EQ 'LWI' then
CtrlEntID = 'SCAN_RESULTS'
CIKey = Get_Property(@Window : '.CI_NO', 'TEXT')
ReactorNo = Xlate('CLEAN_INSP', CIKey, 'REACT_NO', 'X')
CanEdit = Get_Property(@Window, '@CAN_EDIT')
If Not(CanEdit) then
PrevFocusID = Get_Property (@Window, "PREVFOCUS")
Message = 'Only a member of lead, supervisor, final_qa,':@SVM:'engineering, or rotr_override can manually enter data.'
Response = Msg(@Window, '', 'OVERRIDE', '', Message)
Begin Case
Case Response EQ 1
Response = True$ ; // User Clicked Override
Case Response EQ 2
Response = False$ ; // User Clicked Cancel
Case Response EQ char(27)
Response = False$ ; // User Pressed Escape Key
End Case
If Response EQ True$ then
OverrideGroups = 'LEAD' : @VM : 'SUPERVISOR' : @VM : 'ENGINEERING' :@VM: 'FINAL_QA' :@VM: 'ROTR_OVERRIDE'
Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : OverrideGroups)
Valid = Response<1>
Username = Response<2>
If NOT(Valid) then
Set_Property(@Window, 'FOCUS', PrevFocusID)
Set_Property(CtrlEntID, 'SELPOS', -1:@FM:-1)
end else
Set_Property(@Window, '@CAN_EDIT', True$)
CanEdit = True$
end
end else
Set_Property(@Window, 'FOCUS', PrevFocusID)
Set_Property(CtrlEntID, 'SELPOS', -1:@FM:-1)
end
end
If (CanEdit EQ True$) then
// Enable manual entry of data.
ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, '')
For column = 1 to 7
ScanStyles<column> = BitAnd( ScanStyles<column>, BitNot(PROTECTED$) )
Next column
// Enable dropdown menus for recipe and tool columns.
ScanStyles<COL$SCAN_RECIPE> = BitOr(ScanStyles<COL$SCAN_RECIPE>, DTCS_DROPDOWN$ )
ScanStyles<COL$SCAN_TOOL> = BitOr(ScanStyles<COL$SCAN_TOOL>, DTCS_DROPDOWN$ )
ScanStyles = Send_Message(@Window : '.SCAN_RESULTS', 'COLSTYLE', 0, ScanStyles)
end
end
****************Logging Manual Data Entry********************
TableContents = Get_Property(@Window:'.SCAN_RESULTS', 'ARRAY')
ToolID = TableContents<COL$SCAN_TOOL, 1>
IF ToolID NE '' then
Date = SRP_DateTime('Now')
EpochStart = 00732
EpochTime = SRP_DateTime('SecondSpan',EpochStart, Date)
RDSNo = Get_Property(@Window:'.RDS_NO', 'DEFPROP')
PSNo = Get_Property(@Window:'.PS_NO', 'DEFPROP')
User = @User4
Description = 'Manual SurfScan Data Entry detected for RDS #: ':RDSNo
Reactor = XLATE('RDS', RDSNo, 2, 'X')
FileName = Environment_Services('GetApplicationRootPath'): '\LogFiles\ManualDataEntry\PollPath\' : EpochTime :'.json'
OSWrite '' to FileName
JSON = '{"Equipment":"':ToolID:'", "Reactor":"':Reactor:'", "PSN":"':PSNo:'", "RDS":"':RDSNo:'", "User": "':User:'", "Description":"':Description:'"}'
OSWrite JSON to FileName
end
return
SCAN_RESULTS.POSCHANGED:
ScanCtrl = @Window : '.SCAN_RESULTS'
ScanCtrlList = Get_Property(ScanCtrl, 'LIST')
SelPos = Get_Property(ScanCtrl, 'SELPOS')
RowPos = SelPos<2>
TestDTM = ScanCtrlList<RowPos,COL$SCAN_TEST_RUN_DTM>
If TestDTM EQ '' then
Set_Property(@Window:'.BTN_WAFER_DETAILS', 'ENABLED', False$)
end else
Set_Property(@Window:'.BTN_WAFER_DETAILS', 'ENABLED', True$)
end
return
BTN_WAFER_DETAILS.CLICK:
PrevCursor = Set_Property('SYSTEM', 'CURSOR', 'H')
Yield()
CleanInspKey = Get_Property(@Window : '.CI_NO', 'TEXT')
SelPos = Get_Property(@Window : '.SCAN_RESULTS', 'SELPOS')
RowPos = SelPos<2>
If RowPos EQ '' then RowPos = 1
CreateParam = CleanInspKey : @FM : RowPos
WindowName = Create_Dialog('NDW_ROTR_WAFER_DETAILS', @Window, True$, CreateParam)
PrevCursor = Set_Property('SYSTEM', 'CURSOR', PrevCursor)
return
* * * * * * *
RefreshSpec:
* * * * * * *
CINo = Get_Property(@WINDOW:'.CI_NO','TEXT')
PSStageKey = Get_Property(@WINDOW:'.PS_STAGE_KEY','TEXT')
IF CINo NE '' AND PSStageKey NE '' THEN
Send_Event(@WINDOW,'WRITE')
obj_Clean_Insp('SpecDelta',CINo:@RM:PSStageKey)
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
obj_Appwindow('LUValReturn',CINo:@RM:@WINDOW:'.CI_NO')
END
RETURN
* * * * * * *
InspPC:
* * * * * * *
CurrInspPos = Get_Property(@WINDOW:'.INSP_RESULTS','SELPOS')
CurrBSInspPos = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS')
CurrInspCol = CurrInspPos<1>
CurrInspRow = CurrInspPos<2>
CurrBSInspCol = CurrBSInspPos<1>
CurrBSInspRow = CurrBSInspPos<2>
Set_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS',CurrBSInspCol:@FM:CurrInspRow)
GOSUB Refresh
RETURN
* * * * * * *
BSideInspPC:
* * * * * * *
CurrInspPos = Get_Property(@WINDOW:'.INSP_RESULTS','SELPOS')
CurrBSInspPos = Get_Property(@WINDOW:'.INSP_RESULTS_BSIDE','SELPOS')
CurrInspCol = CurrInspPos<1>
CurrInspRow = CurrInspPos<2>
CurrBSInspCol = CurrBSInspPos<1>
CurrBSInspRow = CurrBSInspPos<2>
Set_Property(@WINDOW:'.INSP_RESULTS','SELPOS',CurrInspCol:@FM:CurrBSInspRow)
GOSUB Refresh
RETURN
* * * * * * *
SendSPC:
* * * * * * *
Ctrls = @WINDOW:'.RDS_NO':@RM ; Props = 'DEFPROP':@RM
Ctrls := @WINDOW:'.STAGE':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SS_SCAN_TOOL':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SUM_OF_DEF_MIN':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SUM_OF_DEF_MAX':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SUM_OF_DEF_AVG':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.HAZE_AVG_AVG':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SPOTS':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.FOV':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SCRATCHES':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SCRATCH_LEN':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.REACT_NO':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.WAFER_SIZE':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SS_SCRATCH_MAX':@RM ; Props := 'DEFPROP':@RM
Ctrls := @WINDOW:'.SS_SCRATCH_AVG' ; Props := 'DEFPROP'
Vals = Get_Property(Ctrls,Props)
RDSNo = Vals[1,@RM]
Stage = Vals[COL2()+1,@RM]
ScanTool = Vals[COL2()+1,@RM]
SumOfDefMin = Vals[COL2()+1,@RM]
SumOfDefMax = Vals[COL2()+1,@RM]
SumOfDefAvg = Vals[COL2()+1,@RM]
HazeAvgAvg = Vals[COL2()+1,@RM]
Spots = Vals[COL2()+1,@RM]
FOV = Vals[COL2()+1,@RM]
Scratches = Vals[COL2()+1,@RM]
ScratchLen = Vals[COL2()+1,@RM]
ReactNo = Vals[COL2()+1,@RM]
WaferSize = Vals[COL2()+1,@RM]
SSScratchMax = Vals[COL2()+1,@RM]
SSScratchAvg = Vals[COL2()+1,@RM]
WaferSize = WaferSize[1,' '] ;* Data looks like "125 mm 6 in"
UserName = OCONV(@USER4,'[XLATE_CONV,LSL_USERS*FIRST_LAST]')
DataLine = QUOTE(ReactNo):TAB$
DataLine := QUOTE(RDSNo):TAB$
DataLine := QUOTE(Stage):TAB$
DataLine := QUOTE(ScanTool):TAB$
DataLine := QUOTE(SumOfDefMin):TAB$
DataLine := QUOTE(SumOfDefMax):TAB$
DataLine := QUOTE(SumOfDefAvg):TAB$
DataLine := QUOTE(HazeAvgAvg):TAB$
DataLine := QUOTE(Spots):TAB$
DataLine := QUOTE(FOV):TAB$
DataLine := QUOTE(Scratches):TAB$
DataLine := QUOTE(ScratchLen):TAB$
DataLine := QUOTE(UserName):TAB$
DataLine := QUOTE(SSScratchAvg):TAB$
DataLine := QUOTE(SSScratchMax):TAB$
DataLine := QUOTE(WaferSize)
DOSFile = Environment_Services('GetSPCDataPath') : '\SPC_Surf.txt'
* * * * * * *
DosRead:
* * * * * * *
// SPC Server has been migrated to the EC domain. SPC Queue must be utilized to transfer SPC files.
Filename = 'SPC_Surf.txt'
SPCQueueKey = Date():'*':Time():'*':@USER4
SPCQueueRec = ''
SPCQueueRec<SPC_QUEUE.SPC_FILENAME$> = Filename
SPCQueueRec<SPC_QUEUE.SPC_DOC$> = DataLine:CRLF$
Database_Services('WriteDataRow', 'SPC_QUEUE', SPCQueueKey, SPCQueueRec, True$, False$, False$)
CurrDTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTS')
Set_Property(@WINDOW:'.SPC_DTM','DEFPROP',CurrDTM)
RETURN
* * * * * * *
SetGroupBackground:
* * * * * * *