608 lines
33 KiB
Plaintext
608 lines
33 KiB
Plaintext
Function WO_MAT_QA_Actions(Action, CalcColName, FSList, Handle, Name, FMC, Record, Status, OrigRecord, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10)
|
|
/***********************************************************************************************************************
|
|
|
|
This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
|
|
permission from Infineon.
|
|
|
|
Name : WO_MAT_QA_Actions
|
|
|
|
Description : Handles calculated columns and MFS calls for the current table.
|
|
|
|
Notes : This function uses @ID, @RECORD, and @DICT to make sure {ColumnName} references work correctly.
|
|
If called from outside of a calculated column these will need to be set and restored.
|
|
|
|
Parameters :
|
|
Action [in] -- Name of the action to be taken
|
|
CalcColName [in] -- Name of the calculated column that needs to be processed. Normally this should only be
|
|
populated when the CalcField action is being used.
|
|
FSList [in] -- The list of MFSs and the BFS name for the current file or volume. This is an @SVM
|
|
delimited array, with the current MFS name as the first value in the array, and the BFS
|
|
name as the last value. Normally set by a calling MFS.
|
|
Handle [in] -- The file handle of the file or media map being accessed. Note, this does contain the
|
|
entire handle structure that the Basic+ Open statement would provide. Normally set by a
|
|
calling MFS.
|
|
Name [in] -- The name (key) of the record or file being accessed. Normally set by a calling MFS.
|
|
FMC [in] -- Various functions. Normally set by a calling MFS.
|
|
Record [in] -- The entire record (for record-oriented functions) or a newly-created handle (for
|
|
"get handle" functions). Normally set by a calling MFS.
|
|
Status [in/out] -- Indicator of the success or failure of an action. Normally set by the calling MFS but
|
|
for some actions can be set by the action handler to indicate failure.
|
|
OrigRecord [in] -- Original content of the record being processed by the current action. This is
|
|
automatically being assigned by the WRITE_RECORD and DELETE_RECORD actions within
|
|
BASE_MFS.
|
|
Param1-10 [in/out] -- Additional request parameter holders
|
|
ActionFlow [out] -- Used to control the action chain (see the ACTION_SETUP insert for more information.)
|
|
Can also be used to return a special value, such as the results of the CalcField
|
|
method.
|
|
|
|
History : (Date, Initials, Notes)
|
|
10/22/18 djs Original programmer.
|
|
|
|
|
|
***********************************************************************************************************************/
|
|
|
|
#pragma precomp SRP_PreCompiler
|
|
|
|
$insert LOGICAL
|
|
$insert FILE.SYSTEM.EQUATES
|
|
$insert ACTION_SETUP
|
|
$insert RDS_TEST_EQUATES
|
|
$insert RDS_EQUATES
|
|
$insert WO_LOG_EQUATES
|
|
$insert WM_OUT_EQUATES
|
|
$insert WM_IN_EQUATES
|
|
$insert WO_MAT_EQUATES
|
|
$insert WO_MAT_QA_EQUATES
|
|
$insert PRS_STAGE_EQUATES
|
|
$insert TOOL_CLASS_EQUATES
|
|
|
|
Declare function Database_Services, obj_NCR, obj_SAP, Qa_Services, SRP_Trim, Environment_Services, Logging_Services
|
|
Declare subroutine Error_Services, Database_Services, obj_NCR, obj_SAP, Post_Metrology_Manual_Data_Entry_Log
|
|
Declare subroutine Logging_Services, obj_Notes
|
|
|
|
Equ CRLF$ to \0D0A\
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\WO_MAT_QA'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' WO_MAT_QA Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'Key ID' : @FM : 'Call Stack' : @FM : 'Record'
|
|
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\FQABlocked'
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' FQA Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'RDS Key ID' : @FM : 'Table' : @FM : 'Key' : @FM : 'Notes'
|
|
FQAobjLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
|
|
|
|
If KeyID then GoSub Initialize_System_Variables
|
|
|
|
Begin Case
|
|
|
|
Case Action _EQC 'CalcField' ; GoSub Calc_Field
|
|
Case Action _EQC 'READ_RECORD_PRE' ; GoSub READ_RECORD_PRE
|
|
Case Action _EQC 'READ_RECORD' ; GoSub READ_RECORD
|
|
Case Action _EQC 'READONLY_RECORD_PRE' ; GoSub READONLY_RECORD_PRE
|
|
Case Action _EQC 'READONLY_RECORD' ; GoSub READONLY_RECORD
|
|
Case Action _EQC 'WRITE_RECORD_PRE' ; GoSub WRITE_RECORD_PRE
|
|
Case Action _EQC 'WRITE_RECORD' ; GoSub WRITE_RECORD
|
|
Case Action _EQC 'DELETE_RECORD_PRE' ; GoSub DELETE_RECORD_PRE
|
|
Case Action _EQC 'DELETE_RECORD' ; GoSub DELETE_RECORD
|
|
Case Otherwise$ ; Status = 'Invalid Action'
|
|
|
|
End Case
|
|
|
|
If KeyID then GoSub Restore_System_Variables
|
|
|
|
If Assigned(ActionFlow) else ActionFlow = ACTION_CONTINUE$
|
|
|
|
Return ActionFlow
|
|
|
|
|
|
// ----- Calculated Columns --------------------------------------------------------------------------------------------
|
|
//
|
|
// The typical structure of a calculated column will look like this:
|
|
//
|
|
// Declare function TableName_Actions
|
|
//
|
|
// A = {COL1} ; * Reference as many data columns in this way to ensure the dictionary dependency is generated.
|
|
//
|
|
// @ANS = TableName_Actions('CalcField', 'CalcColName')
|
|
//
|
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
|
|
Calc_Field:
|
|
// Make sure the ActionFlow return variable is cleared in case nothing is calculated.
|
|
ActionFlow = ''
|
|
|
|
return
|
|
|
|
|
|
// ----- MFS calls -----------------------------------------------------------------------------------------------------
|
|
|
|
READ_RECORD_PRE:
|
|
// In order to stop a record from being read in this action these lines of code must be used:
|
|
//
|
|
// OrigFileError = 100 : @FM : KeyID
|
|
// Status = 0
|
|
// Record = ''
|
|
// ActionFlow = ACTION_STOP$
|
|
return
|
|
|
|
READ_RECORD:
|
|
// In order to stop a record from being read in this action these lines of code must be used:
|
|
//
|
|
// OrigFileError = 100 : @FM : KeyID
|
|
// Status = 0
|
|
// Record = ''
|
|
return
|
|
|
|
READONLY_RECORD_PRE:
|
|
// In order to stop a record from being read in this action these lines of code must be used:
|
|
//
|
|
// OrigFileError = 100 : @FM : KeyID
|
|
// Status = 0
|
|
// Record = ''
|
|
// ActionFlow = ACTION_STOP$
|
|
return
|
|
|
|
READONLY_RECORD:
|
|
// In order to stop a record from being read in this action these lines of code must be used:
|
|
//
|
|
// OrigFileError = 100 : @FM : KeyID
|
|
// Status = 0
|
|
// Record = ''
|
|
return
|
|
|
|
WRITE_RECORD_PRE:
|
|
|
|
WorkOrderNo = Field(Name, '*', 1, 1)
|
|
CassNo = Field(Name, '*', 2, 1)
|
|
WOMatKey = WorkOrderNo : '*' : CassNo
|
|
FinalQA = False$
|
|
WorkOrderRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo)
|
|
ReactType = WorkOrderRow<WO_LOG_REACT_TYPE$>
|
|
// Check to see if the Final QA signature is in place.
|
|
If ReactType EQ 'EPP' then
|
|
WMOutKey = WorkOrderNo : '*1*' : CassNo
|
|
WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', WMOutKey)
|
|
If WMOutRow<WM_OUT_SUP_VER_SIG$> NE '' then
|
|
FinalQA = True$
|
|
end
|
|
end else
|
|
RDSNo = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
|
|
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
|
|
If RDSRow<RDS_SUP_VER_SIG$> NE '' then
|
|
FinalQA = True$
|
|
end
|
|
end
|
|
|
|
Begin Case
|
|
|
|
Case Record EQ ''
|
|
|
|
// Unscheduled record write attempt. Block the write and log the event.
|
|
ErrorMessage = 'Empty WO_MAT_QA profile. Unscheduled record write attempt!'
|
|
Error_Services('Add', 'FS104: ':ErrorMessage)
|
|
OrigFileError = 104 : @FM : ErrorMessage
|
|
Stack = RetStack()
|
|
Swap @FM with ' || ' in Stack
|
|
RecordSnapshot = Record
|
|
Swap @FM with CRLF$ in RecordSnapshot
|
|
Swap @VM with ' @VM ' in RecordSnapshot
|
|
Swap @SVM with ' @SVM ' in RecordSnapshot
|
|
Swap @TM with ' @TM ' in RecordSnapshot
|
|
Swap @STM with ' @STM ' in RecordSnapshot
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = @User4
|
|
LogData<3> = Name
|
|
LogData<4> = Stack
|
|
LogData<5> = CRLF$:RecordSnapshot:CRLF$
|
|
LogData<6> = 'FS104: ':ErrorMessage
|
|
|
|
// Sending a null message will send the LogData instead
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, '', '', '')
|
|
|
|
// Send an internal OI message to OI admins
|
|
Recipients = Xlate('SEC_GROUPS', 'OI_ADMIN', 'USER', 'X')
|
|
SentFrom = 'SYSTEM'
|
|
Subject = 'Unscheduled WO_MAT_QA record write attempt.'
|
|
Message = ErrorMessage
|
|
AttachWindow = ''
|
|
AttachKey = ''
|
|
SendToGroup = ''
|
|
Parms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
|
|
obj_Notes('Create',Parms)
|
|
|
|
Status = 0
|
|
Record = ''
|
|
ActionFlow = ACTION_STOP$
|
|
|
|
Case FinalQA EQ True$
|
|
|
|
// User is attempting to modify this row. Set the FS104 error and log the event.
|
|
OrigFileError = 104 : @FM : 'FQA has already been signed. WO_MAT_QA record cannot be updated!'
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = @User4
|
|
LogData<3> = WOMatKey
|
|
LogData<4> = 'WO_MAT_QA'
|
|
LogData<5> = Name
|
|
LogData<6> = 'FS104:FQA has already been signed. WO_MAT_QA record cannot be updated!'
|
|
Logging_Services('AppendLog', FQAobjLog, LogData, @RM, @FM)
|
|
Status = 0
|
|
Record = ''
|
|
ActionFlow = ACTION_STOP$
|
|
Error_Services('Add', 'FS104:FQA has already been signed. WO_MAT_QA record cannot be updated!')
|
|
|
|
Case Otherwise$
|
|
// Validate metrology data
|
|
|
|
// Current values in record
|
|
OrigDataPoints = OrigRecord<WO_MAT_QA_DATA_POINTS$>
|
|
OrigProfiles = OrigRecord<WO_MAT_QA_PROFILE$>
|
|
OrigResult = OrigRecord<WO_MAT_QA_RESULT$>
|
|
OrigSigs = OrigRecord<WO_MAT_QA_SIG$>
|
|
OrigSpecMin = OrigRecord<WO_MAT_QA_MIN$>
|
|
OrigSpecMax = OrigRecord<WO_MAT_QA_MAX$>
|
|
|
|
// New values to be saved
|
|
DataPoints = Record<WO_MAT_QA_DATA_POINTS$>
|
|
Profiles = Record<WO_MAT_QA_PROFILE$> ; // THICK_ONLY, CRES
|
|
Sigs = Record<WO_MAT_QA_SIG$>
|
|
SigDTMS = Record<WO_MAT_QA_SIG_DTM$>
|
|
Result = Record<WO_MAT_QA_RESULT$> ; // Average of Data Points
|
|
MinResult = Record<WO_MAT_QA_MIN_RESULT$> ; // Min of Data Points
|
|
MaxResult = Record<WO_MAT_QA_MAX_RESULT$> ; // Max of Data Points
|
|
RangePctResult = Record<WO_MAT_QA_RANGE_PCT_RESULT$> ; // Range % of Data Points
|
|
EdgeMeanResult = Record<WO_MAT_QA_EDGE_MEAN_RESULT$> ; // Edge Mean Delta of Data Points
|
|
SpecMin = Record<WO_MAT_QA_MIN$>
|
|
SpecMax = Record<WO_MAT_QA_MAX$>
|
|
SpecPhaseMin = Record<WO_MAT_QA_PHASE_MIN$>
|
|
OutOfSpec = Record<WO_MAT_QA_OUT_OF_SPEC$>
|
|
FailReasons = Record<WO_MAT_QA_FAIL_REASON$>
|
|
ScanRecipes = Record<WO_MAT_QA_RECIPE$>
|
|
Stages = Record<WO_MAT_QA_STAGE$>
|
|
PSN = {PS_NO}
|
|
RawThicknessData = ''
|
|
RawHgCVData = ''
|
|
RawPhaseData = ''
|
|
|
|
// Only enter validation code below if relevant data has changed.
|
|
If ( (OrigDataPoints NE DataPoints) or (OrigProfiles NE Profiles) or (OrigResult NE Result) |
|
|
or (OrigSigs NE Sigs) or (OrigSpecMin NE SpecMin) or (OrigSpecMax NE SpecMax) ) then
|
|
|
|
Profile = ''
|
|
For each Profile in Profiles using @VM setting ProfileIndex
|
|
Stage = Stages<1, ProfileIndex>
|
|
PRSStageKey = PSN:'*':Stage
|
|
PRSStageRec = Database_Services('ReadDataRow', 'PRS_STAGE', PRSStageKey)
|
|
SpecRecipes = PRSStageRec<PRS_STAGE_MET_RECIPE$>
|
|
SpecProfiles = PRSStageRec<PRS_STAGE_MET_TEST$>
|
|
Begin Case
|
|
Case ( (Profile EQ '1THICK_ONLY') and (Stage EQ 'UNLOAD') )
|
|
FailReason = ''
|
|
ThickOutOfSpec = False$
|
|
ToolClassID = Record<WO_MAT_QA_TOOL_CLASS$, ProfileIndex>
|
|
ToolClassRec = Database_Services('ReadDataRow', 'TOOL_CLASS', ToolClassID)
|
|
RecipePattern = Record<WO_MAT_QA_RECIPE_PATTERN$, ProfileIndex>
|
|
RequiredDataPoints = ''
|
|
Locate RecipePattern in ToolClassRec<TOOL_CLASS_PATTERN$> setting rPos then
|
|
RequiredDataPoints = ToolClassRec<TOOL_CLASS_PATTERN_SIZE$, rPos>
|
|
end
|
|
ScanProfile = Profile
|
|
ScanProfile[1,1] = ''
|
|
Locate ScanProfile in SpecProfiles using @VM setting vPos then
|
|
SpecRecipe = SpecRecipes<1, vPos>
|
|
ScanRecipe = ScanRecipes<1, ProfileIndex>
|
|
If ScanRecipe NE SpecRecipe then
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Scanned THICK_ONLY UNLOAD recipe, ':ScanRecipe:', does not match spec ' |
|
|
: 'recipe, ':SpecRecipe:'.'
|
|
end
|
|
end
|
|
SaveList = ''
|
|
ThickSig = Sigs<1, ProfileIndex>
|
|
ThickSigDTM = SigDTMS<1, ProfileIndex>
|
|
ThickSpecMin = SpecMin<1, ProfileIndex>
|
|
ThickSpecMax = SpecMax<1, ProfileIndex>
|
|
ThicknessData = DataPoints<1, ProfileIndex>
|
|
ResAvg = Result<1, ProfileIndex>
|
|
ThicknessDataCount = 0
|
|
For each DataPoint in ThicknessData using @SVM setting ThickIndex
|
|
Until DataPoint EQ ''
|
|
Begin Case
|
|
Case ThickIndex GT 10
|
|
Null
|
|
Case (DataPoint EQ '')
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Thickness data point ':ThickIndex:' is missing.'
|
|
Case (DataPoint GT ThickSpecMax) OR (DataPoint LT ThickSpecMin)
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Thickness data point ':ThickIndex:' is out of bounds.'
|
|
End Case
|
|
SaveList<1, 1, ThickIndex> = DataPoint
|
|
RawThicknessData<1, ThickIndex> = DataPoint
|
|
ThicknessDataCount += 1
|
|
Next DataPoint
|
|
DataPoints<1, ProfileIndex> = SaveList
|
|
|
|
If ThicknessDataCount LT RequiredDataPoints then
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Number of data points is less than the required amount of ' : RequiredDataPoints : '!'
|
|
end
|
|
|
|
If RawThicknessData NE '' then
|
|
Response = QA_Services('CalculateThickData', RawThicknessData)
|
|
ThickAvg = Response<1,1>
|
|
ThickMin = Response<1,2>
|
|
ThickMax = Response<1,3>
|
|
Result<1, ProfileIndex> = ThickAvg
|
|
MinResult<1, ProfileIndex> = ThickMin
|
|
MaxResult<1, ProfileIndex> = ThickMax
|
|
end else
|
|
// Lead/Supervisor/Engineer is overriding the typical workflow and is
|
|
// entering the Thickness average only.
|
|
ThickAvg = ResAvg
|
|
Begin Case
|
|
Case (ThickAvg EQ '')
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Thickness average is missing.'
|
|
Case (ThickAvg GT ThickSpecMax) OR (ThickAvg LT ThickSpecMin)
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'Thickness average is out of bounds.'
|
|
End Case
|
|
end
|
|
If ThickOutOfSpec EQ False$ then
|
|
// Final failure check. Only check if a previous failure reason has not been set as to not
|
|
// ovewrite the previous failure reason.
|
|
If (ThickSig EQ '') or (ThickSigDTM EQ '') then
|
|
ThickOutOfSpec = True$
|
|
FailReason = 'THICK_ONLY UNLOAD product measurement test has not been signed.'
|
|
end
|
|
end
|
|
OutOfSpec<1, ProfileIndex> = ThickOutOfSpec
|
|
FailReasons<1, ProfileIndex> = FailReason
|
|
|
|
Case ( (Profile EQ '1CRES') and (Stage EQ 'UNLOAD') )
|
|
|
|
CresOutOfSpec = False$
|
|
FailReason = ''
|
|
ToolClassID = Record<WO_MAT_QA_TOOL_CLASS$, ProfileIndex>
|
|
ToolClassRec = Database_Services('ReadDataRow', 'TOOL_CLASS', ToolClassID)
|
|
RecipePattern = Record<WO_MAT_QA_RECIPE_PATTERN$, ProfileIndex>
|
|
RequiredDataPoints = ''
|
|
Locate RecipePattern in ToolClassRec<TOOL_CLASS_PATTERN$> setting rPos then
|
|
RequiredDataPoints = ToolClassRec<TOOL_CLASS_PATTERN_SIZE$, rPos>
|
|
end
|
|
ScanProfile = Profile
|
|
ScanProfile[1,1] = ''
|
|
Locate ScanProfile in SpecProfiles using @VM setting vPos then
|
|
SpecRecipe = SpecRecipes<1, vPos>
|
|
ScanRecipe = ScanRecipes<1, ProfileIndex>
|
|
If ScanRecipe NE SpecRecipe then
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Scanned CRES UNLOAD recipe, ':ScanRecipe:', does not match spec ' |
|
|
: 'recipe, ':SpecRecipe:'.'
|
|
end
|
|
end
|
|
SaveList = ''
|
|
CriticalPoints = '1,2,5,6,9'
|
|
CRESSig = Sigs<1, ProfileIndex>
|
|
CRESSigDTM = SigDTMS<1, ProfileIndex>
|
|
HgCVSpecMin = SpecMin<1, ProfileIndex>
|
|
HgCVSpecMax = SpecMax<1, ProfileIndex>
|
|
ThisPhaseMin = SpecPhaseMin<1, ProfileIndex>
|
|
HgCVData = DataPoints<1, ProfileIndex>
|
|
|
|
// Adding Result Average here in the case that a lead manually only enters the averages.
|
|
ResAvg = Result<1, ProfileIndex>
|
|
If ThisPhaseMin EQ '' then
|
|
// Spec Phase Min was not added when the record initially created, so add it here.
|
|
PSN = Xlate('RDS', RDSNo, 'PROD_SPEC_ID', 'X')
|
|
If PSN NE '' then
|
|
PRSStageKey = PSN:'*UNLOAD'
|
|
PRSStageRec = Database_Services('ReadDataRow', 'PRS_STAGE', PRSStageKey)
|
|
MetProps = PRSStageRec<PRS_STAGE_MET_PROP$>
|
|
Locate 'CRES' in MetProps using @VM setting PropPos then
|
|
SpecPhaseMinCol = PRSStageRec<PRS_STAGE_MET_PHASE_MIN$>
|
|
ThisPhaseMin = SpecPhaseMinCol<1, PropPos>
|
|
SpecPhaseMin<1, ProfileIndex> = ThisPhaseMin
|
|
Record<WO_MAT_QA_PHASE_MIN$> = SpecPhaseMin
|
|
end
|
|
end
|
|
end
|
|
ResDataCount = 0
|
|
For each DataPoint in HgCVData using @SVM setting CresIndex
|
|
Until DataPoint EQ ''
|
|
HgCVDataPoint = DataPoint[1, 'F':@TM]
|
|
PhaseDataPoint = DataPoint[-1, 'B':@TM]
|
|
CriticalPoint = Index(CriticalPoints, CresIndex, 1)
|
|
Begin Case
|
|
Case (HgCVDataPoint EQ '') and CriticalPoint
|
|
CresOutOfSpec = True$
|
|
FailReason = 'HgCV data point: ':CresIndex:' is missing data.'
|
|
Case (PhaseDataPoint EQ '') and CriticalPoint
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Phase data point: ':CresIndex:' is missing data.'
|
|
Case (HgCVDataPoint GT HgCVSpecMax) OR (HgCVDataPoint LT HgCVSpecMin) and CriticalPoint
|
|
CresOutOfSpec = True$
|
|
FailReason = 'HgCV data point: ':CresIndex:' is out of bounds.'
|
|
Case (PhaseDataPoint LT ThisPhaseMin) and CriticalPoint
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Phase data point: ':CresIndex:' is out of bounds.'
|
|
End Case
|
|
RawHgCVData<1, CresIndex> = HgCVDataPoint
|
|
RawPhaseData<1, CresIndex> = PhaseDataPoint
|
|
ResDataCount += 1
|
|
Next DataPoint
|
|
If ResDataCount LT RequiredDataPoints then
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Number of data points is less than the required amount of ' : RequiredDataPoints : '!'
|
|
end
|
|
If (RawHgCVData NE '') AND (RawPhaseData NE '') then
|
|
|
|
Response = QA_Services('CalculateHgCVData', RawHgCVData)
|
|
HgCVAvg = Response<1,1>
|
|
HgCVMin = Response<1,2>
|
|
HgCVMax = Response<1,3>
|
|
HgCVEdgeMean = Response<1,4>
|
|
HgCVRangePct = Response<1,5>
|
|
Response = QA_Services('CalculateHgCVData', RawPhaseData)
|
|
PhaseAvg = Response<1,1>
|
|
PhaseMin = Response<1,2>
|
|
PhaseMax = Response<1,3>
|
|
PhaseEdgeMean = Response<1,4>
|
|
PhaseRangePct = Response<1,5>
|
|
DataPoints<1, ProfileIndex> = HgCVData
|
|
Result<1, ProfileIndex> = HgCVAvg : @SVM : PhaseAvg
|
|
MinResult<1, ProfileIndex> = HgCVMin : @SVM : PhaseMin
|
|
MaxResult<1, ProfileIndex> = HgCVMax : @SVM : PhaseMax
|
|
EdgeMeanResult<1, ProfileIndex> = HgCVEdgeMean : @SVM : PhaseEdgeMean
|
|
RangePctResult<1, ProfileIndex> = HgCVRangePct : @SVM : PhaseRangePct
|
|
|
|
end else
|
|
// Lead/Supervisor/Engineer is overriding the typical workflow and is
|
|
// entering the HgCV average and Phase average only.
|
|
HgCVAvg = ResAvg<1, 1, 1>
|
|
PhaseAvg = ResAvg<1, 1, 2>
|
|
Begin Case
|
|
Case (HgCVAvg EQ '')
|
|
CresOutOfSpec = True$
|
|
FailReason = 'HgCV average is missing.'
|
|
Case (PhaseAvg EQ '')
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Phase average is missing.'
|
|
Case (HgCVAvg GT HgCVSpecMax) OR (HgCVAvg LT HgCVSpecMin)
|
|
CresOutOfSpec = True$
|
|
FailReason = 'HgCV is out of bounds.'
|
|
Case (PhaseAvg LT ThisPhaseMin)
|
|
CresOutOfSpec = True$
|
|
FailReason = 'Phase is out of bounds.'
|
|
End Case
|
|
end
|
|
|
|
If CresOutOfSpec EQ False$ then
|
|
// Final failure check. Only check if a previous failure reason has not been set as to not
|
|
// overwrite the previous failure reason.
|
|
If (CRESSig EQ '') or (CRESSigDTM EQ '') then
|
|
CresOutofSpec = True$
|
|
FailReason = 'CRES UNLOAD product measurement test has not been signed.'
|
|
end
|
|
end
|
|
|
|
OutOfSpec<1, ProfileIndex> = CresOutOfSpec
|
|
FailReasons<1, ProfileIndex> = FailReason
|
|
|
|
OrigHgCVAvg = OrigRecord<WO_MAT_QA_RESULT$, ProfileIndex, 1>
|
|
If HgCVAvg NE OrigHgCVAvg then
|
|
Post_Metrology_Manual_Data_Entry_Log(@USER4, 'HgCRes', RDSNo : ' / ' : WorkOrderNo : '*' : CassNo)
|
|
end
|
|
|
|
Case ( (Profile EQ '1LW_RHO') and (Stage EQ 'UNLOAD') )
|
|
|
|
ThisOutOfSpec = False$
|
|
FailReason = ''
|
|
|
|
ThisSig = Sigs<1, ProfileIndex>
|
|
ThisSigDTM = SigDTMS<1, ProfileIndex>
|
|
ThisSpecMin = SpecMin<1, ProfileIndex>
|
|
ThisSpecMax = SpecMax<1, ProfileIndex>
|
|
ThisResult = Result<1, ProfileIndex>
|
|
ThisSpecTest = SpecProfiles<1, ProfileIndex>
|
|
|
|
If ( (ThisResult LT ThisSpecMin) or (ThisResult GT ThisSpecMax) ) then
|
|
ThisOutOfSpec = True$
|
|
FailReason = 'RHO is out of bounds.'
|
|
end
|
|
|
|
If ThisOutOfSpec EQ False$ then
|
|
If (ThisSig EQ '') or (ThisSigDTM EQ '') then
|
|
ThisOutOfSpec = True$
|
|
FailReason = Stage:' ':ThisSpecTest:' product measurement test has not been signed.'
|
|
end
|
|
end
|
|
|
|
OutOfSpec<1, ProfileIndex> = ThisOutOfSpec
|
|
FailReasons<1, ProfileIndex> = FailReason
|
|
|
|
Case Otherwise$
|
|
// This profile & stage do not currently have any specific validation code associated with them.
|
|
// Ensure 'out of spec' flag and 'fail reason' field for this profile are clear.
|
|
OutOfSpec<1, ProfileIndex> = False$
|
|
FailReasons<1, ProfileIndex> = ''
|
|
|
|
End Case
|
|
|
|
Next Profile
|
|
Record<WO_MAT_QA_DATA_POINTS$> = DataPoints
|
|
Record<WO_MAT_QA_RESULT$> = Result
|
|
Record<WO_MAT_QA_MIN_RESULT$> = MinResult
|
|
Record<WO_MAT_QA_MAX_RESULT$> = MaxResult
|
|
Record<WO_MAT_QA_EDGE_MEAN_RESULT$> = EdgeMeanResult
|
|
Record<WO_MAT_QA_RANGE_PCT_RESULT$> = RangePctResult
|
|
Record<WO_MAT_QA_OUT_OF_SPEC$> = OutOfSpec
|
|
Record<WO_MAT_QA_FAIL_REASON$> = FailReasons
|
|
SaveRecord = Record
|
|
end
|
|
|
|
End Case
|
|
return
|
|
|
|
WRITE_RECORD:
|
|
return
|
|
|
|
DELETE_RECORD_PRE:
|
|
return
|
|
|
|
DELETE_RECORD:
|
|
return
|
|
|
|
|
|
// ----- Internal Methods ----------------------------------------------------------------------------------------------
|
|
|
|
Initialize_System_Variables:
|
|
// Save these for restoration later
|
|
SaveDict = @DICT
|
|
SaveID = @ID
|
|
SaveRecord = @RECORD
|
|
OrigFileError = @FILE.ERROR
|
|
|
|
// Now make sure @DICT, ID, and @RECORD are populated
|
|
CurrentDictName = ''
|
|
If @DICT then
|
|
DictHandle = @DICT<1, 2>
|
|
Locate DictHandle in @TABLES(5) Using @FM Setting fPos then
|
|
CurrentDictName = Field(@TABLES(0), @FM, fPos, 1)
|
|
end
|
|
end
|
|
|
|
If CurrentDictName NE DictName then
|
|
Open DictName to @DICT else Status = 'Unable to initialize @DICT'
|
|
end
|
|
|
|
@ID = KeyID
|
|
If Record else
|
|
// Record might not have been passed in. Read the record from the database table just to make sure.
|
|
@FILE.ERROR = ''
|
|
Open TableName to hTable then
|
|
FullFSList = hTable[1, 'F' : @VM]
|
|
BFS = FullFSList[-1, 'B' : @SVM]
|
|
LastHandle = hTable[-1, 'B' : \0D\]
|
|
FileHandle = \0D\ : LastHandle[1, @VM]
|
|
|
|
Call @BFS(READO.RECORD, BFS, FileHandle, KeyID, FMC, Record, ReadOStatus)
|
|
end
|
|
end
|
|
@RECORD = Record
|
|
return
|
|
|
|
Restore_System_Variables:
|
|
Transfer SaveDict to @DICT
|
|
Transfer SaveID to @ID
|
|
Transfer SaveRecord to @RECORD
|
|
@FILE.ERROR = OrigFileError
|
|
return
|
|
|