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


