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 CIHaze = CIRec CIDefects = CIRec 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 = CIRecipes CIRec = CIHaze CIRec = 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 PRSHaze = PRSRec PRSDefects = PRSRec PRSSample = PRSRec 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 = PRSRecipes PRSRec = PRSHaze PRSRec = PRSDefects PRSRec = 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 ThickRecipeFound = False$ RHORecipeFound = False$ Locate 'THICK_ONLY' in MetTests using @VM setting vPos then MetRecipes = PRSStageRec 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 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 = MetRecipes Database_Services('WriteDataRow', 'PRS_STAGE', PRSStageKey, PRSStageRec) end If (RHORecipeFound EQ True$) then MetRecipes<0, vPos> = NewProdRecipe PRSStageRec = 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 ThickRecipeFound = False$ RHORecipeFound = False$ Locate 'THICK_ONLY' in MetTests using @VM setting vPos then MetRecipes = PRSStageRec 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 * 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 = 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 = DevServerName ServiceRec = 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 = KeyId FeatureFlagArray = Rec FeatureFlagArray = Rec 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 = ModifyState FeatureRec = ModifyUser FeatureRec = Datetime() FeatureRec = ModifyState FeatureRec = 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