COMPILE FUNCTION obj_WO_Mat_QA(Method,Parms)
/*
	Methods for WO_MAT_QA - WO_MAT QA metrology table
    
	05/5/2015 JCH - Initial Coding
     
    Properties:
     
    Methods:
    
    Convert(WONo)							;* Move metrology data from WO_MAT to WO_MAT_MET table

	
*/
#pragma precomp SRP_PreCompiler


DECLARE SUBROUTINE  Set_Status, Msg, obj_Tables, ErrMsg, Btree.Extract, Database_Services, Logging_Services, PSN_Services

DECLARE FUNCTION Get_Status, Msg, Utility, obj_Tables, Dialog_Box, obj_WO_Log, NextKey, obj_WO_Mat_QA, Environment_Services
DECLARE FUNCTION obj_Prod_Spec, obj_RDS_Test, SRP_Math, Database_Services, Error_Services, Logging_Services

$Insert APP_INSERTS
$INSERT MSG_EQUATES
$INSERT WO_LOG_EQUATES
$INSERT WO_MAT_EQUATES
$INSERT WO_STEP_EQUATES
$INSERT WO_MAT_QA_EQUATES
$INSERT PRS_LAYER_EQUATES
$INSERT PRS_STAGE_EQUATES
$INSERT PROD_VER_EQUATES
$INSERT QA_MET_EQUATES			;* Used in GetQAMet data structure return variable

LogPath    = Environment_Services('GetApplicationRootPath') : '\WO_MAT_QA'; //Define the directory where the log will be saved to. This happens the first time of the day that the log is written to.
LogDate    = Oconv(Date(), 'D4/')
LogTime    = Oconv(Time(), 'MTS')
LoggingDTM = LogDate : ' ' : LogTime   ; // Logging DTM

LogFileName        = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' WO_MAT_QA_Writes.csv'; //Define the file name that will get created.
Headers            = 'Logging DTM' : @FM : 'WOMatKey' : @FM : 'Message'; //Define the column names in the log file, delimited by a Field Mark.
objLogWOMatQAWrite = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$); //Actually creates the log.

ErrTitle = 'Error in Stored Procedure "obj_WO_Mat_QA"'
ErrorMsg = ''

IF NOT(ASSIGNED(Method))	THEN ErrorMsg = 'Unassigned parameter "Method" passed to subroutine'
IF NOT(ASSIGNED(Parms))		THEN Parms = ''

IF ErrorMsg NE '' THEN
    Set_Status(-1,ErrTitle:@SVM:ErrorMsg)
    RETURN ''
END

Result = ''

BEGIN CASE
    CASE Method = 'GetQAMet'			; GOSUB GetQAMet
    CASE Method = 'GetShipDoc'			; GOSUB GetShipDoc
    CASE Method = 'Create'				; GOSUB Create
    CASE Method = 'GetQAMetKeys'		; GOSUB GetQAMetKeys
    CASE Method = 'AddQAMet'			; GOSUB AddQAMet
    CASE Method = 'RemQAMet'			; GOSUB RemQAMet
    CASE Method = 'SetSignature'		; GOSUB SetSignature
    Case Method = 'QAResults'			; Gosub QAResults
        
        
    CASE Method = 'Convert'				; GOSUB Convert
        
    CASE 1
        ErrorMsg = 'Unknown Method ':QUOTE(Method):' passed to routine.'
        
END CASE

IF ErrorMsg NE '' THEN
    Set_Status(-1,ErrTitle:@SVM:ErrorMsg)
    RETURN ''
END

RETURN Result


* * * * * * *
GetQAMet:
* * * * * * *
    
    CassID		= Parms[1,@RM]
    WOMatQARec	= Parms[COL2()+1,@RM]
    WOStep		= Parms[COL2()+1,@RM]
    Stage		= Parms[COL2()+1,@RM]
    MetFields	= Parms[COL2()+1,@RM]
    
    IF CassID = ''	THEN RETURN
    IF WOStep = ''	THEN RETURN
    IF Stage = ''	THEN RETURN
    
    
    IF MetFields = '' THEN
        MetFields  = WO_MAT_QA_PROFILE$:@VM
        MetFields := WO_MAT_QA_STAGE$:@VM
        MetFields := WO_MAT_QA_MIN$:@VM
        MetFields := WO_MAT_QA_MAX$:@VM
        MetFields := WO_MAT_QA_RESULT$:@VM
        MetFields := WO_MAT_QA_SLOT$:@VM
        MetFields := WO_MAT_QA_SIG$:@VM
        MetFields := WO_MAT_QA_SIG_DTM$:@VM
        MetFields := WO_MAT_QA_SLOT_TEST$:@VM
        MetFields := WO_MAT_QA_STD_MAX$:@VM
        MetFields := WO_MAT_QA_STD_RESULT$:@VM
        MetFields := WO_MAT_QA_RECIPE$:@VM
        MetFields := WO_MAT_QA_RECIPE_PATTERN$:@VM
        MetFields := WO_MAT_QA_PROP$:@VM
        MetFields := WO_MAT_QA_TOOL_CLASS$:@VM
        MetFields := WO_MAT_QA_WFR_QTY$:@VM
        MetFields := WO_MAT_QA_WFR_TYPE$:@VM
        MetFields := WO_MAT_QA_SHIP_DOC$
    END
    
    IF WOMatQARec = ''	THEN
        WOMatQARec = XLATE('WO_MAT_QA',CassID,'','X')
        IF WOMatQARec = '' THEN RETURN
    END
    
    MetTests 	= WOMatQARec<WO_MAT_QA_PROFILE$>
    MetStages	= WOMatQARec<WO_MAT_QA_STAGE$>
    
    FieldCnt	= COUNT(MetFields,@VM) + (MetFields NE '')
    MetCnt		= COUNT(MetTests,@VM) + (MetTests NE '')
    
    LineCnt = 1
    Ans = ''
    FOR I = 1 TO MetCnt
        MetWOStep = MetTests<1,I>[1,1]
        
        IF MetWOStep = WOStep  AND WOMatQARec<WO_MAT_QA_STAGE$,I> = Stage THEN
            FOR N = 1 TO FieldCnt
                MetField = MetFields<1,N>
                MetTest = MetTests<1, i>
                Begin Case
                    Case MetField EQ WO_MAT_QA_PROFILE$
                        Ans<N,LineCnt> = WOMatQARec<MetField,I>[2,99]	;* Profile (test) field has stage embedded in the 1st character
                    Case MetField EQ WO_MAT_QA_MIN$     		        
                        MinVal = WOMatQARec<MetField,I>
                        Ans<N,LineCnt> = SRP_Math('ROUND', MinVal, 3)
                    Case MetField EQ WO_MAT_QA_RESULT$ AND Stage EQ 'UNLOAD' AND (MetTest EQ '1CRES' OR MetTest EQ 'CRES')
                        Ans<N,LineCnt> = WOMatQARec<MetField,I, 1>
                    Case Otherwise$
                        Ans<N,LineCnt> = WOMatQARec<MetField,I>
                End Case
                *	     	IF MetField = WO_MAT_QA_PROFILE$ THEN
                *	     		Ans<N,LineCnt> = WOMatQARec<MetField,I>[2,99]	;* Profile (test) field has stage embedded in the 1st character
                *	     	END ELSE
                *				Ans<N,LineCnt> = WOMatQARec<MetField,I>
                *			END
            NEXT N
            LineCnt += 1
        END
    NEXT I
    
    Result = Ans
    
RETURN


* * * * * * *
GetShipDoc:
* * * * * * *
    
    * Returns data for inclusion in documents sent to the customer
    
    WONo	= Parms[1,@RM]
    CassNo 	= Parms[COL2()+1,@RM]
    
    IF WONo = ''		THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    QAMetRec = XLATE('WO_MAT_QA',WONo:'*':CassNo,'','X')
    
    IF QAMetRec = '' THEN RETURN
    
    LineCnt = 0
    IF INDEX(QAMetRec<WO_MAT_QA_SHIP_DOC$>,'1',1) THEN
        TestCnt = COUNT(QAMetRec<WO_MAT_QA_STAGE$>,@VM) + (QAMetRec<WO_MAT_QA_STAGE$> NE '')
        
        FOR I = 1 TO TestCnt
            IF QAMetRec<WO_MAT_QA_SHIP_DOC$,I> = 1 THEN
                LineCnt += 1
                Result<1,LineCnt> = QAMetRec<WO_MAT_QA_PROP$,I>
                Result<2,LineCnt> = QAMetRec<WO_MAT_QA_MIN$,I> 
                Result<3,LineCnt> = QAMetRec<WO_MAT_QA_MAX$,I>
                Result<4,LineCnt> = QAMetRec<WO_MAT_QA_RESULT$,I> 
            END
        NEXT I
        
    END
    
    
RETURN





* * * * * * *
Convert:
* * * * * * *
    
    
    
    
    
RETURN




* * * * * * *
Create:
* * * * * * *
    
    WONo	= Parms[1,@RM]
    CassNo 	= Parms[COL2()+1,@RM]
    
    
    IF WONo = ''		THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    * * * * * * * *   Build QA_MET profile - Work Order scheduled only   * * * * * * * *
    
    WOStepKeys = XLATE('WO_LOG',WONo,WO_LOG_WO_STEP_KEY$,'X')
    
    StepCnt = COUNT(WOStepKeys,@VM) + (WOStepKeys NE '')
    
    EpiProPSNo = ''
    EpiProPSRec = ''
    
    MetLine = 1
    
    WOMatKey   = WONo:'*':CassNo
    WOMatQARec = ''
    WOMatRec   = XLATE('WO_MAT',WOMatKey,'','X')	;* WOMat record used to check for pre-existing signatures jch 6/7/2015
    
    
    FOR WOStepNo = 1 TO StepCnt
        PSNo		= XLATE('WO_STEP',WOStepKeys<1,WOStepNo>,WO_STEP_PROD_SPEC_ID$,'X')
        PSRec 		= XLATE('PROD_SPEC',PSNo,'','X')
        
        QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:PSRec)
        
        QAStages	= QAMetData<COL$QA_MET_STAGE>
        
        StageCnt = COUNT(QAStages,@VM) + (QAStages NE '')
        
        FOR StageNo = 1 TO StageCnt
            Stage = QAMetData<COL$QA_MET_STAGE,StageNo>
            
            MetTest = QAMetData<COL$QA_MET_TEST,StageNo>					;* StageRec<PRS_STAGE_MET_TEST$>
            
            Interval 	= QAMetData<COL$QA_MET_INTERVAL,StageNo>		;* StageRec<PRS_STAGE_MET_INTERVAL$,StageNo>
            Start		= QAMetData<COL$QA_MET_START,StageNo>			;* StageRec<PRS_STAGE_MET_START$,StageNo>
            ReactSched	= QAMetData<COL$QA_MET_REACT_SCHED,StageNo>		;* StageRec<PRS_STAGE_MET_REACT_SCHED$,StageNo>
            
            TestFlag = 0
            
            IF Interval NE '' AND Start NE '' THEN
                IF Interval = Start THEN
                    IF REM(CassNo,Interval) = 0 THEN TestFlag = 1
                END ELSE
                    IF ABS((Start + INT(CassNo/Interval)*Interval) - CassNo) = 0 THEN TestFlag = 1
                END
                IF TestFlag AND NOT(ReactSched) THEN
                    WOMatQARec<WO_MAT_QA_PROFILE$,MetLine>			= WOStepNo:QAMetData<COL$QA_MET_TEST,StageNo>		;* StageRec<PRS_STAGE_MET_TEST$,N>
                    WOMatQARec<WO_MAT_QA_PROP$,MetLine>				= QAMetData<COL$QA_MET_PROP,StageNo>				;* StageRec<PRS_STAGE_MET_PROP$,N>
                    WOMatQARec<WO_MAT_QA_TOOL_CLASS$,MetLine>		= QAMetData<COL$QA_MET_TOOL_CLASS,StageNo>			;* StageRec<PRS_STAGE_MET_TOOL_CLASS$,N>
                    WOMatQARec<WO_MAT_QA_STAGE$,MetLine>			= QAMetData<COL$QA_MET_STAGE,StageNo>
                    WOMatQARec<WO_MAT_QA_MIN$,MetLine>				= QAMetData<COL$QA_MET_MIN,StageNo>					;* StageRec<PRS_STAGE_MET_MIN$,N>
                    WOMatQARec<WO_MAT_QA_MAX$,MetLine>				= QAMetData<COL$QA_MET_MAX,StageNo>					;* StageRec<PRS_STAGE_MET_MAX$,N>
                    WOMatQARec<WO_MAT_QA_SLOT$,MetLine>				= QAMetData<COL$QA_MET_SLOT,StageNo>				;* StageRec<PRS_STAGE_MET_SLOT$,N>
                    WOMatQARec<WO_MAT_QA_RECIPE$,MetLine>			= QAMetData<COL$QA_MET_RECIPE,StageNo>				;* StageRec<PRS_STAGE_MET_RECIPE$,N>
                    WOMatQARec<WO_MAT_QA_RECIPE_PATTERN$,MetLine>	= QAMetData<COL$QA_MET_RECIPE_PATTERN,StageNo>		;* StageRec<PRS_STAGE_MET_RECIPE_PATTERN$,StageNo>
                    WOMatQARec<WO_MAT_QA_WFR_QTY$,MetLine>			= QAMetData<COL$QA_MET_WFR_QTY,StageNo>				;* StageRec<PRS_STAGE_MET_WFR_QTY$,StageNo>
                    WOMatQARec<WO_MAT_QA_WFR_TYPE$,MetLine>			= QAMetData<COL$QA_MET_WFR_TYPE,StageNo>			;* StageRec<PRS_STAGE_MET_WFR_TYPE$,StageNo>
                    WOMatQARec<WO_MAT_QA_REACT_SCHED$,MetLine>		= ReactSched										;* StageRec<PRS_STAGE_MET_REACT_SCHED$,StageNo>
                    WOMatQARec<WO_MAT_QA_SHIP_DOC$,MetLine>			= QAMetData<COL$QA_MET_SHIP_DOC,StageNo>			;* StageRec<PRS_STAGE_MET_SHIP_DOC$,StageNo>
                    WOMatQARec<WO_MAT_QA_PHASE_MIN$,MetLine>		= QAMetData<COL$QA_MET_PHASE_MIN,StageNo>
                    
                    MetTest = QAMetData<COL$QA_MET_TEST,StageNo>
                    IF MetTest = 'ADE' THEN
                        MetSpecSlot = QAMetData<COL$QA_MET_SLOT,StageNo>
                        MetWfrQty   = QAMetData<COL$QA_MET_WFR_QTY,StageNo>
                        IF ( (MetSpecSlot = 'A') OR (MetWfrQty = 'A') OR (MetWfrQty > 5) ) THEN
                            * Standard Deviation Required
                            MetStdMax                      = ((MetMin + MetMax) / 2) * (0.02)
                            MetStdMax                      = ICONV(MetStdMax,'MD3')
                            WOMatQARec<WO_MAT_QA_STD_MAX$> = MetStdMax
                        END
                    END	;* End of check for ADE test					
                    
                    * Retrieve any existing results from the WO_MAT record
                    
                    ProfileKey = WOMatQARec<WO_MAT_QA_PROFILE$,MetLine>
                    
                    LOCATE ProfileKey IN WOMatRec<WO_MAT_MET_PROFILE$> USING @VM SETTING DPos THEN
                        WOMatQARec<WO_MAT_QA_SLOT_TEST$,MetLine>		= WOMatRec<WO_MAT_MET_SLOT_TEST$,DPos>
                        WOMatQARec<WO_MAT_QA_RESULT$,MetLine>			= WOMatRec<WO_MAT_MET_RESULT$,DPos>
                        WOMatQARec<WO_MAT_QA_SIG$,MetLine>				= WOMatRec<WO_MAT_MET_SIG$,DPos>
                        WOMatQARec<WO_MAT_QA_SIG_DTM$,MetLine>			= WOMatRec<WO_MAT_MET_SIG_DTM$,DPos>
                        WOMatQARec<WO_MAT_QA_STD_MAX$,MetLine>			= WOMatRec<WO_MAT_MET_STD_MAX$,DPos>
                        WOMatQARec<WO_MAT_QA_STD_RESULT$,MetLine>		= WOMatRec<WO_MAT_MET_STD_RESULT$,DPos>
                    END ELSE
                        WOMatQARec<WO_MAT_QA_SLOT_TEST$,MetLine>		= ''
                        WOMatQARec<WO_MAT_QA_RESULT$,MetLine>			= ''
                        WOMatQARec<WO_MAT_QA_SIG$,MetLine>				= ''
                        WOMatQARec<WO_MAT_QA_SIG_DTM$,MetLine>			= ''
                        WOMatQARec<WO_MAT_QA_STD_MAX$,MetLine>			= ''
                        WOMatQARec<WO_MAT_QA_STD_RESULT$,MetLine>		= ''
                        
                        
                    END
                    
                    MetLine += 1
                    
                END
            END
            
        NEXT StageNo
        
    NEXT WOStepNo
    Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatKey, WOMatQARec, True$, False$, False$)
    If Error_Services('HasError') then
        ErrorMessage = Error_Services('GetMessage')
        LogData      = ''
        LogData<1>   = LoggingDTM;//Defined at entry of subroutine
        LogData<2>   = WOMatKey
        LogData<3>   = ErrorMessage
        Logging_Services('AppendLog', objLogWOMatQAWrite, LogData, @RM, @FM, False$)
    end
    
    * * * * * * * * * * * * 
    
    
    
    
RETURN



* * * * * * *
GetQAMetKeys:
* * * * * * *
    
    WOMatKey	= Parms[1,@RM]
    WOMatQARec	= Parms[COL2()+1,@RM]
    
    IF WOMatKey = '' THEN RETURN
    IF WOMatQARec = '' THEN
        WOMatQARec = XLATE('WO_MAT_QA',WOMatKey,'','X')
        IF WOMatQARec = '' THEN RETURN
    END
    
    ProdVerNo = XLATE('WO_MAT',WOMatKey,WO_MAT_PROD_VER_NO$,'X')
    
    StepPSNos = XLATE('PROD_VER',ProdVerNo,PROD_VER_PROC_STEP_PSN$,'X')
    
    psCnt = COUNT(StepPSNos,@VM) + (StepPSNos NE '')
    
    LineCnt = 1
    
    FOR I = 1 TO psCNT
        StepPSNo = StepPSNos<1,I>
        
        QAMetStruct = obj_Prod_Spec('GetQAMet',StepPSNo:@RM:'')
        
        msCnt = COUNT(QAMetStruct<COL$QA_MET_STAGE>,@VM) + (QAMetStruct<COL$QA_MET_STAGE> NE '')
        
        FOR N = 1 TO msCnt
            Result<1,LineCnt> = I:'*':QAMetStruct<COL$QA_MET_STAGE,N>:'*':QAMetStruct<COL$QA_MET_PROP,N>
            Result<2,LineCnt> = LineCnt
            LineCnt += 1
        NEXT N
        
    NEXT I
    
RETURN



* * * * * * *
AddQAMet:
* * * * * * *
    
    WONo 				= Parms[1,@RM]
    WOStep				= Parms[COL2()+1,@RM]
    CassNo				= Parms[COL2()+1,@RM]
    Stage				= Parms[COL2()+1,@RM]
    MetTest				= Parms[COL2()+1,@RM]
    MetProp				= Parms[COL2()+1,@RM]
    MetToolClass		= Parms[COL2()+1,@RM]
    MetMin				= Parms[COL2()+1,@RM]
    MetMax				= Parms[COL2()+1,@RM]
    MetSlot				= Parms[COL2()+1,@RM]
    MetRecipe			= Parms[COL2()+1,@RM]
    MetRecipePattern	= Parms[COL2()+1,@RM]
    MetWfrQty			= Parms[COL2()+1,@RM]
    MetWfrType			= Parms[COL2()+1,@RM]
    MetReactSched		= Parms[COL2()+1,@RM]
    MetShipDoc			= Parms[COL2()+1,@RM]
    MetPhaseMin         = Parms[COL2()+1,@RM] ; // 10/15/18 - djs - Added Phase Min Spec for HgCV
    
    IF WONo = ''		THEN ErrorMsg = 'Null Parm "WONo" passed to routine. (':Method:')'
    IF WOStep = ''		THEN ErrorMsg = 'Null Parm "WOStep" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null Parm "CassNo" passed to routine. (':Method:')'
    IF Stage = ''		THEN ErrorMsg = 'Null Parm "Stage" passed to routine. (':Method:')'
    IF MetProp = ''		THEN ErrorMsg = 'Null Parm "MetProp" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    NewMetKey = WOStep:'*':Stage:'*':MetProp
    
    WOMatKey   = WONo:'*':CassNo
    HaveLock   = Database_Services('GetKeyIDLock', 'WO_MAT_QA', WOMatKey, True$)
    If HaveLock then
        WOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey, True$, 0, False$)
        if WOMatQARec NE '' then
            WOMatRec   = XLATE('WO_MAT',WOMatKey,'','X')
            
            AllQAMetKeysStruct	= obj_WO_Mat_QA('GetQAMetKeys',WOMatKey:@RM:WOMatQARec) ;* All QAMetSort Keys Specified for this Work Order  Returns Keys in <1> and Sequence numbers = <2>
            
            AllMetKeys	= AllQAMetKeysStruct<1>		;* Correctly sorted list of all possible QA Met keys built from the PRS_SPEC records for all WO Steps
            AllLines	= AllQAMetKeysStruct<2>		;* List of position numbers for each of the met keys
            
            CurrMetKeys = ''
            CurrLines = ''
            cmqCnt = COUNT(WOMatQARec<WO_MAT_QA_PROFILE$>,@VM) + (WOMatQARec<WO_MAT_QA_PROFILE$> NE '')
            
            FOR M = 1 to cmqCnt
                CurrMetKey			= WOMatQARec<WO_MAT_QA_PROFILE$,M>[1,1]:'*':WOMatQARec<WO_MAT_QA_STAGE$,M>:'*':WOMatQARec<WO_MAT_QA_PROP$,M>
                CurrMetKeys<1,M>	= CurrMetKey
                
                LOCATE CurrMetKey IN AllMetKeys USING @VM SETTING AllPos THEN
                    CurrLines<1,M> = AllPos													;* Builds a list of CurrLines for the Met Keys on the existing WO_MAT records
                END
            NEXT M
            
            LOCATE NewMetKey IN AllMetKeys USING @VM SETTING SpecLine THEN
                
                LOCATE SpecLine IN CurrLines BY 'AR' USING @VM SETTING InsertPos ELSE
                    
                    CurrLines = INSERT(CurrLines,1,InsertPos,0,SpecLine)
                    
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_PROFILE$, InsertPos, 0, WOStep:MetTest)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_PROP$,InsertPos,0,MetProp)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_TOOL_CLASS$, InsertPos, 0, MetToolClass)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_STAGE$, InsertPos, 0, Stage)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_MIN$, InsertPos, 0, MetMin)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_MAX$, InsertPos, 0, MetMax)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SLOT$, InsertPos, 0, MetSlot)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_RECIPE$, InsertPos, 0, MetRecipe)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_RECIPE_PATTERN$, InsertPos, 0, MetRecipePattern)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_WFR_QTY$, InsertPos, 0, MetWfrQty)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_WFR_TYPE$, InsertPos, 0, MetWfrType)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_REACT_SCHED$, InsertPos, 0, MetReactSched)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SHIP_DOC$, InsertPos, 0, MetShipDoc)
                    WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_PHASE_MIN$, InsertPos, 0, MetPhaseMin) ; // 10/15/18 - djs - Added Phase Min Spec for HgCV
                    
                    * Retrieve any existing results from the WO_MAT record
                    
                    ProfileKey = WOMatQARec<WO_MAT_QA_PROFILE$, InsertPos>
                    
                    LOCATE ProfileKey IN WOMatRec<WO_MAT_MET_PROFILE$> USING @VM SETTING DPos THEN
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SLOT_TEST$, InsertPos, 0, WOMatRec<WO_MAT_MET_SLOT_TEST$,DPos> )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_RESULT$, InsertPos, 0, WOMatRec<WO_MAT_MET_RESULT$,DPos> )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SIG$, InsertPos, 0, WOMatRec<WO_MAT_MET_SIG$,DPos> )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SIG_DTM$, InsertPos, 0, WOMatRec<WO_MAT_MET_SIG_DTM$,DPos> )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_STD_MAX$, InsertPos, 0, WOMatRec<WO_MAT_MET_STD_MAX$,DPos> )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_STD_RESULT$, InsertPos, 0, WOMatRec<WO_MAT_MET_STD_RESULT$,DPos> )
                    END ELSE
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SLOT_TEST$, InsertPos, 0, '' )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_RESULT$, InsertPos, 0, '')
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SIG$, InsertPos, 0, '' )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_SIG_DTM$, InsertPos, 0, '' )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_STD_MAX$, InsertPos, 0, '' )
                        WOMatQARec = INSERT(WOMatQARec, WO_MAT_QA_STD_RESULT$, InsertPos, 0, '' )
                    END
                    Database_Services('WriteDataRow', 'WO_MAT_QA', WOMatKey, WOMatQARec, True$, False$, False$)
                    If Error_Services('HasError') then
                        ErrorMessage = Error_Services('GetMessage')
                        LogData      = ''
                        LogData<1>   = LoggingDTM;//Defined at entry of subroutine
                        LogData<2>   = WOMatKey
                        LogData<3>   = ErrorMessage
                        Logging_Services('AppendLog', objLogWOMatQAWrite, LogData, @RM, @FM, False$)
                    end
                END		;* End of SpecLine LOCATE
                
            END 
        end else
            //Record is blank, create new from spec.
            PSN_Services('UpdateAllQAMetrologyRecord', WOMatKey)
        end
        
    end else
        LogData    = ''
        LogData<1> = LoggingDTM;//Defined at entry of subroutine
        LogData<2> = WOMatKey
        LogData<3> = 'Error getting lock on WO_MAT_QA record.'
        Logging_Services('AppendLog', objLogWOMatQAWrite, LogData, @RM, @FM, False$)
    end
    
RETURN



* * * * * * *
RemQAMet:
* * * * * * *
    
    WONo 	= Parms[1,@RM]
    WOStep	= Parms[COL2()+1,@RM]
    CassNo	= Parms[COL2()+1,@RM]
    Stage	= Parms[COL2()+1,@RM]
    PropCd	= Parms[COL2()+1,@RM]
    
    IF WONo = ''		THEN ErrorMsg = 'Null Parm "WONo" passed to routine. (':Method:')'
    IF WOStep = ''		THEN ErrorMsg = 'Null Parm "WOStep" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null Parm "CassNo" passed to routine. (':Method:')'
    IF Stage = ''		THEN ErrorMsg = 'Null Parm "Stage" passed to routine. (':Method:')'
    IF PropCd = ''		THEN ErrorMsg = 'Null Parm "PropCd" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    WOMatKey 	= WONo:'*':CassNo
    otParms		= 'WO_MAT_QA':@RM:WOMatKey
    WOMatQARec	= obj_Tables('ReadRec',otParms)
    
    CurrMetKeys = ''
    
    cmqCnt = COUNT(WOMatQARec<WO_MAT_QA_PROFILE$>,@VM) + (WOMatQARec<WO_MAT_QA_PROFILE$> NE '')
    
    FOR M = 1 to cmqCnt
        CurrMetKey			= WOMatQARec<WO_MAT_QA_PROFILE$,M>[1,1]:'*':WOMatQARec<WO_MAT_QA_STAGE$,M>:'*':WOMatQARec<WO_MAT_QA_PROP$,M>
        CurrMetKeys<1,M>	= CurrMetKey
    NEXT M
    
    DelMetKey = WOStep:'*':Stage:'*':PropCd
    
    LOCATE DelMetKey IN CurrMetKeys USING @VM SETTING DelPos THEN
        
        IF WOMatQARec<WO_MAT_QA_SIG$,DelPos> = '' THEN
            
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_PROFILE$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_PROP$,DelPos,0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_TOOL_CLASS$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_STAGE$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_MIN$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_MAX$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_SLOT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_RECIPE$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_RECIPE_PATTERN$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_SIG$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_SIG_DTM$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_STD_MAX$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_STD_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_WFR_QTY$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_WFR_TYPE$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_REACT_SCHED$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_SHIP_DOC$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_DATA_POINTS$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_MIN_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_MAX_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_RANGE_PCT_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_EDGE_MEAN_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_5MM_PCT_RESULT$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_OUT_OF_SPEC$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_PHASE_MIN$, DelPos, 0)
            WOMatQARec                       = DELETE(WOMatQARec, WO_MAT_QA_FAIL_REASON$, DelPos, 0)
            
            otParms = FIELDSTORE(otParms,@RM,4,0,WOMatQARec)
            obj_Tables('WriteRec',otParms)
            
        END ELSE
            obj_Tables('UnlockRec',otParms)
        END
        
    END ELSE
        obj_Tables('UnlockRec',otParms)
    END
    
    
RETURN


* * * * * * *
SetSignature:
* * * * * * *
    
    WONo		= Parms[1,@RM]
    CassNo		= Parms[COL2()+1,@RM]
    WOStepNo	= Parms[COL2()+1,@RM]
    SigProfKeys	= Parms[COL2()+1,@RM]
    Signatures	= Parms[COL2()+1,@RM]
    SigDTMs		= Parms[COL2()+1,@RM]
    MetResults	= Parms[COL2()+1,@RM]
    Stages		= Parms[COL2()+1,@RM]
    StdMaxs		= Parms[COL2()+1,@RM]
    StdResults	= Parms[COL2()+1,@RM]	;* Added 08/05/2013 JCH
    Slot        = Parms[COL2()+1,@RM]   ;* Added 07/23/2019 DJS
    
    IF WONo = ''		THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
    IF WOStepNo = ''	THEN Errormsg = 'Null parameter "WOStepNo" passed to routine. (':Method:')'
    IF SigProfKeys = ''	THEN ErrorMsg = 'Null parameter "SigProfKeys" passed to routine. (':Method:')'
    IF Signatures = ''	THEN ErrorMsg = 'Null parameter "Signatures" passed to routine. (':Method:')'
    IF SigDTMs = ''		THEN ErrorMsg = 'Null parameter "SigDTMs" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    SigCnt = COUNT(SigProfKeys,@VM) + (SigProfKeys NE '')
    
    FOR I = 1 TO SigCnt
        
        IF SigProfKeys<1,I> = ''	THEN ErrorMsg = 'Null parameter "SigProfKey" passed to routine. (':Method:')'
        
        thisSigDTM = ICONV(SigDTMs<1,I>,'DT') 
        IF thisSigDTM = '' THEN
            *ErrorMsg = 'Invalid SigDTM ':QUOTE(thisSigDTM):' passed to routine. (':Method:')'
        END
        
        IF ErrorMsg NE '' THEN RETURN
        
    NEXT I
    
    
    otParms = 'WO_MAT_QA':@RM:WONo:'*':CassNo
    WOMatQARec = obj_Tables('ReadRec',otParms)
    
    errCode = ''
    IF Get_Status(errCode) THEN
        RETURN
    END
    
    
    ProfSteps = ''
    ProfileCnt = COUNT(WOMatQARec<WO_MAT_QA_PROFILE$>,@VM) + (WOMatQARec<WO_MAT_QA_PROFILE$> NE '')
    
    FOR N = 1 TO ProfileCnt
        ProfSteps<1,N> = WOMatQARec<WO_MAT_QA_PROFILE$,N>:'*':WOMatQARec<WO_MAT_QA_STAGE$,N>
    NEXT N
    
    LastProfSig = WOMatQARec<WO_MAT_QA_PROFILE$,ProfileCnt>
    
    LastBoxSigned = 0
    WriteFlag = 0
    
    FOR I = 1 TO SigCnt
        SigProfKey	= SigProfKeys<1,I>
        Stage		= Stages<1,I>
        
        IF NUM(SigProfKey[1,1]) ELSE
            SigProfKey = WOStepNo:SigProfKey
        END
        
        ProfStep = SigProfKey:'*':Stage	
        
        Found  = False$
        For each ProfStep in ProfSteps using @VM setting vPos
            
            // Use stage, profile, and slot to uniquely identify QA metrology test that is being signed.
            If ( (SigProfKey EQ WOMatQARec<WO_MAT_QA_PROFILE$, vPos>) |
            and  (Stage      EQ WOMatQARec<WO_MAT_QA_STAGE$,   vPos>) |
            and  (Slot       EQ WOMatQARec<WO_MAT_QA_SLOT$,    vPos>) ) then
                // Test found -> Store values and set signature
                Found = True$
                WOMatQARec<WO_MAT_QA_RESULT$,vPos>		= MetResults<1,I>
                WOMatQARec<WO_MAT_QA_STD_MAX$,vPos>		= ICONV(StdMaxs<1,I>,'MD3')
                WOMatQARec<WO_MAT_QA_STD_RESULT$,vPos>	= StdResults<1,I>						;* Added 8/5/2013 JCH
                WOMatQARec<WO_MAT_QA_SIG$,vPos>			= Signatures<1,I>
                WOMatQARec<WO_MAT_QA_SIG_DTM$,vPos>		= ICONV(SigDTMs<1,I>,'DT')
                WriteFlag = 1
            end
            
            *	    Sig    = WOMatQARec<WO_MAT_QA_SIG$,vPos>
            *		SigDTM = WOMatQARec<WO_MAT_QA_SIG_DTM$,vPos>
            *		If Sig EQ '' and SigDTM EQ '' then
            *		    Found = True$
            *		    WOMatQARec<WO_MAT_QA_RESULT$,vPos>		= MetResults<1,I>
            *            WOMatQARec<WO_MAT_QA_STD_MAX$,vPos>		= ICONV(StdMaxs<1,I>,'MD3')
            *            WOMatQARec<WO_MAT_QA_STD_RESULT$,vPos>	= StdResults<1,I>						;* Added 8/5/2013 JCH
            *            WOMatQARec<WO_MAT_QA_SIG$,vPos>			= Signatures<1,I>
            *            WOMatQARec<WO_MAT_QA_SIG_DTM$,vPos>		= ICONV(SigDTMs<1,I>,'DT')
            *            
            *            WriteFlag = 1
            *		end
            
        Until Found EQ True$
        Next ProfStep
        
    NEXT I
    
    IF WriteFlag = 1 THEN
        
        otParms = FieldStore(OtParms,@RM,4,0,WOMatQARec)	;* Put record in 4th field of OtParms
        obj_Tables('WriteRec',otParms)
        
    END ELSE
        obj_Tables('UnlockRec',otParms)
    END
    
RETURN


* * * * * * * *
QAResults:
* * * * * * * * 
    
    * Returns Stage/test/missing or not signed * for incomplete tests
    
    WONo	= Parms[1,@RM]
    WOStep	= Parms[COL2()+1,@RM]
    CassNo 	= Parms[COL2()+1,@RM]
    
    IF WONo = ''		THEN ErrorMsg = 'Null parameter "WONo" passed to routine. (':Method:')'
    If WOStep = ''		Then ErrorMsg = 'Null Parameter "WOStep" passed to routine. (':Method:')'
    IF CassNo = ''		THEN ErrorMsg = 'Null parameter "CassNo" passed to routine. (':Method:')'
    
    IF ErrorMsg NE '' THEN RETURN
    
    WOMatQARec = Xlate('WO_MAT_QA',WONo:'*':CassNo,'','X')
    
    If WOMatQARec = '' Then RETURN
    
    QAProfile = WOMatQARec<WO_MAT_QA_PROFILE$>
    pCnt = Count(QAProfile,@VM) + (QAProfile NE '')
    
    For I = 1 To pCnt
        
        PStep		= QAProfile<1,I>[1,1]
        PTest		= QAProfile<1,I>[2,99]
        TestMin		= WOMatQARec<WO_MAT_QA_MIN$,I>
        TestMax		= WOMatQARec<WO_MAT_QA_MAX$,I>
        TestResult	= WOMatQARec<WO_MAT_QA_RESULT$,I>
        TestSig		= WOMatQARec<WO_MAT_QA_SIG$,I>
        
        
        If PStep = WOStep Then
            Begin Case
                Case TestResult = ''
                    Result = PTest:' at the ':WOMatQARec<WO_MAT_QA_STAGE$,I>:' is incomplete'
                    
                Case TestSig = ''
                    Result = PTest:' at the ':WOMatQARec<WO_MAT_QA_STAGE$,I>:' is unsigned'
                    
                Case TestResult < TestMin Or TestResult > TestMax 
                    Result = PTest:' at the ':WOMatQARec<WO_MAT_QA_STAGE$,I>:' is out of spec'
                    
            End Case 
            
        End ;* End check for Same WOStep
    Next I
    
RETURN

