Compile function Development_Services(@Service, @Params)
#pragma precomp SRP_PreCompiler

$INSERT SERVICE_SETUP
$INSERT POPUP_EQUATES
$INSERT LOGICAL
$INSERT MSG_EQUATES
$INSERT APPCOLORS
$INSERT WM_IN_EQUATES
$INSERT WM_OUT_EQUATES
$INSERT WO_LOG_EQU
$INSERT WO_STEP_EQU
$INSERT WO_MAT_EQUATES
$INSERT ORDER_EQU
$INSERT RDS_EQUATES
$INSERT PROD_SPEC_EQU
$INSERT NOTIFICATION_EQU
$INSERT LSL_USERS_EQU
$INSERT SECURITY_RIGHTS_EQU
$INSERT RTI_LH_INFO_EQUATES
$INSERT WO_MAT_QA_EQUATES
$INSERT CUST_EPI_PART_EQUATES
$INSERT PRS_STAGE_EQUATES
$INSERT RLIST_EQUATES
$INSERT CLEAN_INSP_EQUATES
$INSERT TOOL_PARMS_EQUATES
$INSERT SERVICES_EQUATES
$INSERT FEATURE_FLAGS_EQUATES

EQU COL$QA_MET_PHASE_MIN TO 17

Equ Tab$                    to \09\
Equ CRLF$                   to \0D0A\
Equ LF$                     to \0A\
Equ Comma$                  to ','

Declare subroutine Set_Property,  Set_Status, ErrMsg, Set_Property, obj_AppWindow, Send_Message, Logging_Services
Declare subroutine Btree.Extract, Send_Event, Security_Err_Msg, Forward_Event, End_Window, Start_Window
Declare subroutine EditCell, obj_NCR, obj_Notes, Post_Event, obj_WO_Mat, obj_WO_Mat_Log, obj_WO_Wfr, obj_Tables, obj_RDS
Declare subroutine Error_Services, RDS_Services, Dialog_Box, Insert, Unlock, QA_Services, Validate, Development_Services
Declare subroutine Update_Index, Database_Services, Messaging_Services
Declare function Get_Property, Get_Status, Popup, Send_Message, Msg, Security_Check, Dialog_Box, RowExists, Utility
Declare function Dialog_Box, obj_WO_Log, obj_NCR, Check_Notes, obj_MUWafers, obj_WO_Mat, Error_Services, RDS_Services
Declare function MemberOf, obj_Tables, obj_RDS, Environment_Services, Logging_Services, Material_Services, ErrMsg
Declare function Work_Order_Services, RetStack, Min, Max, Obj_Prod_Spec, Insert, SRP_Trim, Xlate, Obj_Wo_Mat
Declare function Security_Services, QA_Services, Database_Services, RowExists, Rti_Lh_Info, UNICODE_ANSI, UNICODE_UTF8
Declare function index, Httpclient_Services, SRP_Encode, SRP_Decode, DirList, Obj_Rds_Test, Tool_Parms_Services
Declare function SQL_Services, RDS_Services, Obj_WM_out, Schedule_Services, Obj_Tool, SRP_Sort_Array
Declare function Development_Services, Datetime

GoToService

Return Response or ""

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options PROJECTS        = 'HGCV'

//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------


Service UpdateProdCI()
    
*    ConvRecipes = '6IN_PTYPE ROTR,6IN_THIN ROTR,6IN_THICK ROTR,8IN_THIN ROTR,8IN_THICK ROTR,IFX_ROTR,8IN_IFX_ROTR,' |
*                : 'EPISIL,GEN5_ROTR,AS_IFX_ROTR'
*    FailRecipes = '6IN100_ROTR,6IN100_ROTR,6IN100_ROTR,8IN100_ROTR,8IN100_ROTR,IFX100_ROTR,IFX100_ROTR,EPISIL_100,' |
*                : 'GEN5_100ROTR,AS_IFX100_ROTR'
                
    ConvRecipes   = '6IN_PTYPE ROTR'
    FailRecipes   = '6IN_PTYPE_100'
    RemoveRecipes = '6IN100_ROTR'
    
    Query = "SELECT WO_MAT WITH CURR_STATUS EQ 'REL' OR WITH CURR_STATUS EQ 'VER' OR WITH CURR_STATUS EQ 'UNLOAD' " |
          : "OR WITH CURR_STATUS EQ 'LOAD' OR WITH CURR_STATUS EQ 'NCR' OR WITH CURR_STATUS EQ 'LWIS' OR WITH " |
          : "CURR_STATUS EQ 'LWII' OR WITH CURR_STATUS EQ 'RX' OR WITH CURR_STATUS EQ 'HOLD'"

    GoSub ClearCursors
    Rlist(Query, Target_ActiveList$, '', '', '')
    
    If @RecCount GT 0 then      
        Open 'CLEAN_INSP' to hCI then        
            EOF         = False$
            Loop
                ReadNext KeyID else EOF = True$
                RDSNo = Xlate('WO_MAT', KeyID, 'RDS_NO', 'X')
                If RDSNo GT 200000 and RDSNo LT 900000 then
                    CINo  = Xlate('RDS', RDSNo, 'LWI_CI_NO', 'X')
                    If RowExists('CLEAN_INSP', CINo) then                        
                        Read CIRec from hCI, CINo then
                            CIRecipes = CIRec<CLEAN_INSP_SPEC_SURFSCAN_RECIPE$>
                            CIHaze    = CIRec<CLEAN_INSP_SPEC_SURF_HAZE$>
                            CIDefects = CIRec<CLEAN_INSP_SPEC_SURF_DEFECTS$>
                            For each Recipe in ConvRecipes using ',' setting Pos
                                Locate Recipe in CIRecipes using @VM setting vPos then
                                    Locate Recipe in ConvRecipes using ',' setting rPos then                                
                                        FailRecipe   = Field(FailRecipes, ',', rPos, 1)
                                        RemoveRecipe = Field(RemoveRecipes, ',', rPos, 1)
                                        Locate FailRecipe in CIRecipes using @VM setting fPos then
                                            CIHaze<0, fPos>    = CIHaze<0, vPos>
                                            CIDefects<0, fPos> = CIDefects<0, vPos>
                                        end else
                                            CIRecipes<0, -1>   = FailRecipe
                                            CIHaze<0, -1>      = CIHaze<0, vPos>
                                            CIDefects<0, -1>   = CIDefects<0, vPos>
                                        end
                                        Locate RemoveRecipe in CIRecipes using @VM setting RemPos then
                                            CIRecipes = Delete(CIRecipes, 0, RemPos, 0)
                                            CIHaze    = Delete(CIHaze, 0, RemPos, 0)
                                            CIDefects = Delete(CIDefects, 0, RemPos, 0)
                                        end
                                    end
                                end
                            Next Recipe
                            CIRec<CLEAN_INSP_SPEC_SURFSCAN_RECIPE$> = CIRecipes
                            CIRec<CLEAN_INSP_SPEC_SURF_HAZE$>       = CIHaze
                            CIRec<CLEAN_INSP_SPEC_SURF_DEFECTS$>    = CIDefects
                            Write CIRec on hCI, CINo else
                                ErrMsg('Error updating CLEAN_INSP record ':CINo)
                            end
                        end else
                            ErrMsg('Error reading CLEAN_INSP record ':CINo)
                        end
                    end
                end
            Until EOF
            Repeat
        end
    end
    
end service


Service UpdateROTRPSNs()
    
*    ConvRecipes = '6IN_PTYPE ROTR,6IN_THIN ROTR,6IN_THICK ROTR,8IN_THIN ROTR,8IN_THICK ROTR,IFX_ROTR,8IN_IFX_ROTR,' |
*                : 'EPISIL,GEN5_ROTR,AS_IFX_ROTR'
*    FailRecipes = '6IN100_ROTR,6IN100_ROTR,6IN100_ROTR,8IN100_ROTR,8IN100_ROTR,IFX100_ROTR,IFX100_ROTR,EPISIL_100,' |
*                : 'GEN5_100ROTR,AS_IFX100_ROTR'

    ConvRecipes   = '6IN_PTYPE ROTR'
    FailRecipes   = '6IN_PTYPE_100'
    RemoveRecipes = '6IN100_ROTR'
    
    Pos = ''
    Query = 'SELECT PRS_STAGE WITH STAGE EQ "LWI" AND WITH SURFSCAN_RECIPE CONTAINING '
    For each Recipe in ConvRecipes using ',' setting Pos
        If Pos GT 1 then
            Query := ' OR WITH STAGE EQ "LWI" AND WITH SURFSCAN_RECIPE CONTAINING ':Quote(Recipe)
        end else
            Query := Quote(Recipe)
        end
    Next Recipe
    GoSub ClearCursors
    Rlist(Query, Target_ActiveList$, '', '', '')
    
    If @RecCount GT 0 then      
        Open 'PRS_STAGE' to hPRS then        
            EOF         = False$
            Loop
                ReadNext KeyID else EOF = True$
                Read PRSRec from hPRS, KeyID then
                    PRSRecipes = PRSRec<PRS_STAGE_SURFSCAN_RECIPE$>
                    PRSHaze    = PRSRec<PRS_STAGE_SURF_HAZE$>
                    PRSDefects = PRSRec<PRS_STAGE_SURF_DEFECTS$>
                    PRSSample  = PRSRec<PRS_STAGE_SS_SAMP_QTY$>
                    SampleSize = 25
                    For each Recipe in ConvRecipes using ',' setting Pos
                        Locate Recipe in PRSRecipes using @VM setting vPos then
                            Locate Recipe in ConvRecipes using ',' setting rPos then                                
                                FailRecipe   = Field(FailRecipes, ',', rPos, 1)
                                RemoveRecipe = Field(RemoveRecipes, ',', rPos, 1)
                                Locate FailRecipe in PRSRecipes using @VM setting fPos then
                                    PRSHaze<0, fPos>    = PRSHaze<0, vPos>
                                    PRSDefects<0, fPos> = PRSDefects<0, vPos>
                                    PRSSample<0, fPos>  = SampleSize
                                end else
                                    PRSRecipes<0, -1>   = FailRecipe
                                    PRSHaze<0, -1>      = PRSHaze<0, vPos>
                                    PRSDefects<0, -1>   = PRSDefects<0, vPos>
                                    PRSSample<0, -1>    = SampleSize
                                end
                                Locate RemoveRecipe in PRSRecipes using @VM setting RemPos then
                                    PRSRecipes = Delete(PRSRecipes, 0, RemPos, 0)
                                    PRSHaze    = Delete(PRSHaze, 0, RemPos, 0)
                                    PRSDefects = Delete(PRSDefects, 0, RemPos, 0)
                                    PRSSample  = Delete(PRSSample, 0, RemPos, 0)
                                end
                            end
                        end
                    Next Recipe
                    PRSRec<PRS_STAGE_SURFSCAN_RECIPE$> = PRSRecipes
                    PRSRec<PRS_STAGE_SURF_HAZE$>       = PRSHaze
                    PRSRec<PRS_STAGE_SURF_DEFECTS$>    = PRSDefects
                    PRSRec<PRS_STAGE_SS_SAMP_QTY$>     = PRSSample
                    Write PRSRec on hPRS, KeyID else
                        ErrMsg('Error updating PRS_STAGE SurfScan recipes for record ':KeyID)
                    end
                end else
                    ErrMsg('Error reading PRS_STAGE SurfScan recipes for record ':KeyID)
                end

            Until EOF
            Repeat
        end
    end
    
end service


Service GetProjectStatus(ProjectName=PROJECTS)
    
    // Initialize ProjectStatus to false to be safe.
    ProjectStatus = False$
    ProjectStatus = Xlate('DEVELOPMENT', ProjectName, 'STATUS', 'X')   
    Response = ProjectStatus
    
end service


Service DeployProject(ProjectName=PROJECTS)
    
    ServiceName = 'Deploy':ProjectName
    Development_Services(ServiceName)
    Database_Services('ActivateRecord', 'DEVELOPMENT', ProjectName)
    {STATUS}    = True$
    {START_DTM} = Date():'.':Time()
    {END_DTM}   = ''
    Database_Services('WriteDataRow', 'DEVELOPMENT', ProjectName, @Record)
    
end service


Service RollbackProject(ProjectName=PROJECTS)
    
    ServiceName = 'Rollback':ProjectName
    Development_Services(ServiceName)
    Database_Services('ActivateRecord', 'DEVELOPMENT', ProjectName)
    {STATUS}    = False$
    {END_DTM}   = Date():'.':Time()
    Database_Services('WriteDataRow', 'DEVELOPMENT', ProjectName, @Record)
    
end service


Service DeployHGCV()
    
    ! Get list of work orders in production today.
    SchedEvents = Schedule_Services('GetScheduleEvents', (date() - 7), (date() + 7))
    WOList = ''
    For each Row in SchedEvents using @FM
        ThisWO = Field(Row<1,2>, '*', 1)
        Locate ThisWO in WOList using @VM setting vPos else
            If ThisWO NE '' then WOList<1,-1> = ThisWO
        end
    Next Row

    ! Get list of WO_MAT_QA records in production today.
    Table = 'WO_MAT_QA'
    Open 'DICT.':Table to @DICT then
        Query = 'WO_NO':@VM:WOList:@FM
        KeyList = ''
        Option  = ''
        Flag    = ''
        Btree.Extract(Query, Table, @DICT, KeyList, Option, Flag) 
    end

    Database_Services('WriteDataRow', 'SYSLISTS', 'HGCV_UAT', KeyList, True$, False$, True$)
    
    ! Update UNLOAD PSNs with the new PROD naming convention introduced in the HgCV Project
    ! We have to use a traditional select here because the PRS_STAGE_KEY column does not have a Btree index on it
    Cursor = ''        
    EOF    = False$
    Query  = "SELECT PROD_SPEC WITH PRS_STAGE_KEY CONTAINING 'UNLOAD' AND WITH STATUS EQ 'A'"
    GoSub ClearCursors
    Rlist(Query, Target_ActiveList$, '', '', '')
    Loop
    While EOF EQ False$
        ReadNext PSN else EOF = True$   
        If PSN NE '' then
            PRSStageKey = PSN:'*UNLOAD'
            If RowExists('PRS_STAGE', PRSStageKey) then
                PRSStageRec      = Database_Services('ReadDataRow', 'PRS_STAGE', PRSStageKey)
                MetTests         = PRSStageRec<PRS_STAGE_MET_TEST$>
                ThickRecipeFound = False$
                RHORecipeFound   = False$
                Locate 'THICK_ONLY' in MetTests using @VM setting vPos then
                    MetRecipes       = PRSStageRec<PRS_STAGE_MET_RECIPE$>
                    ThickOnlyRecipe  = MetRecipes<0, vPos>
                    ThickOnlyRecipe  = Trim(ThickOnlyRecipe)
                    ThickRecipeFound = True$
                    NewProdRecipe    = ''
                    Begin Case
                        Case ThickOnlyRecipe EQ 'thin6inch'
                            NewProdRecipe = 'PROD_thin6'
                        Case ThickOnlyRecipe EQ '8inch'
                            NewProdRecipe = 'PROD_8inch'
                        Case ThickOnlyRecipe EQ 'thin8inch'
                            NewProdRecipe = 'PROD_thin8'
                        Case ThickOnlyRecipe EQ 'IRC6in_6mm'
                            NewProdRecipe = 'PROD_IRC6'
                        Case ThickOnlyRecipe EQ 'Wacker'
                            NewProdRecipe = 'PROD_Wack'
                        Case ThickOnlyRecipe EQ '8IN_INF'
                            NewProdRecipe = 'PROD_INF'
                        Case ThickOnlyRecipe EQ '6inTHICK'
                            NewProdRecipe = 'PROD_IRC6'
                        Case ThickOnlyRecipe = 'EP_8IN9PT'
                            NewProdRecipe = 'PROD_8inch'
                        Case Otherwise$
                             // Unexpected THICK_ONLY recipe name -> proceed to next PSN
                             ThickRecipeFound = False$
                    End Case
                end
                
                Locate 'LW_RHO' in MetTests using @VM setting vPos then
                    MetRecipes     = PRSStageRec<PRS_STAGE_MET_RECIPE_PATTERN$>
                    LWRHORecipe    = MetRecipes<0, vPos>
                    LWRHORecipe    = Trim(LWRHORecipe)
                    RHORecipeFound = True$
                    NewProdRecipe  = ''
                    Begin Case
                        Case LWRHORecipe EQ 'IRC6mm'
                            NewProdRecipe = 'PROD_IRC6mm'
                        Case LWRHORecipe EQ '10PT_5mm'
                            NewProdRecipe = 'PROD_10PT_5mm'
                        Case Otherwise$
                             // Unexpected LW_RHO recipe name -> proceed to next PSN
                             RHORecipeFound = False$
                    End Case
                end
                
                If (ThickRecipeFound EQ True$) then
                    MetRecipes<0, vPos> = NewProdRecipe
                    PRSStageRec<PRS_STAGE_MET_RECIPE$> = MetRecipes
                    Database_Services('WriteDataRow', 'PRS_STAGE', PRSStageKey, PRSStageRec)
                end
                
                If (RHORecipeFound EQ True$) then
                    MetRecipes<0, vPos> = NewProdRecipe
                    PRSStageRec<PRS_STAGE_MET_RECIPE_PATTERN$> = MetRecipes
                    Database_Services('WriteDataRow', 'PRS_STAGE', PRSStageKey, PRSStageRec, True$, False$, True$)
                end
            end
        end
    Repeat        
    
    ! Update all WO_MAT_QA records currently in production.
    HgCVList = Database_Services('ReadDataRow', 'SYSLISTS', 'HGCV_UAT')
    
    For each WoMatQAKey in HgCVList using @VM

        Database_Services('ActivateRecord', 'WO_MAT_QA', WoMatQAKey)
        Profiles         = {PROFILE}
        ThickRecipeFound = False$
        RHORecipeFound   = False$
        Locate '1THICK_ONLY' in Profiles using @VM setting vPos then
            ThickPos = vPos
            MetRecipes       = {RECIPE}
            ThickOnlyRecipe  = MetRecipes<0, vPos>
            ThickOnlyRecipe  = Trim(ThickOnlyRecipe)
            ThickRecipeFound = True$
            NewProdRecipe    = ''
            Begin Case
                Case ThickOnlyRecipe EQ 'thin6inch'
                    NewProdRecipe = 'PROD_thin6'
                Case ThickOnlyRecipe EQ '8inch'
                    NewProdRecipe = 'PROD_8inch'
                Case ThickOnlyRecipe EQ 'thin8inch'
                    NewProdRecipe = 'PROD_thin8'
                Case ThickOnlyRecipe EQ 'IRC6in_6mm'
                    NewProdRecipe = 'PROD_IRC6'
                Case ThickOnlyRecipe EQ 'Wacker'
                    NewProdRecipe = 'PROD_Wack'
                Case ThickOnlyRecipe EQ '8IN_INF'
                    NewProdRecipe = 'PROD_INF'
                Case ThickOnlyRecipe EQ '6inTHICK'
                    NewProdRecipe = 'PROD_IRC6'
                Case ThickOnlyRecipe = 'EP_8IN9PT'
                    NewProdRecipe = 'PROD_8inch'
                Case Otherwise$
                     // Unexpected THICK_ONLY recipe name -> proceed to next PSN
                     ThickRecipeFound = False$
            End Case
            
        end
        
        Locate '1LW_RHO' in Profiles using @VM setting vPos then
            RHOPos = vPos
            MetRecipes     = {RECIPE_PATTERN}
            LWRHORecipe    = MetRecipes<0, vPos>
            LWRHORecipe    = Trim(LWRHORecipe)
            RHORecipeFound = True$
            NewProdRecipe  = ''
            Begin Case
                Case LWRHORecipe EQ 'IRC6mm'
                    NewProdRecipe = 'PROD_IRC6mm'
                Case LWRHORecipe EQ '10PT_5mm'
                    NewProdRecipe = 'PROD_10PT_5mm'
                Case Otherwise$
                     // Unexpected 1LW_RHO pattern name -> proceed to next PSN
                     RHORecipeFound = False$
            End Case
        end
        
        If (ThickRecipeFound EQ True$) then
            MetRecipes<0, ThickPos> = NewProdRecipe
            {RECIPE} = MetRecipes
            Database_Services('WriteDataRow', 'WO_MAT_QA', WoMatQAKey, @Record, True$, False$, True$)
        end
        
        If (RHORecipeFound EQ True$) then
            MetRecipes<0, RHOPos> = NewProdRecipe
            {RECIPE_PATTERN} = MetRecipes
            Database_Services('WriteDataRow', 'WO_MAT_QA', WoMatQAKey, @Record, True$, False$, True$)
        end
        
    Next WoMatQAKey
    
End Service


Service RollbackHGCV()
    
    ! Get list of work orders in production today.
    SchedEvents = Schedule_Services('GetScheduleEvents', date(), date())
    WOList = ''
    For each Row in SchedEvents using @FM
        ThisWO = Field(Row<1,2>, '*', 1)
        Locate ThisWO in WOList using @VM setting vPos else
            WOList<1,-1> = ThisWO
        end
    Next Row

    ! Get list of WO_MAT_QA records in production today.
    Table = 'WO_MAT_QA'
    Open 'DICT.':Table to @DICT then
        Query = 'WO_NO':@VM:WOList:@FM
        KeyList = ''
        Option  = ''
        Flag    = ''
        Btree.Extract(Query, Table, @DICT, KeyList, Option, Flag) 
    end

    Database_Services('WriteDataRow', 'SYSLISTS', 'HGCV_UAT', KeyList, True$, False$, True$)
    
    ! Rollback UNLOAD PSNs to their original naming convention (i.e. without 'PROD_')
    ! We have to use a traditional select here because the PRS_STAGE_KEY column does not have a Btree index on it
    Cursor = ''        
    EOF    = False$
    Query  = "SELECT PROD_SPEC WITH PRS_STAGE_KEY CONTAINING 'UNLOAD' AND WITH STATUS EQ 'A'"
    GoSub ClearCursors
    Rlist(Query, Target_ActiveList$, '', '', '')
    Loop
    While EOF EQ False$
        ReadNext PSN else EOF = True$   
        If PSN NE '' then
            PRSStageKey = PSN:'*UNLOAD'
            If RowExists('PRS_STAGE', PRSStageKey) then
                PRSStageRec      = Database_Services('ReadDataRow', 'PRS_STAGE', PRSStageKey)
                MetTests         = PRSStageRec<PRS_STAGE_MET_TEST$>
                ThickRecipeFound = False$
                RHORecipeFound   = False$
                Locate 'THICK_ONLY' in MetTests using @VM setting vPos then
                    MetRecipes       = PRSStageRec<PRS_STAGE_MET_RECIPE$>
                    ThickOnlyRecipe  = MetRecipes<0, vPos>
                    ThickOnlyRecipe  = Trim(ThickOnlyRecipe)
                    ThickRecipeFound = True$
                    NewProdRecipe    = ''
                    Begin Case
                    Case ThickOnlyRecipe EQ 'PROD_thin6'
                        NewProdRecipe = 'thin6inch'
                    Case ThickOnlyRecipe EQ 'PROD_8inch'
                        NewProdRecipe = '8inch'
                    Case ThickOnlyRecipe EQ 'PROD_thin8'
                        NewProdRecipe = 'thin8inch'
                    Case ThickOnlyRecipe EQ 'PROD_IRC6'
                        NewProdRecipe = 'IRC6in_6mm'
                    Case ThickOnlyRecipe EQ 'PROD_Wack'
                        NewProdRecipe = 'Wacker'
                    Case ThickOnlyRecipe EQ 'PROD_INF'
                        NewProdRecipe = '8IN_INF'
                    Case Otherwise$
                         // Unexpected THICK_ONLY recipe name -> proceed to next PSN
                         ThickRecipeFound = False$
                    End Case
                end
                
*                Locate 'LW_RHO' in MetTests using @VM setting vPos then
*                    MetRecipes      = PRSStageRec<PRS_STAGE_MET_RECIPE$>
*                    LWRHORecipe     = MetRecipes<0, vPos>
*                    LWRHORecipe     = Trim(LWRHORecipe)
*                    RHORecipeFound  = True$
*                    NewProdRecipe   = ''
*                    Begin Case
*                        Case LWRHORecipe EQ 'PROD_IRC6mm'
*                            NewProdRecipe = 'IRC6mm'
*                        Case Otherwise$
*                             // Unexpected LW_RHO recipe name -> proceed to next PSN
*                             RHORecipeFound = False$
*                    End Case
*                end
                
                If (ThickRecipeFound EQ True$) then
                    // or (RHORecipeFound EQ True$) then
                    MetRecipes<0, vPos> = NewProdRecipe
                    PRSStageRec<PRS_STAGE_MET_RECIPE$> = MetRecipes
                    Database_Services('WriteDataRow', 'PRS_STAGE', PRSStageKey, PRSStageRec)
                end
                
            end
        end
    Repeat        
    
    ! Revert all WO_MAT_QA records currently in production.
    HgCVList = Database_Services('ReadDataRow', 'SYSLISTS', 'HGCV_UAT')

    For each WoMatQAKey in HgCVList using @VM
        Database_Services('ActivateRecord', 'WO_MAT_QA', WoMatQAKey)
        Profiles         = {PROFILE}
        ThickRecipeFound = False$
        RHORecipeFound   = False$
        Locate '1THICK_ONLY' in Profiles using @VM setting vPos then
            MetRecipes       = {RECIPE}
            ThickOnlyRecipe  = MetRecipes<0, vPos>
            ThickOnlyRecipe  = Trim(ThickOnlyRecipe)
            ThickRecipeFound = True$
            NewProdRecipe    = ''
            Begin Case
                Case ThickOnlyRecipe EQ 'PROD_thin6'
                    NewProdRecipe = 'thin6inch'
                Case ThickOnlyRecipe EQ 'PROD_8inch'
                    NewProdRecipe = '8inch'
                Case ThickOnlyRecipe EQ 'PROD_thin8'
                    NewProdRecipe = 'thin8inch'
                Case ThickOnlyRecipe EQ 'PROD_IRC6'
                    NewProdRecipe = 'IRC6in_6mm'
                Case ThickOnlyRecipe EQ 'PROD_Wack'
                    NewProdRecipe = 'Wacker'
                Case ThickOnlyRecipe EQ 'PROD_INF'
                    NewProdRecipe = '8IN_INF'
                Case Otherwise$
                     // Unexpected THICK_ONLY recipe name -> proceed to next PSN
                     ThickRecipeFound = False$
            End Case                      
        end
        
*        Locate '1LW_RHO' in Profiles using @VM setting vPos then
*            MetRecipes     = {RECIPE}
*            LWRHORecipe    = MetRecipes<0, vPos>
*            LWRHORecipe    = Trim(LWRHORecipe)
*            RHORecipeFound = True$
*            NewProdRecipe  = ''
*            Begin Case
*                Case LWRHORecipe EQ 'PROD_IRC6mm'
*                    NewProdRecipe = 'IRC6mm'
*                Case Otherwise$
*                     // Unexpected 1LW_RHO recipe name -> proceed to next PSN
*                     RHORecipeFound = False$
*            End Case
*        end
        
        If (ThickRecipeFound EQ True$) then
        //or (RHORecipeFound EQ True$) then
            MetRecipes<0, vPos> = NewProdRecipe
            {RECIPE} = MetRecipes
            Database_Services('WriteDataRow', 'WO_MAT_QA', WoMatQAKey, @Record, True$, False$, True$)
        end
        
    Next WoMatQAKey
    
End Service


//----------------------------------------------------------------------------------------------------------------------
// SetupDevServices
//
// This service can be used to setup the development servers services after a restore from production.
// Only the bare necesseties are turned on to prevent individual development instances from potentially stepping
// on each other (e.g. SHARED_TEST and JONATHAN_O instance trying to import a metrology file simultaneously).
//----------------------------------------------------------------------------------------------------------------------
Service SetupDevServices()
    
    DevServerName = Environment_Services('GetServer')
    IsProd        = Environment_Services('IsProd')
    If (IsProd EQ False$) then
    	
		BaselineServices  = 'Update Material Logs':@VM:'Log Transaction Postings':@VM:'Process Wafer Image Queue':@VM
		BaselineServices := 'Process UCL Requests':@VM:'Process ROTR Requests':@VM:'Process Wafer Image Requests':@VM
		BaselineServices := 'Process SQL Requests':@VM:'Send Notes':@VM:'Update Notification Groups':@VM
		BaselineServices := 'Update Security Groups':@VM:'Auto Scheduler'
		
		Query = "SELECT SERVICES"

		GoSub ClearCursors
		Rlist(Query, Target_ActiveList$, '', '', '')
		
		If @RecCount GT 0 then      
			Open 'SERVICES' to hServices then        
				EOF         = False$
				Loop
					ReadNext ServiceName else EOF = True$
					ServiceRec                   = Database_Services('ReadDataRow', 'SERVICES', ServiceName)
					If Error_Services('NoError') then 
						ServiceRec<SERVICES.SERVER$> = DevServerName
						ServiceRec<SERVICES.ACTIVE$> = InList(BaselineServices, ServiceName, @VM)
						Database_Services('WriteDataRow', 'SERVICES', ServiceName, ServiceRec, True$, False$, True$)
					end
				Until EOF
				Repeat
			end
		end
    end
    
end service


Service DeployRoutine(StoredProcNames)

    If StoredProcNames NE '' then
        For each StoredProcName in StoredProcNames using @FM setting fPos
            SysObjKey = '$':StoredProcName:'*LSL2'
            If RowExists('SYSOBJ', SysObjKey) then
                Messaging_Services('SendMessage', 'RunProcedure', 'Request', '', 'All', 'RTP27,':StoredProcName, '', '', '')
            end else
                Error_Services('Add', 'Error in ':Service:' service. Stored procedure ':StoredProcName:' does not exist!')
            end
        Next StoredProcName
    end
    
end service


Service GetFeatureFlagArray()

	FeatureFlagArray = ''
	Open 'FEATURE_FLAGS' to hTable then
		Select hTable
		RowIndex = 0
		EOF      = False$
		Loop
			ReadNext KeyId else EOF = True$
		Until EOF
			RowIndex += 1
			Read Rec from hTable, KeyId then 
				FeatureFlagArray<RowIndex, 1> = KeyId
				FeatureFlagArray<RowIndex, 2> = Rec<FEATURE_FLAGS.FEATURE_DESCRIPTION$>
				FeatureFlagArray<RowIndex, 3> = Rec<FEATURE_FLAGS.ENABLED$>
			end
		Repeat
	end
	Response = FeatureFlagArray
	
end service


Service ChangeFeatureState(FeatureId, ModifyState, ModifyUser, ModifyComment)
	
	ErrorMsg = ''
	If RowExists('FEATURE_FLAGS', FeatureId) then 
		If ( (ModifyState NE '') and (ModifyUser NE '') ) then
			FeatureRec = Database_Services('ReadDataRow', 'FEATURE_FLAGS', FeatureId)
			If Error_Services('NoError') then
				FeatureRec<FEATURE_FLAGS.ENABLED$>            = ModifyState
				FeatureRec<FEATURE_FLAGS.MODIFY_USER$, -1>    = ModifyUser
				FeatureRec<FEATURE_FLAGS.MODIFY_DTM$, -1>     = Datetime()
				FeatureRec<FEATURE_FLAGS.MODIFY_STATE$, -1>   = ModifyState
				FeatureRec<FEATURE_FLAGS.MODIFY_COMMENT$, -1> = ModifyComment
				Database_Services('WriteDataRow', 'FEATURE_FLAGS', FeatureId, FeatureRec, True$, False$, False$)
			end
		end else
			ErrorMsg = 'Error in ':Service:' service. Null ModifyState or ModifyUser passed in.'
		end
	end else
		ErrorMsg = 'Error in ':Service:' service. FEATURE_FLAGS "':FeatureId:'" does not exist!'
	end
	
	If ErrorMsg NE '' then
		Error_Services('Add', ErrorMsg)
		Response = False$
	end else
		Response = True$
	end
	
end service

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

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

