834 lines
35 KiB
Plaintext
834 lines
35 KiB
Plaintext
Function NDW_QA_MET_RESULT_EVENTS(CtrlEntId, Event, @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 Infineon.
|
|
|
|
Name : NDW_QA_MET_RESULT_EVENTS
|
|
|
|
Description : This function acts as a commuter module for all events related to this window.
|
|
|
|
Notes : Commuter Modules are automatically called from the Promoted_Events function which is called by the
|
|
application-specific promoted event handler. This makes it possible to add QuickEvents that need to
|
|
execute Basic+ logic without having use the Form Designer to make the association, although this is
|
|
limited to the events which are currently promoted.
|
|
|
|
If the form needs to call the commuter module directly then the QuickEvent parameters should be
|
|
formatted like this:
|
|
|
|
'@SELF','@EVENT',['@PARAM1','@PARAMx']
|
|
|
|
Parameters :
|
|
CtrlEntId [in] -- The fully qualified name of the control calling the promoted event
|
|
Event [in] -- The event being executed. See the Notes section regarding "PRE" events
|
|
Param1-15 [in] -- Additional event parameter holders
|
|
EventFlow [out] -- Set to 1 or 0 so the calling event knows whether or not to chain forward. See comments in
|
|
EVENT_SETUP insert
|
|
|
|
History : (Date, Initials, Notes)
|
|
06/08/18 djs Created initial commuter module.
|
|
07/30/18 djs Refactored form and commuter module to apply to the Unload stage only. Other stages
|
|
will use the previous form, QA_MET_RESULT.
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
#pragma precomp SRP_PreCompiler
|
|
#Window NDW_QA_MET_RESULT
|
|
|
|
DECLARE SUBROUTINE Set_Property, End_Dialog, Send_Event, Set_Status, obj_WO_Mat, Btree.Extract
|
|
DECLARE SUBROUTINE ErrMsg, Set_Property, obj_AppWindow, Send_Event, obj_WO_Mat_QA, obj_Tables
|
|
DECLARE SUBROUTINE Start_Window, End_Window, Database_Services
|
|
Declare subroutine SRP_EditTable_Manager, SRP_Show_Window, Rds_Services, Form_Services
|
|
|
|
DECLARE FUNCTION Get_Property, Get_Status, Dialog_Box, obj_WM_Out, set_WinMsgVal, Form_Services, Memberof
|
|
DECLARE FUNCTION Msg, obj_WO_Mat, Send_Message, obj_Tables, Start_Window, End_Window, QA_Services, Signature_Services
|
|
DECLARE FUNCTION SRP_EditTable_Manager, Database_Services, Material_Services, Rds_Services, RGB
|
|
|
|
$insert LOGICAL
|
|
$insert EVENT_SETUP
|
|
$insert WO_MAT_EQUATES
|
|
$insert MSG_EQUATES
|
|
$INSERT LSL_USERS_EQU
|
|
$INSERT WM_OUT_EQUATES
|
|
$INSERT WO_MAT_QA_EQUATES
|
|
$INSERT POPUP_EQUATES
|
|
$INSERT APPCOLORS
|
|
$INSERT RDS_EQUATES
|
|
$INSERT PRS_STAGE_EQUATES
|
|
$INSERT TOOL_CLASS_EQUATES
|
|
|
|
Equ Tab$ to \09\
|
|
Equ CRLF$ to \0D0A\
|
|
Equ LF$ to \0A\
|
|
Equ Comma$ to ','
|
|
|
|
ErrTitle = 'Error in NDW_QA_Met_Result_Events'
|
|
ErrorMsg = ''
|
|
|
|
Result = ''
|
|
|
|
SubclassInfo = Form_Services('FindSubclassControl')
|
|
Subclass = SubclassInfo<1>
|
|
|
|
// Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler.
|
|
If Event EQ 'OLE' then
|
|
Transfer Event to OIEvent
|
|
Transfer Param1 to Event
|
|
Transfer Param2 to Param1
|
|
Transfer Param3 to Param2
|
|
* Transfer Param4 to Param3
|
|
* Transfer Param5 to Param4
|
|
* Transfer Param6 to Param5
|
|
* Transfer Param7 to Param6
|
|
* Transfer Param8 to Param7
|
|
end
|
|
|
|
GoToEvent Event for CtrlEntID
|
|
|
|
Return EventFlow else EVENT_CONTINUE$
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Events
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Event WINDOW.CREATE(CreateParam)
|
|
|
|
*******************
|
|
* Read Parameters *
|
|
*******************
|
|
|
|
CassID = CreateParam[1,@FM]
|
|
Stage = CassID[-1, 'B*']
|
|
WONo = FIELD(CassID,'*',1)
|
|
WOStepNo = FIELD(CassID,'*',2)
|
|
CassNo = FIELD(CassID,'*',3)
|
|
RDSNo = FIELD(CassID,'*',4)
|
|
RunStep = FIELD(CassID,'*',5)
|
|
CanEdit = (Memberof(@USER4, 'ENGINEERING') or Memberof(@USER4, 'LEAD') or Memberof(@USER4, 'SUPERVISOR'))
|
|
If CanEdit then
|
|
If Stage EQ 'UNLOAD' then
|
|
//Check if UNLOAD stage is signed
|
|
UnloadSigned = Signature_Services('GetStageSummary', WoMatKey, 'UNLOAD')<2>
|
|
If UnloadSigned then
|
|
Set_Property(@Window, '@CANEDIT', True$)
|
|
end else
|
|
Set_Property(@Window, '@CANEDIT', False$)
|
|
end
|
|
end
|
|
end else
|
|
Set_Property(@Window, '@CANEDIT', False$)
|
|
end
|
|
|
|
|
|
|
|
Set_Property(@Window : '.WO_NO', 'TEXT', WoNo)
|
|
Set_Property(@Window : '.PROC_STEP_NO', 'TEXT', WOStepNo)
|
|
Set_Property(@Window : '.OUT_CASS_NO', 'TEXT', CassNo)
|
|
Set_Property(@Window : '.RDS_NO', 'TEXT', RDSNo)
|
|
Set_Property(@Window : '.STAGE', 'TEXT', Stage)
|
|
Set_Property(@Window : '.RUN_STEP', 'TEXT', RunStep)
|
|
|
|
WOMatQAKey = WONo : '*' : CassNo
|
|
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
|
|
Profile = WOMatQARec<WO_MAT_QA_PROFILE$>
|
|
ThickSpecMin = ''
|
|
ThickSpecMax = ''
|
|
HgCVSpecMin = ''
|
|
HgCVSpecMax = ''
|
|
HgCVSpecPhaseMin = ''
|
|
Locate '1THICK_ONLY' in Profile using @VM setting vPos then
|
|
ThickSpecMin = WOMatQARec<WO_MAT_QA_MIN$, vPos>
|
|
ThickSpecMax = WOMatQARec<WO_MAT_QA_MAX$, vPos>
|
|
end
|
|
Locate '1CRES' in Profile using @VM setting vPos then
|
|
HgCVSpecMin = WOMatQARec<WO_MAT_QA_MIN$, vPos>
|
|
HgCVSpecMax = WOMatQARec<WO_MAT_QA_MAX$, vPos>
|
|
HgCVSpecPhaseMin = WOMatQARec<WO_MAT_QA_PHASE_MIN$, vPos>
|
|
If HgCVSpecPhaseMin EQ '' then
|
|
// Phase Min Spec was not added to WO_MAT_QA record when it should have been.
|
|
// This bug should be fixed now, but in the meantime current records in production
|
|
// may not have a phase min specification value. We need to add it here. - djs - 10/15/18
|
|
PSN = Xlate('RDS', RDSNo, 'PROD_SPEC_ID', 'X')
|
|
If PSN NE '' then
|
|
PRSStageKey = PSN:'*UNLOAD'
|
|
Database_Services('ActivateRecord', 'PRS_STAGE', PRSStageKey)
|
|
MetProps = {MET_PROP}
|
|
Locate 'CRES' in MetProps using @VM setting PropPos then
|
|
SpecPhaseMinCol = {MET_PHASE_MIN}
|
|
SpecPhaseMin = SpecPhaseMinCol<1, PropPos>
|
|
WOMatQARec<WO_MAT_QA_PHASE_MIN$, vPos> = SpecPhaseMin
|
|
HgCVSpecPhaseMin = SpecPhaseMin
|
|
Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatQAKey, WOMatQARec, True$, False$, False$)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
If ThickSpecMin NE '' then
|
|
Set_Property(@Window : '.THICK_SPEC_MIN', 'TEXT', ThickSpecMin)
|
|
Set_Property(@Window : '.THICK_SPEC_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
If ThickSpecMax NE '' then
|
|
Set_Property(@Window : '.THICK_SPEC_MAX', 'TEXT', ThickSpecMax)
|
|
Set_Property(@Window : '.THICK_SPEC_MAX', 'BACKCOLOR', GREEN$)
|
|
end
|
|
If HgCVSpecMin NE '' then
|
|
Set_Property(@Window : '.HGCV_SPEC_MIN', 'TEXT', HgCVSpecMin)
|
|
Set_Property(@Window : '.HGCV_SPEC_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
If HgCVSpecMax NE '' then
|
|
Set_Property(@Window : '.HGCV_SPEC_MAX', 'TEXT', HgCVSpecMax)
|
|
Set_Property(@Window : '.HGCV_SPEC_MAX', 'BACKCOLOR', GREEN$)
|
|
end
|
|
If HgCVSpecPhaseMin NE '' then
|
|
Set_Property(@Window : '.HGCV_SPEC_PHASE_MIN', 'TEXT', HgCVSpecPhaseMin)
|
|
Set_Property(@Window : '.HGCV_SPEC_PHASE_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
|
|
GoSub FillHgCVTable
|
|
|
|
SRP_Show_Window(@Window, '', 'C', 'C', 1, '', False$, False$, FormSize)
|
|
|
|
end event
|
|
|
|
|
|
Event THICK_READINGS.GOTFOCUS(PrevFocusID)
|
|
WO = Get_Property(@Window : '.WO_NO', 'TEXT')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'TEXT')
|
|
WoMatKey = WO : '*' : CassNo
|
|
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
|
|
If Stage EQ 'UNLOAD' then
|
|
test = Signature_Services('GetStageSummary', WoMatKey, 'UNLOAD')
|
|
UnloadSigned = Signature_Services('GetStageSummary', WoMatKey, 'UNLOAD')<2>
|
|
If UnloadSigned then
|
|
GoSub VerifyUser
|
|
end else
|
|
Message = 'Unload metrology data may only be entered after the UNLOAD signature has been signed.'
|
|
Msg(@Window, Message)
|
|
end
|
|
end else
|
|
GoSub VerifyUser
|
|
end
|
|
|
|
|
|
end event
|
|
|
|
|
|
Event HGCV_READINGS.GOTFOCUS(PrevFocusID)
|
|
WO = Get_Property(@Window : '.WO_NO', 'TEXT')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'TEXT')
|
|
WoMatKey = WO : '*' : CassNo
|
|
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
|
|
GoSub VerifyUser
|
|
|
|
end event
|
|
|
|
|
|
Event HGCV_PHASE_READINGS.GOTFOCUS(PrevFocusID)
|
|
WO = Get_Property(@Window : '.WO_NO', 'TEXT')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'TEXT')
|
|
WoMatKey = WO : '*' : CassNo
|
|
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
|
|
GoSub VerifyUser
|
|
end event
|
|
|
|
|
|
Event THICK_AVG.GOTFOCUS(PrevFocusID)
|
|
|
|
GoSub VerifyUser
|
|
|
|
end event
|
|
|
|
|
|
Event HGCV_AVG.GOTFOCUS(PrevFocusID)
|
|
|
|
GoSub VerifyUser
|
|
|
|
end event
|
|
|
|
|
|
Event HGCV_PHASE_AVG.GOTFOCUS(PrevFocusID)
|
|
|
|
GoSub VerifyUser
|
|
|
|
end event
|
|
|
|
|
|
Event SIGN.CLICK()
|
|
WO = Get_Property(@Window : '.WO_NO', 'TEXT')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'TEXT')
|
|
WoMatKey = WO : '*' : CassNo
|
|
Stage = Get_Property(@Window : '.STAGE', 'TEXT')
|
|
If Stage EQ 'UNLOAD' then
|
|
UnloadSigned = Signature_Services('GetStageSummary', WoMatKey, 'UNLOAD')<2>
|
|
If UnloadSigned then
|
|
GoSub SaveQAData
|
|
end else
|
|
GoSub VerifyUser
|
|
CanEdit = Get_Property(@Window, '@CANEDIT')
|
|
If CanEdit then
|
|
GoSub SaveQAData
|
|
end else
|
|
Message = 'Unload metrology data may only be entered after the UNLOAD signature has been signed.'
|
|
Msg(@Window, Message)
|
|
Return
|
|
end
|
|
|
|
end
|
|
end else
|
|
GoSub SaveQAData
|
|
end
|
|
|
|
|
|
SignatureReady = True$
|
|
WONo = Get_Property(@WINDOW:'.WO_NO','DEFPROP')
|
|
CassNo = Get_Property(@WINDOW:'.OUT_CASS_NO','DEFPROP')
|
|
WOMatQAKey = WONo : '*' : CassNo
|
|
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey, True$, 0, False$)
|
|
UnloadOutOfSpec = 0
|
|
Stages = WOMatQARec<WO_MAT_QA_STAGE$>
|
|
TestAvgs = WOMatQARec<WO_MAT_QA_RESULT$>
|
|
For each Stage in Stages using @VM setting vPos
|
|
If Stage EQ 'UNLOAD' then
|
|
// Check if an average value (i.e. result) exists for the test.
|
|
// If not, then skip if that test has failed.
|
|
TestComp = (TestAvgs<0, vPos> NE '')
|
|
If TestComp EQ True$ then
|
|
StageOutOfSpec = WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$, vPos>
|
|
If StageOutOfSpec EQ True$ then
|
|
StageFailReason = WOMatQARec<WO_MAT_QA_FAIL_REASON$, vPos>
|
|
// Ignore signature failures since user is attempting to sign the records.
|
|
If (StageFailReason NE 'THICK_ONLY UNLOAD product measurement test has not been signed.') |
|
|
and (StageFailReason NE 'CRES UNLOAD product measurement test has not been signed.') then
|
|
UnloadOutOfSpec += 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Next Stage
|
|
OutOfSpec = Sum(UnloadOutOfSpec)
|
|
If OutOfSpec GT 0 then
|
|
FailReasons = WOMatQARec<WO_MAT_QA_FAIL_REASON$>
|
|
Msg = 'Unable to sign Unload QA Metrology for the followings reason(s).'
|
|
For each FailReason in FailReasons using @VM
|
|
If (FailReason NE 'THICK_ONLY UNLOAD product measurement test has not been signed.') |
|
|
and (FailReason NE 'CRES UNLOAD product measurement test has not been signed.') then
|
|
Msg := CRLF$ : FailReason
|
|
end
|
|
Next FailReason
|
|
ErrMsg(Msg)
|
|
SignatureReady = False$
|
|
end
|
|
|
|
RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT')
|
|
|
|
IF (SignatureReady = True$) THEN
|
|
|
|
Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW)
|
|
Valid = Response<1>
|
|
Username = Response<2>
|
|
|
|
IF (Valid) THEN
|
|
DTM = OCONV(Date(),'D4/'):' ':OCONV(Time(),'MTHS')
|
|
|
|
OverrideUser = Get_Property(@Window, '@OVERRIDE_USER')
|
|
If OverrideUser NE '' then
|
|
Signature = OverrideUser
|
|
end else
|
|
Signature = Username
|
|
end
|
|
|
|
Profile = WOMatQARec<WO_MAT_QA_PROFILE$>
|
|
Locate '1THICK_ONLY' in Profile setting vPos then
|
|
Avg = WOMatQARec<WO_MAT_QA_RESULT$, vPos>
|
|
Sig = WOMatQARec<WO_MAT_QA_SIG$, vPos>
|
|
If (Avg NE '') and (Sig EQ '') then
|
|
WOMatQARec<WO_MAT_QA_SIG$, vPos> = Signature
|
|
WOMatQARec<WO_MAT_QA_SIG_DTM$, vPos> = IConv(DTM, 'DT')
|
|
end
|
|
end
|
|
|
|
Locate '1CRES' in Profile setting vPos then
|
|
Avg = WOMatQARec<WO_MAT_QA_RESULT$, vPos>
|
|
Sig = WOMatQARec<WO_MAT_QA_SIG$, vPos>
|
|
If (Avg NE '') and (Sig EQ '') then
|
|
WOMatQARec<WO_MAT_QA_SIG$, vPos> = Signature
|
|
WOMatQARec<WO_MAT_QA_SIG_DTM$, vPos> = IConv(DTM, 'DT')
|
|
end
|
|
end
|
|
end
|
|
Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatQAKey, WOMatQARec, True$, False$, True$)
|
|
|
|
Send_Event('RDS_UNLOAD','WRITE')
|
|
obj_Appwindow('LoadFormKeys','RDS_UNLOAD':@RM:RDSNo)
|
|
|
|
End_Window(@WINDOW,'')
|
|
|
|
END ELSE ;* End of check for Signature Ready
|
|
|
|
Send_Event('RDS_UNLOAD','WRITE')
|
|
obj_Appwindow('LoadFormKeys','RDS_UNLOAD':@RM:RDSNo)
|
|
|
|
END
|
|
|
|
end event
|
|
|
|
|
|
Event TW_USE_BUTTON.CLICK()
|
|
|
|
GoSub LaunchRDSMetrology
|
|
|
|
end event
|
|
|
|
|
|
Event EXIT.CLICK()
|
|
|
|
End_Window(@Window, '')
|
|
|
|
end event
|
|
|
|
|
|
Event WINDOW.CLOSE(CancelFlag)
|
|
|
|
End_Window(@WINDOW,'')
|
|
|
|
end event
|
|
|
|
|
|
Event OLE_SUBCLASS.OnComboClick(CtrlId, Sel, Value)
|
|
|
|
Send_Event(CtrlId, 'LOSTFOCUS')
|
|
|
|
end event
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Internal GoSubs
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Setup_OLE_Controls:
|
|
|
|
Qualify = ''
|
|
Qualify<1> = 1
|
|
Qualify<4> = 0
|
|
|
|
return
|
|
|
|
|
|
FillHgCVTable:
|
|
|
|
WorkOrderNo = Get_Property(@Window : '.WO_NO', 'DEFPROP')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'DEFPROP')
|
|
WOMatQAKey = WorkOrderNo : '*' : CassNo
|
|
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
|
|
DataPoints = WOMatQARec<WO_MAT_QA_DATA_POINTS$>
|
|
Profiles = WOMatQARec<WO_MAT_QA_PROFILE$> ; // THICK_ONLY, CRES
|
|
Result = WOMatQARec<WO_MAT_QA_RESULT$> ; // Average of Data Points
|
|
MinResult = WOMatQARec<WO_MAT_QA_MIN_RESULT$> ; // Min of Data Points
|
|
MaxResult = WOMatQARec<WO_MAT_QA_MAX_RESULT$> ; // Max of Data Points
|
|
RangePctResult = WOMatQARec<WO_MAT_QA_RANGE_PCT_RESULT$> ; // Range % of Data Points
|
|
EdgeMeanResult = WOMatQARec<WO_MAT_QA_EDGE_MEAN_RESULT$> ; // Edge Mean Delta of Data Points
|
|
SpecMin = WOMatQARec<WO_MAT_QA_MIN$>
|
|
SpecMax = WOMatQARec<WO_MAT_QA_MAX$>
|
|
SpecPhaseMin = WOMatQARec<WO_MAT_QA_PHASE_MIN$>
|
|
ToolClasses = WOMatQARec<WO_MAT_QA_TOOL_CLASS$>
|
|
Patterns = WOMatQARec<WO_MAT_QA_RECIPE_PATTERN$>
|
|
RowLimit = Get_Property(@Window : '.TEST_POINTS', 'ROWLIMIT') ; //Default row limit.
|
|
RowLimits = ''
|
|
MaxRows = 0
|
|
|
|
For each Pattern in Patterns using @VM setting vPos
|
|
|
|
ToolClass = ToolClasses<1, vPos>
|
|
ToolClassRec = Database_Services('ReadDataRow', 'TOOL_CLASS', ToolClass)
|
|
ToolPatterns = ToolClassRec<TOOL_CLASS_PATTERN$>
|
|
ToolPatternSizes = ToolClassRec<TOOL_CLASS_PATTERN_SIZE$>
|
|
Locate Pattern in ToolPatterns using @VM setting PatternPos then
|
|
PatternSize = ToolPatternSizes<1, PatternPos>
|
|
If PatternSize GT MaxRows then MaxRows = PatternSize
|
|
RowLimits<1, vPos> = PatternSize
|
|
end else
|
|
RowLimits<1, vPos> = RowLimit
|
|
end
|
|
Next Recipe
|
|
|
|
BadColorArray = RED$:@FM:'':@FM:BRED$:@FM:''
|
|
GoodColorArray = GREEN$:@FM:'':@FM:'':@FM:''
|
|
List = ''
|
|
HgCVData = ''
|
|
PhaseData = ''
|
|
|
|
|
|
For each Profile in Profiles using @VM setting ProfIndex
|
|
|
|
If Profile EQ '1THICK_ONLY' then
|
|
ThickEditCtrl = @Window:'.THICK_READINGS'
|
|
List = DataPoints<1, ProfIndex>
|
|
PatternSize = RowLimits<1, ProfIndex>
|
|
If List NE '' then
|
|
// Data points 11-14 are not to be used for statistical analysis within OpenInsight. We will display
|
|
// them, but will not flag them as within/out of spec nor will we block signatures if they are out of
|
|
// bounds. This means that the min, max, and average will be calculated using points 1-9.
|
|
StopPoint = 10
|
|
SpecThickMin = SpecMin<1, ProfIndex>
|
|
SpecThickMax = SpecMax<1, ProfIndex>
|
|
Convert @SVM to @VM in List
|
|
NumRows = DCount(List, @VM)
|
|
// Fill out the edit table to RowLimit for clean display
|
|
For CurrRow = NumRows to PatternSize
|
|
List := @VM
|
|
Next CurrRow
|
|
Set_Property(@Window : '.THICK_READINGS', 'DEFPROP', List)
|
|
For each ThickDataPoint in List using @VM setting vPos
|
|
Until (vPos GT NumRows) or (vPos GT StopPoint)
|
|
If ( ThickDataPoint LT SpecThickMin ) OR ( ThickDataPoint GT SpecThickMax ) then
|
|
stat = Send_Message(ThickEditCtrl, 'COLOR_BY_POS', 0, vPos, BadColorArray)
|
|
end else
|
|
stat = Send_Message(ThickEditCtrl, 'COLOR_BY_POS', 0, vPos, GoodColorArray)
|
|
end
|
|
Next ThickDataPoint
|
|
end else
|
|
For Row = 1 to PatternSize
|
|
stat = Send_Message(ThickEditCtrl, 'COLOR_BY_POS', 0, Row, BadColorArray)
|
|
Next Row
|
|
Set_Property(@Window : '.THICK_AVG', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.THICK_MIN', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.THICK_MAX', 'BACKCOLOR', RED$)
|
|
end
|
|
SpecThickMin = SpecMin<1, ProfIndex>
|
|
SpecThickMax = SpecMax<1, ProfIndex>
|
|
ResultThickAvg = Result<1, ProfIndex>
|
|
ResultThickMin = MinResult<1, ProfIndex>
|
|
ResultThickMax = MaxResult<1, ProfIndex>
|
|
Set_Property(@Window : '.THICK_AVG', 'DEFPROP', ResultThickAvg)
|
|
Set_Property(@Window : '.THICK_MIN', 'DEFPROP', ResultThickMin)
|
|
Set_Property(@Window : '.THICK_MAX', 'DEFPROP', ResultThickMax)
|
|
|
|
If ResultThickAvg NE '' and SpecThickMax NE '' and SpecThickMin NE '' then
|
|
If (ResultThickAvg GT SpecThickMax) OR (ResultThickAvg LT SpecThickMin) then
|
|
Set_Property(@Window : '.THICK_AVG', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.THICK_AVG', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
|
|
If ResultThickMin NE '' and SpecThickMax NE '' and SpecThickMin NE '' then
|
|
If (ResultThickMin GT SpecThickMax) OR (ResultThickMin LT SpecThickMin) then
|
|
Set_Property(@Window : '.THICK_MIN', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.THICK_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
|
|
If ResultThickMax NE '' and SpecThickMax NE '' and SpecThickMin NE '' then
|
|
If (ResultThickMax GT SpecThickMax) OR (ResultThickMax LT SpecThickMin) then
|
|
Set_Property(@Window : '.THICK_MAX', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.THICK_MAX', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
end
|
|
|
|
If Profile EQ '1CRES' then
|
|
HgCVEditCtrl = @Window:'.HGCV_READINGS'
|
|
PhaseEditCtrl = @Window:'.HGCV_PHASE_READINGS'
|
|
List = DataPoints<1, ProfIndex>
|
|
PatternSize = RowLimits<1, ProfIndex>
|
|
CriticalPoints = '1,2,5,6,9'
|
|
SpecHgCVMin = SpecMin<1, ProfIndex>
|
|
SpecHgCVMax = SpecMax<1, ProfIndex>
|
|
ThisSpecPhaseMin = SpecPhaseMin<1, ProfIndex>
|
|
If List NE '' then
|
|
For each DataPoint in List using @SVM setting SVPos
|
|
HgCVData := DataPoint[1, 'F' : @TM] : @VM
|
|
PhaseData := DataPoint[-1, 'B' : @TM] : @VM
|
|
Next DataPoint
|
|
HgCVData[-1, 1] = '' ; // Strip final @VM
|
|
PhaseData[-1, 1] = ''
|
|
NumRows = DCount(HgCVData, @VM)
|
|
// Fill out the edit table to RowLimit for clean display
|
|
For CurrRow = NumRows to PatternSize
|
|
HgCVData := @VM
|
|
PhaseData := @VM
|
|
Next CurrRow
|
|
HgCVRangePct = RangePctResult<1, ProfIndex, 1>
|
|
PhaseRangePct = RangePctResult<1, ProfIndex, 2>
|
|
HgCVEdgeMean = EdgeMeanResult<1, ProfIndex, 1>
|
|
PhaseEdgeMean = EdgeMeanResult<1, ProfIndex, 2>
|
|
Set_Property(@Window : '.HGCV_READINGS', 'DEFPROP', HgCVData)
|
|
Set_Property(@Window : '.HGCV_PHASE_READINGS', 'DEFPROP', PhaseData)
|
|
For each HgCVDataPoint in HgCVData using @VM setting vPos
|
|
Until vPos GT NumRows
|
|
If ( ( HgCVDataPoint LT SpecHgCVMin ) OR ( HgCVDataPoint GT SpecHgCVMax ) ) and Index(CriticalPoints, vPos, 1) then
|
|
stat = Send_Message(HgCVEditCtrl, 'COLOR_BY_POS', 0, vPos, BadColorArray)
|
|
end else
|
|
stat = Send_Message(HgCVEditCtrl, 'COLOR_BY_POS', 0, vPos, GoodColorArray)
|
|
end
|
|
Next HgCVDataPoint
|
|
For each PhaseDataPoint in PhaseData using @VM setting vPos
|
|
Until vPos GT NumRows
|
|
If ( PhaseDataPoint LT ThisSpecPhaseMin ) and Index(CriticalPoints, vPos, 1) then
|
|
stat = Send_Message(PhaseEditCtrl, 'COLOR_BY_POS', 0, vPos, BadColorArray)
|
|
end else
|
|
stat = Send_Message(PhaseEditCtrl, 'COLOR_BY_POS', 0, vPos, GoodColorArray)
|
|
end
|
|
Next PhaseDataPoint
|
|
Set_Property(@Window : '.HGCV_RANGE_PCT', 'TEXT', HgCVRangePct : '%')
|
|
Set_Property(@Window : '.HGCV_PHASE_RANGE_PCT', 'TEXT', PhaseRangePct : '%')
|
|
Set_Property(@Window : '.HGCV_EDGE_DELTA', 'DEFPROP', HgCVEdgeMean : '%')
|
|
Set_Property(@Window : '.HGCV_PHASE_DELTA', 'DEFPROP', PhaseEdgeMean : '%')
|
|
Set_Property(@Window : '.HGCV_RANGE_PCT', 'BACKCOLOR', GREEN$)
|
|
Set_Property(@Window : '.HGCV_PHASE_RANGE_PCT', 'BACKCOLOR', GREEN$)
|
|
Set_Property(@Window : '.HGCV_EDGE_DELTA', 'BACKCOLOR', GREEN$)
|
|
Set_Property(@Window : '.HGCV_PHASE_DELTA', 'BACKCOLOR', GREEN$)
|
|
|
|
end else
|
|
For each CriticalPoint in CriticalPoints using ','
|
|
stat = Send_Message(HgCVEditCtrl, 'COLOR_BY_POS', 0, CriticalPoint, BadColorArray)
|
|
stat = Send_Message(PhaseEditCtrl, 'COLOR_BY_POS', 0, CriticalPoint, BadColorArray)
|
|
Next CriticalPoint
|
|
Set_Property(@Window : '.HGCV_AVG', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_MIN', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_MAX', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_PHASE_AVG', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_PHASE_MIN', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_PHASE_MAX', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_RANGE_PCT', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_PHASE_RANGE_PCT', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_EDGE_DELTA', 'BACKCOLOR', RED$)
|
|
Set_Property(@Window : '.HGCV_PHASE_DELTA', 'BACKCOLOR', RED$)
|
|
|
|
end
|
|
|
|
HgCVAvg = Result<1, ProfIndex, 1>
|
|
PhaseAvg = Result<1, ProfIndex, 2>
|
|
HgCVMin = MinResult<1, ProfIndex, 1>
|
|
HgCVMax = MaxResult<1, ProfIndex, 1>
|
|
PhaseMin = MinResult<1, ProfIndex, 2>
|
|
PhaseMax = MaxResult<1, ProfIndex, 2>
|
|
Set_Property(@Window, '@ORIG_HGCV_AVG', HgCVAvg)
|
|
Set_Property(@Window : '.HGCV_AVG', 'DEFPROP', HgCVAvg)
|
|
Set_Property(@Window : '.HGCV_PHASE_AVG', 'DEFPROP', PhaseAvg)
|
|
Set_Property(@Window : '.HGCV_MIN', 'DEFPROP', HgCVMin)
|
|
Set_Property(@Window : '.HGCV_MAX', 'DEFPROP', HgCVMax)
|
|
Set_Property(@Window : '.HGCV_PHASE_MIN', 'DEFPROP', PhaseMin)
|
|
Set_Property(@Window : '.HGCV_PHASE_MAX', 'DEFPROP', PhaseMax)
|
|
|
|
If HgCVAvg NE '' and SpecHgCVMax NE '' and SpecHgCVMin NE '' then
|
|
If (HgCVAvg GT SpecHgCVMax) OR (HgCVAvg LT SpecHgCVMin) then
|
|
Set_Property(@Window : '.HGCV_AVG', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_AVG', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
If HgCVMin NE '' and SpecHgCVMax NE '' and SpecHgCVMin NE '' then
|
|
If (HgCVMin GT SpecHgCVMax) OR (HgCVMin LT SpecHgCVMin) then
|
|
Set_Property(@Window : '.HGCV_MIN', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
If HgCVMax NE '' and SpecHgCVMax NE '' and SpecHgCVMin NE '' then
|
|
If (HgCVMax GT SpecHgCVMax) OR (HgCVMax LT SpecHgCVMin) then
|
|
Set_Property(@Window : '.HGCV_MAX', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_MAX', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
If PhaseAvg NE '' and ThisSpecPhaseMin NE '' then
|
|
If (PhaseAvg LT ThisSpecPhaseMin) then
|
|
Set_Property(@Window : '.HGCV_PHASE_AVG', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_PHASE_AVG', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
If PhaseMin NE '' and ThisSpecPhaseMin NE '' then
|
|
If (PhaseMin LT ThisSpecPhaseMin) then
|
|
Set_Property(@Window : '.HGCV_PHASE_MIN', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_PHASE_MIN', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
If PhaseMax NE '' and ThisSpecPhaseMin NE '' then
|
|
If (PhaseMax LT ThisSpecPhaseMin) then
|
|
Set_Property(@Window : '.HGCV_PHASE_MAX', 'BACKCOLOR', RED$)
|
|
end else
|
|
Set_Property(@Window : '.HGCV_PHASE_MAX', 'BACKCOLOR', GREEN$)
|
|
end
|
|
end
|
|
end
|
|
|
|
Next Profile
|
|
|
|
List = ''
|
|
For Index = 1 to MaxRows
|
|
List := Index : @VM
|
|
Next Index
|
|
List[-1, 1] = ''
|
|
// Fill out the edit table to RowLimit for clean display
|
|
For CurrRow = Index to RowLimit
|
|
List := @VM
|
|
Next CurrRow
|
|
Set_Property(@Window : '.TEST_POINTS', 'DEFPROP', List)
|
|
return
|
|
|
|
|
|
SaveQAData:
|
|
|
|
RDSNo = Get_Property(@Window : '.RDS_NO', 'TEXT')
|
|
WorkOrderNo = Get_Property(@Window : '.WO_NO', 'TEXT')
|
|
CassNo = Get_Property(@Window : '.OUT_CASS_NO', 'TEXT')
|
|
WOMatQAKey = WorkOrderNo : '*' : CassNo
|
|
WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatQAKey)
|
|
DataPoints = WOMatQARec<WO_MAT_QA_DATA_POINTS$>
|
|
Profiles = WOMatQARec<WO_MAT_QA_PROFILE$> ; // THICK_ONLY, CRES
|
|
Result = WOMatQARec<WO_MAT_QA_RESULT$> ; // Average of Data Points
|
|
ThicknessData = Get_Property(@Window : '.THICK_READINGS', 'LIST')
|
|
HgCVData = Get_Property(@Window : '.HGCV_READINGS', 'LIST')
|
|
PhaseData = Get_Property(@Window : '.HGCV_PHASE_READINGS', 'LIST')
|
|
// The following average values are typically calculated in the WO_MAT_QA MFS, but can be manually
|
|
// entered by leads/engineers/supervisors in order to override the typical workflow.
|
|
ThickAvg = Get_Property(@Window : '.THICK_AVG', 'TEXT')
|
|
HgCVAvg = Get_Property(@Window : '.HGCV_AVG', 'TEXT')
|
|
PhaseAvg = Get_Property(@Window : '.HGCV_PHASE_AVG', 'TEXT')
|
|
|
|
Profile = ''
|
|
For each Profile in Profiles using @VM setting ProfileIndex
|
|
|
|
Begin Case
|
|
Case Profile EQ '1THICK_ONLY'
|
|
SaveList = ''
|
|
For each DataPoint in ThicknessData using @FM setting ThickIndex
|
|
* Until DataPoint EQ ''
|
|
SaveList<1, 1, ThickIndex> = DataPoint
|
|
Next DataPoint
|
|
If SaveList NE '' then
|
|
// This is the typical path where data is read in through metrology services
|
|
// and the min, max, and avg are calculated in the WO_MAT_QA MFS (WO_MAT_QA_ACTIONS).
|
|
DataPoints<1, ProfileIndex> = SaveList
|
|
end else
|
|
// Lead/Supervisor/Engineer is overriding the typical workflow by entering the
|
|
// Thickness average only.
|
|
Result<1, ProfileIndex> = ThickAvg
|
|
end
|
|
|
|
Case Profile EQ '1CRES'
|
|
SaveList = ''
|
|
For each DataPoint in HgCVData using @FM setting CresIndex
|
|
* Until DataPoint EQ ''
|
|
PhaseDataPoint = PhaseData<CresIndex>
|
|
SaveList<1, 1, CresIndex> = DataPoint : @TM : PhaseDataPoint
|
|
Next DataPoint
|
|
If SaveList NE '' then
|
|
// This is the typical path where data is read in through metrology services
|
|
// and the min, max, avg, etc. are calculated in the WO_MAT_QA MFS (WO_MAT_QA_ACTIONS).
|
|
DataPoints<1, ProfileIndex> = SaveList
|
|
end else
|
|
// Lead/Supervisor/Engineer is overriding the typical workflow by entering the
|
|
// HgCV average and the Phase average only.
|
|
Result<1, ProfileIndex, 1> = HgCVAvg
|
|
Result<1, ProfileIndex, 2> = PhaseAvg
|
|
end
|
|
End Case
|
|
|
|
Next Profile
|
|
|
|
WOMatQARec<WO_MAT_QA_DATA_POINTS$> = DataPoints
|
|
WOMatQARec<WO_MAT_QA_RESULT$> = Result
|
|
|
|
Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatQAKey, WOMatQARec, True$, False$, True$)
|
|
|
|
GoSub FillHgCVTable
|
|
|
|
return
|
|
|
|
|
|
LaunchRDSMetrology:
|
|
Ctrls = @WINDOW:'.WO_NO':@RM ; Props = 'DEFPROP':@RM
|
|
Ctrls := @WINDOW:'.PROC_STEP_NO':@RM ; Props := 'DEFPROP':@RM
|
|
Ctrls := @WINDOW:'.OUT_CASS_NO':@RM ; Props := 'DEFPROP':@RM
|
|
Ctrls := @WINDOW:'.RDS_NO':@RM ; Props := 'DEFPROP':@RM
|
|
Ctrls := @WINDOW:'.RUN_STEP':@RM ; Props := 'DEFPROP'
|
|
|
|
Vals = Get_Property(Ctrls,Props)
|
|
|
|
WONo = Vals[1,@RM]
|
|
WOStep = Vals[COL2()+1,@RM]
|
|
CassNo = Vals[COL2()+1,@RM]
|
|
RDSNo = Vals[COL2()+1,@RM]
|
|
RunStep = Vals[COL2()+1,@RM]
|
|
|
|
// RDS_TEST is Metrology Data
|
|
Open 'DICT.RDS_TEST' To DictRdsTest Else
|
|
ErrMsg('Unable to open DICT.RDS_TEST for index lookup')
|
|
Return
|
|
End
|
|
|
|
// Return Metrology key(s) associated with the RDSNo
|
|
Search = 'RDS_NO':@VM:RDSNo:@FM
|
|
RDSTestKeys = ''
|
|
Btree.Extract(Search,'RDS_TEST',DictRdsTest,RDSTestKeys,'','')
|
|
|
|
If Get_Status(errCode) Then
|
|
ErrMsg(errCode)
|
|
RETURN
|
|
End
|
|
|
|
// If there are multiple metrology records associated with the RDSNo, then
|
|
// provide a popup of the metrology records for the user to select from.
|
|
If Index(RDSTestKeys,@VM,1) Then
|
|
TypeOver = ''
|
|
TypeOver<PDISPLAY$> = RDSTestKeys
|
|
|
|
RDSTestKey = Popup(@WINDOW,TypeOver,'RDS_TEST')
|
|
End Else
|
|
RDSTestKey = RDSTestKeys
|
|
End
|
|
|
|
oaParms = 'RDS_TEST':@RM
|
|
oaParms := RDSTestKey:@RM
|
|
oaParms := ''
|
|
|
|
obj_AppWindow('ViewRelated',oaParms)
|
|
|
|
return
|
|
|
|
|
|
VerifyUser:
|
|
|
|
CanEdit = Get_Property(@Window, '@CANEDIT')
|
|
If Not(CanEdit) then
|
|
|
|
Message = 'Only a member of lead, supervisor, or ':@SVM:'engineering 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
|
|
Response = Dialog_Box('NDW_VERIFY_USER', @WINDOW, @USER4 : @FM : 'LEAD' : @VM : 'SUPERVISOR' : @VM : 'ENGINEERING')
|
|
Valid = Response<1>
|
|
Username = Response<2>
|
|
If NOT(Valid) then
|
|
Set_Property(@Window:'.EXIT', 'FOCUS', True$)
|
|
end else
|
|
// Store verified user's name so we can sign with it.
|
|
Set_Property(@Window, '@OVERRIDE_USER', Username)
|
|
Set_Property(@Window, '@CANEDIT', True$)
|
|
end
|
|
end else
|
|
Set_Property(@Window:'.EXIT', 'FOCUS', True$)
|
|
end
|
|
end
|
|
|
|
return
|
|
|
|
|