Function Disposition_Services(@Service, @Params)
/***********************************************************************************************************************

    Name        :   Disposition_Services

    Description :   Handler program for all Disposition services.

    Notes       :   Application errors should be logged using the Error Services module. There are a few methodological
                    assumptions built into way errors are managed which are important to understand in order to properly
                    work with Error Services:

                    - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to
                      the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger
                      this will appear backwards since the originating procedure always appears at the bottom of the
                      list and the current routine appears at the top of the list. We are using this orientation because
                      it is common to refer to the process of calling other procedures as 'drilling down'.

                    - The reason for defining the orientation of the call stack is because Error_Services allows for
                      multiple error conditions to be appended to an original error. In most cases this will happen when
                      a procedure at the bottom of the stack generates an error condition and then returns to its
                      calling procedure. This higher level procedure can optionally add more information relevant to
                      itself. This continues as the call stack 'bubbles' its way back to the top to where the
                      originating procedure is waiting.

                    - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus)
                      preserve their error state until explicitly cleared. This can hinder the normal execution of code
                      since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists.
                      Our philosophy is that error conditions should automatically be cleared before a new procedure
                      is executed to avoid this problem. However, the nature of Basic+ does not make this easy to
                      automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our
                      philosophy then it should include a call into the 'Clear' service request at the top of the
                      program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.)

                    - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any
                      error conditions that were set before.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    Metadata    :

    History     :   (Date, Initials, Notes)
        08/20/20    djs     Original programmer.
														

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler

$insert SERVICE_SETUP
$insert REACT_RUN_EQUATES
$insert WO_WFR_EQUATES
$insert RUN_STAGE_WFR_EQUATES
$insert APP_INSERTS

Declare subroutine  Error_Services, Database_Services, GaN_Services, Disposition_Services  
Declare function    Database_Services, Error_Services, DateTime, GaN_Services

GoToService else
    Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end

Return Response else ''

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//----------------------------------------------------------------------------------------------------------------------
// AutoDispositionRun
//
//
//----------------------------------------------------------------------------------------------------------------------
Service AutoDispositionRun(RDSNo)

    If RDSNo NE '' then
        ReactRunRec = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
        If Error_Services('NoError') then
            InWfrIDs    = ReactRunRec<REACT_RUN_IN_WFR_ID$>
            For each WfrID in InWfrIDs using @VM
                Disposition_Services('AutoDispositionWfr', WfrID)
            Next WfrID
        end
    end
    
end service


//----------------------------------------------------------------------------------------------------------------------
// AutoDispositionWfr
//
//
//----------------------------------------------------------------------------------------------------------------------
Service AutoDispositionWfr(WfrID)

    RDSNo    = Xlate('WO_WFR', WfrID, 'RDS_NO', 'X')
    PSNo     = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X')
    TechType = Xlate('PROD_SPEC', PSNo, 'TECH_TYPE', 'X')
    
    Begin Case
        
        Case TechType EQ 'P'
            // Production
            
            // Update missing and out of spec flags before performing auto disposition.
            GaN_Services('UpdateDataFlags', RDSNo)
            ReactRunRec         = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
            OrigReactRunRec     = ReactRunRec
            NCRFlags            = ReactRunRec<REACT_RUN_NCR_REQ$>
            InWfrIDs            = ReactRunRec<REACT_RUN_IN_WFR_ID$>
            DispFlags           = ReactRunRec<REACT_RUN_WFRS_DISP_READY$>
            Grades              = ReactRunRec<REACT_RUN_CARR_WFR_GRADE$>
            Reasons             = ReactRunRec<REACT_RUN_DISP_REASON$>
            CharFlags           = ReactRunRec<REACT_RUN_CHAR_WFR_FLAG$>
            ShipFlags           = ReactRunRec<REACT_RUN_CARR_WFR_SHIP$>
            CritStages          = ReactRunRec<REACT_RUN_GAN_CRITICAL_STAGES$>
            WfrStages           = ReactRunRec<REACT_RUN_WFR_STAGE$>
            MissingDataFlags    = ReactRunRec<REACT_RUN_DATA_MISSING$>
            OutOfSpecFlags      = ReactRunRec<REACT_RUN_DATA_OUT_OF_SPEC$>
            ValidationDisFlags  = ReactRunRec<REACT_RUN_MISSING_DATA_VALID_DISABLED$>
            ScrapRDS            = ReactRunRec<REACT_RUN_RUN_SCRAPPED$>
            InternalFlags       = ReactRunRec<REACT_RUN_INTERNAL$>
            ExternalFlags       = ReactRunRec<REACT_RUN_EXTERNAL$>
            CharList            = ReactRunRec<REACT_RUN_CHAR_LIST$>
            RDSClosed           = ReactRunRec<REACT_RUN_DISP_COMPLETE$>
            AllWfrsComp         = Gan_Services('ReadyToClose', RDSNo)
            GaNMetStages        = Database_Services('ReadDataRow', 'APP_INFO', 'GAN_MET_STAGES')
            PSNo                = Xlate('REACT_RUN', RDSNo, 'PS_NO', 'X')
            ANKO                = Xlate('PROD_SPEC', PSNo, 'ANKO', 'X')
            
            Locate WfrID in InWfrIDs using @VM setting WaferPos then
                CharFlag = CharFlags<0, WaferPos>
                If CharFlag EQ True$ then
                    
                    // Characterization disposition logic
                    WOWfrRec             = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
                    OrigWOWfrRec         = WOWfrRec
                    ShipFlag             = ShipFlags<0, WaferPos>   
                    NCRNo                = Xlate('WO_WFR', WfrID, 'RDS_NCR_NO', 'X')
                    NCRFlag              = NCRFlags<0, WaferPos>
                    Grade                = WOWfrRec<WO_WFR_GRADE$>
                    Reason               = Reasons<0, WaferPos>
                    CharFlag             = CharFlags<0, WaferPos>
                    DispFlag             = DispFlags<0, WaferPos>
                    MissingDataValidFlag = ValidationDisFlags<0, WaferPos>
                    DataOutOfSpec        = OutOfSpecFlags<0, WaferPos>
                    DataIsMissing        = MissingDataFlags<0, WaferPos>
                    InternalFlag         = InternalFlags<0, WaferPos>
                    ExternalFlag         = ExternalFlags<0, WaferPos>
                    WfrStatus            = WOWfrRec<WO_WFR_STATUS$>
                    MetStatus            = GaN_Services('GetMetrologyStatus', WfrID)
                    CharType             = GaN_Services('GetCharType', WfrID)
                    WfrIsRunning         = GaN_Services('WfrIsRunning', WfrID)
                    
                    If NCRNo NE '' then
                        LossCode  = Xlate('NCR', NCRNo, 'LOSS_CODE', 'X')
                        NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X')
                    end else
                        LossCode  = ''
                        NCRStatus = ''
                    end
                    
                    If ( ( ( (NCRNo NE '') and (LossCode NE 'G24') ) or (ANKO EQ True$) ) and (RDSClosed NE True$) and ( (Grade EQ 'Prod') or (LossCode NE 'G24') ) and (MetStatus EQ True$) ) then
                        // Retain the wafer if it hasn't been retained yet (the service checks this).
                        Gan_Services('RetainWafer', WfrID)
                    end else
                        Gan_Services('ClearRetainInfo', WfrID)                
                    end
                    
                    // Get retain information now in case it has changed by the code block above
                    WOWfrRec   = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
                    RetainBox  = WOWfrRec<WO_WFR_RETAIN_BOX$>
                    RetainSlot = WOWfrRec<WO_WFR_RETAIN_SLOT$>
                    RetainSig  = WOWfrRec<WO_WFR_RETAIN_SIG$>
                    
                    If ( (LossCode EQ 'G19') or (LossCode EQ 'G24') ) then
                        ******** External (G19) or Broken (G24) Characterization Wafer ********
                        InternalFlag = False$
                        ExternalFlag = (LossCode EQ 'G19')                 
                        Grade        = 'Scrap'
                        ShipFlag     = False$
                        If ANKO EQ True$ then
                            NCRFlag = False$
                            DispFlag = ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )
                        end else
                            NCRFlag = True$
                            DispFlag = ( (MetStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )
                        end
                        
                        Begin Case
                            Case MetStatus EQ False$
                                WfrStatus   = 'Metrology is not complete'
                                // Move wafer to next scheduled stage
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                NextStageID = Gan_Services('GetNextStage', WfrID)
                                NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                Gan_Services('MoveWfrToQueue', WfrID, NextLocQ)                   
                            Case ( (NCRNo EQ '') and (ANKO NE True$) )
                                WfrStatus = 'Wafer has not been NCRed'
                                // Move wafer to DISP
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ)                   
                            Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) )
                                WfrStatus = 'NCR has not been closed'
                                // Move wafer to DISP
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                            Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                // Move wafer to DISP
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                            Case DispFlag EQ True$
                                WfrStatus = 'Ready to close'
                                // Move wafer to DISP
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                        End Case
                        
                    end else         
                        ******** Internal Characterization Wafer ********
                        InternalFlag = True$
                        ExternalFlag = False$                    
                        NCRFlag      = False$
                        // Need to look if another wafer has already been characterized.
                        Locate WfrID in CharList using @VM setting CharIndex then
                            If CharIndex EQ 1 then
                                CharReason = 'Internal Characterization (Primary)'
                            end else
                                CharReason = 'Internal Characterization (Secondary)'
                            end
                        end else
                            CharReason = 'Error'
                        end                                  
                        Reason   = CharReason
                        
                        If ( (CharType EQ 'Light') and (NCRNo EQ '') and ( (DataOutOfSpec EQ False$) or (MissingDataValidFlag EQ True$) ) ) then
                            Grade    = 'Prod'
                            If ANKO EQ True$ then
                                ShipFlag = False$
                            end else
                                ShipFlag = True$
                            end
                            DispFlag = ( ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (NCRNo EQ '') or ( (NCRNo NE '') and (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) ) ) )
                        end else
                            // Full characterization or metrology failure
                            Grade      = 'Scrap'
                            ShipFlag   = False$
                            DispFlag   = ( (MetStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )                                 
                        end
                        
                        Begin Case
                            Case WfrIsRunning EQ True$
                                // Move wafer to the tool queue it is running on
                                ToolID = GaN_Services('GetWfrRunTool', WfrID)
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                GaN_Services('MoveWfrToQueue', WfrID, ToolID)
                            Case MetStatus EQ False$
                                WfrStatus = 'Metrology is not complete'
                                // Move wafer to next scheduled stage
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                NextStageID = Gan_Services('GetNextStage', WfrID)
                                NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                Gan_Services('MoveWfrToQueue', WfrID, NextLocQ)   
                            Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                WfrStatus = 'Wafer has not yet been retained'
                                // Move wafer to RETAIN queue if it isn't already there.
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                Gan_Services('MoveWfrToQueue', WfrID, RetainQ) 
                            Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (CharType EQ 'Light') )
                                WfrStatus = 'NCR has not been closed'
                                // Move wafer to DISP queue
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                            Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                // Move wafer to DISP queue
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                            Case DispFlag EQ True$
                                WfrStatus = 'Ready to close'
                                // Move wafer to DISP queue
                                Gan_Services('RemoveWfrFromWIP', WfrID)
                                DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                Gan_Services('MoveWfrToQueue', WfrID, DispQ) 
                        End Case
                        
                    end            
                    
                    NCRFlags<0, WaferPos>        = NCRFlag                                          
                    Reasons<0, WaferPos>         = Reason                                   
                    DispFlags<0, WaferPos>       = DispFlag            
                    ShipFlags<0, WaferPos>       = ShipFlag
                    InternalFlags<0, WaferPos>   = InternalFlag
                    ExternalFlags<0, WaferPos>   = ExternalFlag
                    
                    ReactRunRec<REACT_RUN_NCR_REQ$>          = NCRFlags  
                    ReactRunRec<REACT_RUN_DISP_REASON$>      = Reasons
                    ReactRunRec<REACT_RUN_WFRS_DISP_READY$>  = DispFlags
                    ReactRunRec<REACT_RUN_CARR_WFR_SHIP$>    = ShipFlags                         
                    ReactRunRec<REACT_RUN_INTERNAL$>         = InternalFlags                
                    ReactRunRec<REACT_RUN_EXTERNAL$>         = ExternalFlags
                    
                    WOWfrRec<WO_WFR_GRADE$>       = Grade
                    WOWfrRec<WO_WFR_RETAIN_BOX$>  = RetainBox
                    WOWfrRec<WO_WFR_RETAIN_SLOT$> = RetainSlot
                    WOWfrRec<WO_WFR_STATUS$>      = WfrStatus
                    
                    If (WOWfrRec NE OrigWOWfrRec) then
                        Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$)
                    end
                    
                end else
                    
                    // Non-characterization disposition logic
                    WOWfrRec             = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
                    OrigWOWfrRec         = WOWfrRec
                    ShipFlag             = ShipFlags<0, WaferPos>   
                    NCRNo                = WOWfrRec<WO_WFR_RDS_NCR_NO$>
                    NCRFlag              = NCRFlags<0, WaferPos>
                    CharFlag             = CharFlags<0, WaferPos>
                    DispFlag             = DispFlags<0, WaferPos>
                    Grade                = WOWfrRec<WO_WFR_GRADE$>
                    Reason               = Reasons<0, WaferPos>
                    MissingDataValidFlag = ValidationDisFlags<0, WaferPos>
                    DataOutOfSpec        = OutOfSpecFlags<0, WaferPos>
                    DataIsMissing        = MissingDataFlags<0, WaferPos>
                    WfrStatus            = WOWfrRec<WO_WFR_STATUS$>
                    CriticalFailFlag     = WOWfrRec<WO_WFR_CRITICAL_FAILURE$>
                    DispStatus           = GaN_Services('GetDispStatus', WfrID)
                    
                    If NCRNo NE '' then
                        LossCode  = Xlate('NCR', NCRNo, 'LOSS_CODE', 'X')
                        NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X')
                    end else
                        LossCode  = ''
                        NCRStatus = ''
                    end
                    
                    // Internal Flag - Non-characterized wafers never considered "Internal"
                    InternalFlag = False$
                    ExternalFlag = (LossCode EQ 'G19')
                    
                    If ( ( ( (NCRNo NE '') and (LossCode NE 'G24') ) or (ANKO EQ True$) ) and (RDSClosed NE True$) and (CriticalFailFlag NE True$) and (DispStatus EQ True$) ) then
                        // Retain the wafer if it hasn't been retained yet (the service checks this).
                        Gan_Services('RetainWafer', WfrID)
                    end else
                        Gan_Services('ClearRetainInfo', WfrID)                
                    end
                    
                    // Get retain information now in case it has changed by the code block above
                    WOWfrRec   = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
                    RetainBox  = WOWfrRec<WO_WFR_RETAIN_BOX$>
                    RetainSlot = WOWfrRec<WO_WFR_RETAIN_SLOT$>
                    RetainSig  = WOWfrRec<WO_WFR_RETAIN_SIG$>
                    
                    Begin Case
                        
                        Case CriticalFailFlag EQ True$
                            // Bow and/or warp critical limit exceeded, so the wafer must be
                            // destroyed to prevent damage to candela tools
                            Grade    = 'Scrap'
                            NCRFlag  = True$
                            ShipFlag = False$
                            DispFlag = ( (NCRNo NE '') and (NCRStatus EQ 'C') ) 
                            Reason   = 'Bow and/or warp critical limit exceeded'
                            Begin Case
                                Case ( (NCRNo NE '') and (NCRStatus EQ 'C') )
                                    WOWfrRec<WO_WFR_STATUS$> = 'Ready to close'
                                Case ( (NCRNo NE '') and (NCRStatus NE 'C') )
                                    WOWfrRec<WO_WFR_STATUS$> = 'NCR must be closed'
                                Case NCRNo EQ ''
                                    WOWfrRec<WO_WFR_STATUS$> = 'Wafer requires an NCR'
                            End Case
                            // Move wafer to DISP queue
                            Gan_Services('RemoveWfrFromWIP', WfrID)
                            DispQ = Gan_Services('GetLocQueueID', 'DISP')
                            Gan_Services('MoveWfrToQueue', WfrID, DispQ)        
                            
                        Case ( (LossCode EQ 'G19') or (LossCode EQ 'G24') )
                            ******** External (G19) or Broken (G24) Wafer ********                                              
                            Grade      = 'Scrap'
                            Reason     = '' ; // In this case the reason will come from the NCR instead
                            If ANKO EQ True$ then					    
                                NCRFlag    = False$
                                DispFlag   = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) ) 
                            end else
                                NCRFlag    = True$
                                DispFlag   = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox EQ '') or (RetainSig NE '') ) ) 
                            end 
                            ShipFlag   = False$
                            
                            Begin Case
                                Case DispStatus EQ False$
                                    WfrStatus = 'Metrology is not complete'
                                    // Move wafer to next scheduled stage
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    NextStageID = Gan_Services('GetNextStage', WfrID)
                                    NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                    Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) 
                                Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                    WfrStatus = 'Wafer has not yet been retained'
                                    // Move wafer to RETAIN queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                    Gan_Services('MoveWfrToQueue', WfrID, RetainQ)
                                Case ( (NCRNo EQ '') and (ANKO NE True$) )
                                    WfrStatus = 'Wafer has not been NCRed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) )
                                    WfrStatus = 'NCR has not been closed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                    WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case DispFlag EQ True$
                                    WfrStatus = 'Ready to close'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                            End Case
                            
                        Case ScrapRDS EQ True$
                            // A characterized wafer has failed, so the entire lot must be scrapped                    
                            If ANKO EQ True$ then
                                NCRFlag = False$
                                DispFlag = ( (DispStatus EQ True$) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) )
                            end else
                                NCRFlag = True$
                                DispFlag = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) ) )
                            end
                            Grade    = 'Scrap'
                            Reason   = 'Characterization Failure - OOS'                   
                            // Scrapped lots are not eligible to ship
                            ShipFlag = False$
                            
                            Begin Case
                                Case DispStatus EQ False$
                                    WfrStatus = 'Disposition stage is not complete'
                                    // Move wafer to next scheduled stage
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    NextStageID = Gan_Services('GetNextStage', WfrID)
                                    NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                    Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) 
                                Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                    WfrStatus = 'Wafer has not yet been retained'
                                    // Move wafer to RETAIN queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                    Gan_Services('MoveWfrToQueue', WfrID, RetainQ)
                                Case ( (NCRNo EQ '') and (ANKO NE True$) )
                                    WfrStatus = 'Wafer has not been NCRed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) )
                                    WfrStatus = 'NCR has not been closed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                    WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case DispFlag EQ True$
                                    WfrStatus = 'Ready to close'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                            End Case
                            
                        Case DataOutOfSpec EQ True$
                            // Data out of spec and the RDS has not been scrapped due to characterization failure
                            If ANKO EQ True$ then
                                NCRFlag = False$
                                DispFlag = ( (DispStatus EQ True$) and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )
                            end else
                                NCRFlag = True$
                                DispFlag = ( (DispStatus EQ True$) and (NCRNo NE '') and (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )
                            end
                            Grade    = 'Scrap'
                            Reason   = 'Metrology Failure - OOS'                    
                            // Failed wafers are never eligible to ship
                            ShipFlag = False$
                            
                            Begin Case
                                Case DispStatus EQ False$
                                    WfrStatus = 'Disposition stage is not complete'
                                    // Move wafer to next scheduled stage
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    NextStageID = Gan_Services('GetNextStage', WfrID)
                                    NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                    Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) 
                                Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                    WfrStatus = 'Wafer has not yet been retained'
                                    // Move wafer to RETAIN queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                    Gan_Services('MoveWfrToQueue', WfrID, RetainQ)
                                Case ( (NCRNo EQ '') and (ANKO NE True$) )
                                    WfrStatus = 'Wafer has not been NCRed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (NCRNo NE '') and (NCRStatus NE 'C') and (ANKO NE True$) )
                                    WfrStatus = 'NCR has not been closed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                    WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case DispFlag EQ True$
                                    WfrStatus = 'Ready to close'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                            End Case
                            
                        Case ( (DataOutOfSpec EQ False$) and (NCRNo NE '') )
                            // Data within spec, but wafer manually NCRd                  
                            Grade     = 'Scrap'
                            Reason    = 'NCR'
                            NCRStatus = Xlate('NCR', NCRNo, 'STATUS', 'X')
                            DispFlag  = ( (NCRStatus EQ 'C') and (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) )
                            // NCRd wafers are never eligible to ship
                            ShipFlag  = False$
                            
                            Begin Case
                                Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                    WfrStatus = 'Wafer has not yet been retained'
                                    // Move wafer to RETAIN queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                    Gan_Services('MoveWfrToQueue', WfrID, RetainQ)
                                Case NCRStatus NE 'C'
                                    WfrStatus = 'NCR has not been closed'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                    WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case DispFlag EQ True$
                                    WfrStatus = 'Ready to close'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                            End Case
                            
                        Case DataOutOfSpec EQ False$
                            // Data within spec and the RDS has not been scrapped due to characterization failure
                            NCRFlag   = False$                     
                            If DispStatus EQ True$ then
                                Grade = 'Prod'                        
                            end else
                                Grade = ''
                            end
                            Reason = ''
                            If ANKO EQ True$ then
                                DispFlag  = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox NE '') and (RetainSlot NE '') and (RetainSig NE '') ) )
                                ShipFlag  = False$
                            end else
                                DispFlag  = ( (DispStatus EQ True$) and ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) ) and ( (RetainBox EQ '') or (RetainSig NE '') ) )
                                ShipFlag  = ( (DataIsMissing EQ False$) or (MissingDataValidFlag EQ True$) )
                            end
                            
                            Begin Case
                                Case DispStatus EQ False$
                                    WfrStatus = 'Disposition stage is not complete'
                                    // Move wafer to next scheduled stage
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    NextStageID = Gan_Services('GetNextStage', WfrID)
                                    NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                                    Gan_Services('MoveWfrToQueue', WfrID, NextLocQ) 
                                Case ( ( (RetainBox NE '') or (RetainSlot NE '') ) and (RetainSig EQ '') )
                                    WfrStatus = 'Wafer has not yet been retained'
                                    // Move wafer to RETAIN queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    RetainQ   = Gan_Services('GetLocQueueID', 'RETAIN')
                                    Gan_Services('MoveWfrToQueue', WfrID, RetainQ)
                                Case ( (DataIsMissing EQ True$) and (MissingDataValidFlag NE True$) )
                                    WfrStatus = 'Metrology data is missing and data validation has not been disabled'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                Case DispFlag EQ True$
                                    WfrStatus = 'Ready to close'
                                    // Move wafer to DISP queue
                                    Gan_Services('RemoveWfrFromWIP', WfrID)
                                    DispQ     = Gan_Services('GetLocQueueID', 'DISP')
                                    Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                            End Case
                            
                    End Case
                    
                    NCRFlags<0, WaferPos>        = NCRFlag                                          
                    Reasons<0, WaferPos>         = Reason                                   
                    DispFlags<0, WaferPos>       = DispFlag            
                    ShipFlags<0, WaferPos>       = ShipFlag
                    InternalFlags<0, WaferPos>   = InternalFlag
                    ExternalFlags<0, WaferPos>   = ExternalFlag
                    
                    ReactRunRec<REACT_RUN_NCR_REQ$>          = NCRFlags    
                    ReactRunRec<REACT_RUN_DISP_REASON$>      = Reasons
                    ReactRunRec<REACT_RUN_WFRS_DISP_READY$>  = DispFlags
                    ReactRunRec<REACT_RUN_CARR_WFR_SHIP$>    = ShipFlags                        
                    ReactRunRec<REACT_RUN_INTERNAL$>         = InternalFlags                
                    ReactRunRec<REACT_RUN_EXTERNAL$>         = ExternalFlags
                    
                    WOWfrRec<WO_WFR_GRADE$>       = Grade
                    WOWfrRec<WO_WFR_RETAIN_BOX$>  = RetainBox
                    WOWfrRec<WO_WFR_RETAIN_SLOT$> = RetainSlot
                    WOWfrRec<WO_WFR_STATUS$>      = WfrStatus
                    
                    If (WOWfrRec NE OrigWOWfrRec) then
                        Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$)
                    end
                end
            end            
            
            If ReactRunRec NE OrigReactRunRec then
                Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$)
            end
            
        Case TechType EQ 'E'
            
            // Engineering Run            
            CurrDTM         = DateTime()
            ReactRunRec     = Database_Services('ReadDataRow', 'REACT_RUN', RDSNo)
            OrigReactRunRec = ReactRunRec
            InWfrIDs        = ReactRunRec<REACT_RUN_IN_WFR_ID$>
            ShipFlags       = ReactRunRec<REACT_RUN_CARR_WFR_SHIP$>
            RetainFlags     = ReactRunRec<REACT_RUN_GAN_RET_WFR$>
            InternalFlags   = ReactRunRec<REACT_RUN_INTERNAL$>
            ExternalFlags   = ReactRunRec<REACT_RUN_EXTERNAL$>
            CassDispComp    = ReactRunRec<REACT_RUN_DISP_COMPLETE$>
            WfrsDispReady   = ReactRunRec<REACT_RUN_WFRS_DISP_READY$>
            NCRReqFlags     = ReactRunRec<REACT_RUN_NCR_REQ$>
            CharFlags       = ReactRunRec<REACT_RUN_IN_WFR_CHAR$>
            
            Locate WfrID in InWfrIDs using @VM setting WfrIndex then
                WOWfrRec         = Database_Services('ReadDataRow', 'WO_WFR', WfrID)
                OrigWOWfrRec     = WOWfrRec
                ShipFlag         = ShipFlags<0, WfrIndex>
                RetainFlag       = RetainFlags<0, WfrIndex>
                InternalFlag     = InternalFlags<0, WfrIndex>
                ExternalFlag     = ExternalFlags<0, WfrIndex>
                CharFlag         = CharFlags<0, WfrIndex>
                DispReady        = WfrsDispReady<0, WfrIndex>
                NCRNo            = WOWfrRec<WO_WFR_RDS_NCR_NO$>
                NCRStatus        = Xlate('NCR', NCRNo, 'STATUS', 'X')
                CriticalFailFlag = WOWfrRec<WO_WFR_CRITICAL_FAILURE$>
                NCRReq           = NCRReqFlags<0, WfrIndex>
                DestStatus       = GaN_Services('GetDestroyedStatus', WfrID)
                If ( (CharFlag EQ 'DUMMY') or (CharFlag EQ 'EMPTY') ) then
                    DispReady                               = True$
                    WfrsDispReady<0, WfrIndex>              = DispReady
                    ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                    WOWfrRec<WO_WFR_STATUS$>                = 'Ready to close'
                end
                If DestStatus EQ True$ then                    
                    If ( (InternalFlag NE True$) and (ExternalFlag NE True$) ) then
                        // Mark wafer's internal flag. Clear all other flags.                
                        ShipFlag                                = False$
                        RetainFlag                              = False$
                        InternalFlag                            = True$
                        ExternalFlag                            = False$
                        ShipFlags<0, WfrIndex>                  = ShipFlag
                        RetainFlags<0, WfrIndex>                = RetainFlag 
                        InternalFlags<0, WfrIndex>              = InternalFlag
                        ExternalFlags<0, WfrIndex>              = ExternalFlag
                        ReactRunRec<REACT_RUN_CARR_WFR_SHIP$>   = ShipFlags
                        ReactRunRec<REACT_RUN_GAN_RET_WFR$>     = RetainFlags 
                        ReactRunRec<REACT_RUN_INTERNAL$>        = InternalFlags
                        ReactRunRec<REACT_RUN_EXTERNAL$>        = ExternalFlags
                    end
                end else
                    // Wafer may have been previously marked as external or internal. Since the destroyed status
                    // is now false clear internal and external flag.
                    InternalFlag                          = False$
                    ExternalFlag                          = False$
                    InternalFlags<0, WfrIndex>            = InternalFlag
                    ExternalFlags<0, WfrIndex>            = ExternalFlag 
                    ReactRunRec<REACT_RUN_INTERNAL$>      = InternalFlags
                    ReactRunRec<REACT_RUN_EXTERNAL$>      = ExternalFlags
                end
                
                MetStatus  = GaN_Services('GetMetrologyStatus', WfrID)
                DispStatus = GaN_Services('GetDispStatus', WfrID)
                
                Begin Case
                    Case CriticalFailFlag EQ True$
                        // Bow and/or warp critical limit exceeded, so the wafer must be
                        // destroyed to prevent damage to candela tools                
                        Reason   = 'Bow and/or warp critical limit exceeded'
                        Begin Case
                            Case ( (NCRNo NE '') and (NCRStatus EQ 'C') )
                                WOWfrRec<WO_WFR_STATUS$> = 'Ready to close'
                            Case ( (NCRNo NE '') and (NCRStatus NE 'C') )
                                WOWfrRec<WO_WFR_STATUS$> = 'NCR must be closed'
                            Case NCRNo EQ ''
                                WOWfrRec<WO_WFR_STATUS$> = 'Wafer requires an NCR'
                        End Case
                        DispReady                               = ( (NCRNo NE '') and (NCRStatus EQ 'C') ) 
                        WfrsDispReady<0, WfrIndex>              = DispReady
                        ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                        
                    Case ( (MetStatus EQ True$) or (DispStatus EQ True$) )
                        // Check Ship, Interal, External, and Retain conditions to determine if wafer should be removed from the WIP
                        FormattedWfrID = WfrID
                        Convert '*' to '.' in FormattedWfrID
                        Begin Case
                            Case ShipFlag EQ True$
                                GPackQ = GaN_Services('GetLocQueueID', 'G_PACK')
                                ShipID = ReactRunRec<REACT_RUN_OUT_SLOT_ID$, WfrIndex>
                                RunStageWfrKey = RDSNo:'*DISP*':FormattedWfrID
                                RunStageWfrRec = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                StageStatus    = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                If StageStatus _EQC 'INIT' then
                                    // Mark DISP stage as complete
                                    RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @USER4
                                    RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                    RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                    Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                end
                                Begin Case
                                    Case (ShipID EQ '')
                                        LocQ                     = GaN_Services('GetWfrQueue', WfrID)
                                        WOWfrRec<WO_WFR_STATUS$> = 'Wafer needs to be placed in an outbound cassette'
                                        If LocQ _EQC GPackQ then
                                            // Wafer is being removed from an outbound cassette, so place the wafer back into the G_PACK
                                            // queue and reset the G_PACK RUN_STAGE_WFR record to 'INIT'.
                                            RunStageWfrKey              = RDSNo:'*G_PACK*':FormattedWfrID
                                            RunStageWfrRec              = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                            StageStatus                 = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>                                
                                            If StageStatus _EQC 'COMP' then
                                                RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = ''
                                                RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = ''
                                                RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'INIT'
                                                Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                                Gan_Services('MoveWfrToQueue', WfrID, GPackQ)
                                            end
                                        end else
                                            // Wafer has been marked as shipped in the Disposition Report (Excel spreadsheet), but has
                                            // not yet been added to an outbound cassette. Remove the wafer from its current location
                                            // (which likely is DISP), then place the wafer in the G_PACK location queue and update
                                            // the wafer trace (WO_WFR record).
                                            Gan_Services('RemoveWfrFromWIP', WfrID)
                                            Gan_Services('MoveWfrToQueue', WfrID, GPackQ)
                                            // Update wafer trace (WO_WFR record)
                                            LocDTM                               = WOWfrRec<WO_WFR_LOC_DTM$>
                                            NextPos                              = DCount(LocDTM, @VM) + 1
                                            WOWfrRec<WO_WFR_LOC_DTM$, NextPos>   = CurrDTM
                                            WOWfrRec<WO_WFR_LOC_BY$, NextPos>    = @USER4
                                            WOWfrRec<WO_WFR_LOC_EVENT$, NextPos> = 'COMP'
                                            WOWfrRec<WO_WFR_TOOL_ID$, NextPos>   = ''
                                            WOWfrRec<WO_WFR_INV_LOC$, NextPos>   = GPackQ
                                        end                           
                                    Case ( (ShipID NE '') and ( (CassDispComp EQ False$) or (CassDispComp EQ '') ) )
                                        // Wafer is ready for disposition, so mark it as such. Once user marks the cassette
                                        // disposition complete, then the wafer will move off the WIP. Move wafer to the G_PACK
                                        // location queue if it is not there and update the wafer trace (WO_WFR record).
                                        If (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) then
                                            LocQ = Gan_Services('GetWfrQueue', WfrID)
                                            Gan_Services('RemoveWfrFromWIP', WfrID)
                                            Gan_Services('MoveWfrToQueue', WfrID, GPackQ)
                                            // Update wafer trace (WO_WFR record)
                                            LocDTM   = WOWfrRec<WO_WFR_LOC_DTM$>
                                            NextPos  = DCount(LocDTM, @VM) + 1
                                            WOWfrRec<WO_WFR_LOC_DTM$, NextPos>   = CurrDTM
                                            WOWfrRec<WO_WFR_LOC_BY$, NextPos>    = @USER4
                                            WOWfrRec<WO_WFR_LOC_EVENT$, NextPos> = 'G_PACK'
                                            WOWfrRec<WO_WFR_TOOL_ID$, NextPos>   = ''
                                            WOWfrRec<WO_WFR_INV_LOC$, NextPos>   = GPackQ
                                            WOWfrRec<WO_WFR_STATUS$>             = 'Ready to close'
                                            DispReady = True$
                                            WfrsDispReady<0, WfrIndex> = DispReady
                                            ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                                        end                                                    
                                    Case ( (ShipID NE '') and (CassDispComp EQ True$) )
                                        // A ship ID has been added (i.e. the wafer has been placed in an outbound cassette and the
                                        // user has marked the cassette disposition as complete, so remove the wafer from the 
                                        // GaN WIP and mark the G_PACK stage as complete.)
                                        RunStageWfrKey           = RDSNo:'*G_PACK*':FormattedWfrID
                                        RunStageWfrRec           = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                        StageStatus              = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                        LocQ                     = Gan_Services('GetWfrQueue', WfrID)
                                        WOWfrRec<WO_WFR_STATUS$> = 'Run closed'
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        If StageStatus _EQC 'INIT' then                                
                                            // Mark G_PACK stage as complete
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @USER4
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                            RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                            Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                        end                           
                                    Case Otherwise$
                                        // No action necessary at this time.
                                        Null
                                End Case
                                
                            Case RetainFlag EQ True$
                                
                                RetainSlot      = WOWfrRec<WO_WFR_RETAIN_SLOT$>
                                RetainBox       = WOWfrRec<WO_WFR_RETAIN_BOX$>
                                RetainSig       = WOWfrRec<WO_WFR_RETAIN_SIG$>
                                RetainQ         = GaN_Services('GetLocQueueID', 'RETAIN')
                                RunStageWfrKey  = RDSNo:'*DISP*':FormattedWfrID
                                RunStageWfrRec  = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                StageStatus     = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                If StageStatus _EQC 'INIT' then
                                    // Retain flag has been set and metrology is complete, so mark DISP stage as complete.
                                    RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @User4
                                    RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                    RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                    Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                end
                                Begin Case
                                    
                                    Case ( (RetainSlot EQ '') or (RetainBox EQ '') )
                                        // Wafer needs to go into RETAIN queue until it receives a Retain Slot and Retain Box 
                                        // If wafer is not at RETAIN, then update wafer trace (WO_WFR record) and move the wafer.
                                        WOWfrRec<WO_WFR_STATUS$> = 'Wafer requires a retain box and retain slot'     
                                        CurrStage                = GaN_Services('GetCurrStage', WfrID)
                                        LocQ                     = GaN_Services('GetWfrQueue', WfrID)
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        Gan_Services('MoveWfrToQueue', WfrID, RetainQ)                            
                                        If CurrStage NE 'RETAIN' then                                                       
                                            LocDTM                               = WOWfrRec<WO_WFR_LOC_DTM$>
                                            NextPos                              = DCount(LocDTM, @VM) + 1
                                            WOWfrRec<WO_WFR_LOC_DTM$, NextPos>   = CurrDTM
                                            WOWfrRec<WO_WFR_LOC_BY$, NextPos>    = @USER4
                                            WOWfrRec<WO_WFR_LOC_EVENT$, NextPos> = 'COMP'
                                            WOWfrRec<WO_WFR_TOOL_ID$, NextPos>   = ''
                                            WOWfrRec<WO_WFR_INV_LOC$, NextPos>   = RetainQ
                                        end                               
                                    Case ( (RetainSlot NE '') and (RetainBox NE '') and (CassDispComp NE True$) )
                                        // Wafer is ready for disposition, so mark it as such. Once user marks the cassette
                                        // disposition complete, then the wafer will move off the WIP. Move wafer into RETAIN stage
                                        // if it is not currently there. This can occur if an RDS is opened after being closed.
                                        If ( ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) and (RetainSig NE '') ) then
                                            WOWfrRec<WO_WFR_STATUS$> = 'Ready to close'
                                            DispReady                = True$                                    
                                        end else
                                            WOWfrRec<WO_WFR_STATUS$> = 'Wafer has not yet been retained'
                                            DispReady                = False$
                                        end
                                        RetainQ = 'GCH*Q_RETAIN'
                                        LocQ    = Gan_Services('GetWfrQueue', WfrID)
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        Gan_Services('MoveWfrToQueue', WfrID, RetainQ)                             
                                        LocDTM                                  = WOWfrRec<WO_WFR_LOC_DTM$>
                                        NextPos                                 = DCount(LocDTM, @VM) + 1
                                        WOWfrRec<WO_WFR_LOC_DTM$, NextPos>      = CurrDTM
                                        WOWfrRec<WO_WFR_LOC_BY$, NextPos>       = @USER4
                                        WOWfrRec<WO_WFR_LOC_EVENT$, NextPos>    = 'RETAIN'
                                        WOWfrRec<WO_WFR_TOOL_ID$, NextPos>      = ''
                                        WOWfrRec<WO_WFR_INV_LOC$, NextPos>      = RetainQ
                                        WfrsDispReady<0, WfrIndex>              = DispReady
                                        ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                                    Case ( ( (RetainSlot NE '') and (RetainBox NE '') and (RetainSig NE '') ) and (CassDispComp EQ True$) )
                                        // Retain slot and retain box are populated and the user has marked disposition complete ->
                                        // mark RETAIN stage complete and remove the wafer from the GaN WIP.
                                        RunStageWfrKey           = RDSNo:'*RETAIN*':FormattedWfrID
                                        RunStageWfrRec           = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                        StageStatus              = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                        LocQ                     = Gan_Services('GetWfrQueue', WfrID)
                                        WOWfrRec<WO_WFR_STATUS$> = 'Run closed'
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        If StageStatus _EQC 'INIT' then
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @User4
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                            RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                            Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)                                
                                        end
                                    Case Otherwise$
                                        // No action necessary at this time.
                                        Null
                                        
                                End Case
                                
                            Case InternalFlag EQ True$
                                Begin Case
                                    Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') )                            
                                        // Wafer is ready for disposition, so mark it as such. Once user marks the cassette
                                        // disposition complete, then the wafer will move off the WIP.
                                        DispReady                               = True$
                                        WfrsDispReady<0, WfrIndex>              = DispReady
                                        ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                                        WOWfrRec<WO_WFR_STATUS$>                = 'Ready to close'
                                    Case CassDispComp EQ True$
                                        // Remove the wafer from the GaN WIP and mark DISP stage as complete.         
                                        RunStageWfrKey           = RDSNo:'*DISP*':FormattedWfrID
                                        RunStageWfrRec           = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                        StageStatus              = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>                        
                                        LocQ                     = GaN_Services('GetWfrQueue', WfrID)
                                        WOWfrRec<WO_WFR_STATUS$> = 'Run closed'
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        If StageStatus _EQC 'INIT' then                        
                                            // Mark DISP stage as complete
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @User4
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                            RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                            Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                        end
                                End Case                    
                                
                            Case ExternalFlag EQ True$
                                
                                Begin Case
                                    Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') )
                                        // Check to see if an NCR has been added to this wafer before marking this wafer as ready
                                        // to be dispositioned.
                                        If ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) then
                                            // Wafer is ready for disposition, so mark it as such. Once user marks the cassette
                                            // disposition complete, then the wafer will move off the WIP.
                                            DispReady                               = True$
                                            WfrsDispReady<0, WfrIndex>              = DispReady
                                            ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                                            WOWfrRec<WO_WFR_STATUS$>                = 'Ready to close'
                                        end
                                    Case CassDispComp EQ True$
                                        // Remove the wafer from the GaN WIP and mark DISP stage as complete.
                                        RunStageWfrKey           = RDSNo:'*DISP*':FormattedWfrID
                                        RunStageWfrRec           = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                        StageStatus              = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                        WOWfrRec<WO_WFR_STATUS$> = 'Run closed'                            
                                        LocQ                     = Gan_Services('GetWfrQueue', WfrID)
                                        Gan_Services('RemoveWfrFromWIP', WfrID)                          
                                        If StageStatus _EQC 'INIT' then                        
                                            // Mark DISP stage as complete
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @User4
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                            RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                            Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                        end
                                End Case
                                
                            Case Otherwise$
                                // All flags false. Lot aborted or disposition report not found.
                                Begin Case
                                    Case ( (CassDispComp EQ False$) or (CassDispComp EQ '') )
                                        // Move wafer to DISP queue if it is not there
                                        DispQ = 'GGR*Q_DISP'
                                        CurrQ = Gan_Services('GetWfrQueue', WfrID)
                                        If CurrQ _NEC DispQ then
                                            Gan_Services('RemoveWfrFromWIP', WfrID)
                                            Gan_Services('MoveWfrToQueue', WfrID, DispQ)
                                        end                                                       
                                        // Check to see if an NCR has been added to this wafer before marking this wafer as ready
                                        // to be dispositioned.
                                        If ( (NCRReq EQ False$) or ( (NCRReq EQ True$) and (NCRNo NE '') ) ) then
                                            // Wafer is ready for disposition, so mark it as such. Once user marks the cassette
                                            // disposition complete, then the wafer will move off the WIP.
                                            DispReady                               = True$
                                            WfrsDispReady<0, WfrIndex>              = DispReady
                                            ReactRunRec<REACT_RUN_WFRS_DISP_READY$> = WfrsDispReady
                                            WOWfrRec<WO_WFR_STATUS$>                = 'Ready to close'
                                        end else
                                            If NCRReq EQ True$ then
                                                WOWfrRec<WO_WFR_STATUS$> = 'NCR required'
                                            end else
                                                WOWfrRec<WO_WFR_STATUS$> = 'Disposition report not found'
                                            end
                                        end
                                    Case CassDispComp EQ True$
                                        // Remove the wafer from the GaN WIP and mark DISP stage as complete.
                                        RunStageWfrKey           = RDSNo:'*DISP*':FormattedWfrID
                                        RunStageWfrRec           = Database_Services('ReadDataRow', 'RUN_STAGE_WFR', RunStageWfrKey)
                                        StageStatus              = RunStageWfrRec<RUN_STAGE_WFR_STATUS$>
                                        WOWfrRec<WO_WFR_STATUS$> = 'Run closed'                           
                                        LocQ                     = GaN_Services('GetWfrQueue', WfrID)
                                        Gan_Services('RemoveWfrFromWIP', WfrID)
                                        If StageStatus _EQC 'INIT' then                        
                                            // Mark DISP stage as complete
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_BY$>  = @User4
                                            RunStageWfrRec<RUN_STAGE_WFR_COMP_DTM$> = CurrDTM
                                            RunStageWfrRec<RUN_STAGE_WFR_STATUS$>   = 'COMP'
                                            Database_Services('WriteDataRow', 'RUN_STAGE_WFR', RunStageWfrKey, RunStageWfrRec, True$, False$, True$)
                                        end
                                End Case                                 
                        End Case
                        
                    Case Otherwise$
                        // Metrology or Disposition not complete
                        WOWfrRec<WO_WFR_STATUS$> = 'Metrology incomplete'                        
                        WfrIsRunning             = GaN_Services('WfrIsRunning', WfrID)
                        If WfrIsRunning EQ True$ then
                            // Move wafer to the tool queue it is runnig on
                            ToolID = GaN_Services('GetWfrRunTool', WfrID)
                            Gan_Services('RemoveWfrFromWIP', WfrID)
                            GaN_Services('MoveWfrToQueue', WfrID, ToolID)
                        end else
                            // Move wafer to next scheduled stage
                            Gan_Services('RemoveWfrFromWIP', WfrID)
                            NextStageID = Gan_Services('GetNextStage', WfrID)
                            NextLocQ    = Gan_Services('GetLocQueueID', NextStageID)
                            Gan_Services('MoveWfrToQueue', WfrID, NextLocQ)
                        end
                        
                End Case
                If OrigWOWfrRec NE WOWfrRec then Database_Services('WriteDataRow', 'WO_WFR', WfrID, WOWfrRec, True$, False$, True$)        
            end
            
            If OrigReactRunRec NE ReactRunRec then Database_Services('WriteDataRow', 'REACT_RUN', RDSNo, ReactRunRec, True$, False$, True$)            
            
        Case Otherwise$
            // Error
            Null
    End Case               
    
end service


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ClearCursors:
    For counter = 0 to 8
        ClearSelect counter
    Next counter
return

