Compile function Reactor_Log_Services(@Service, @Params)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   Reactor_Log_Services

    Description :   Handler program for all module related services.

    Notes       :   The generic parameters should contain all the necessary information to process the services. Often
                    this will be information like the data Record and Key ID.

    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

    History     :   (Date, Initials, Notes)
        ??/??/??    jro     Original programmer.

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

$Insert APP_INSERTS
$Insert SERVICE_SETUP
$Insert REACTOR_LOG_EQUATES
$Insert RLIST_EQUATES
$Insert REACT_STATE_EQUATES
$Insert REACTOR_PM_EQUATES
$Insert REACT_ITEM_EQUATES
$Insert RDS_EQUATES
$Insert REACT_SERVS_EQUATES
$Insert REACTOR_EQUATES

Declare function   Database_Services, Reactor_Log_Services, Obj_React_Item, Set_Status, Errmsg, Error_Services, Utility
Declare function   obj_Calendar, NextKey, SRP_JSON, Datetime, Reactor_Services, React_Servs_Services, Logging_Services
Declare function   Environment_Services, HttpClient_Services, SRP_List, Nica_Orders_Services
Declare subroutine Set_Status, RList, Errmsg, Database_Services, Error_Services, obj_React_Reads, obj_Post_Log, Delay
Declare subroutine obj_Reactor_Log, Btree.Extract, SRP_JSON, Reactor_Services, Logging_Services, Mona_Services, SRP_List
Declare subroutine Reactor_Log_Services, Nica_Orders_Services

GoToService

Return Response or ""

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN     = True$,False$
Options PM_TYPES    = 'ASM_HTR_TUBE_CHANGE','ASM_HTR_ANNUAL_PM','ASM_HTR_SEMIANNUAL_PM','ASM_HTR_FIVE_AND_TEN_YEAR_PM'

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SERVICES
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Service Create()
	
end service


Service UpdateReactorLog(ReactorLogID, ReactorLogRec)
	
	ErrorMsg = ''
	If ( RowExists('REACTOR_LOG', ReactorLogID) and (ReactorLogRec NE '') ) then
		Database_Services('WriteDataRow', 'REACTOR_LOG', ReactorLogID, ReactorLogRec)
		If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
	end else
		ErrorMsg = 'Error in ':Service:' service. REACTOR_LOG record "':ReactorLogID:'" does not exist!'
	end
	
	If ErrorMsg EQ '' then
		Response = True$
	end else
		Error_Services('Add', ErrorMsg)
		Response = False$
	end
	
	
end service


Service SignReactorLog(ReactorLogID, UserID)
	
	Flag     = ''
	ErrCode  = ''
	ErrorMsg = ''
	If RowExists('REACTOR_LOG', ReactorLogID) then
		// Update any NICA checklist order statuses
		Nica_Orders_Services('GetOrderUpdates')
		If Error_Services('NoError') then 
			If RowExists('LSL_USERS', UserID) then
				ReactorLogRec = Database_Services('ReadDataRow', 'REACTOR_LOG', ReactorLogID)
				If Error_Services('NoError') then
					// Verify NICA checklists are complete
					ActiveRlNicaOrders = Nica_Orders_Services('GetActiveOrders', 'REACTOR_LOG', ReactorLogID)
					If ActiveRLNicaOrders EQ '' then 
						// Verify reactor number is populated
						ReactorNo = ReactorLogRec<REACTOR_LOG_REACTOR$>
						If ReactorNo NE '' then
							// Verify wafer count is populated
							WaferCount = ReactorLogRec<REACTOR_LOG_REACT_WFR_CNT_START$>
							If WaferCount NE '' then								
								//Check if any of the services chosen require a reactor item
								CurrServices = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_REACT_SERV_ID$, 'X')
								CurrItems    = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_REACT_ITEM_IDS$, 'X')
								If CurrServices NE '' then
									for each ServiceID in CurrServices using @VM setting sPos
										If RowExists('REACT_SERVS', ServiceID) then
											ServiceRec = Database_Services('ReadDataRow', 'REACT_SERVS', ServiceID)
											If Error_Services('NoError') then
												ItemReqd = ServiceRec<REACT_SERVS_GRAPHITE_OR_TUBE$>
												If ItemReqd NE '' then
													If CurrItems<1, sPos> NE '' then
														CurrItemID   = CurrItems<1, sPos>
														If RowExists('REACT_ITEM', CurrItemID) then
															CurrReactItemType = XLATE('REACT_ITEM', CurrItemID, REACT_ITEM_RI_TYPE$, 'X')
															If CurrReactItemType NE ItemReqd then
																ErrorMsg = 'React Item ' : CurrItemID : " doesn't match the required react item type!"
															end
														end else
															ErrorMsg = 'React Item ' : CurrItemID : " doesn't exist!"
														end
													end else
														ErrorMsg = 'Service  ' : ServiceID : ' requires an item to be selected and none was selected.' 
													end
												end
											end else
												ErrorMsg = 'Error reading service record for service ID: ' : ServiceID
											end
										end else
											ErrorMsg = 'Invalid service selected! Service ID: ' : ServiceID  
										end
									Until ErrorMsg NE ''
									Next ServiceID
								end
								
								// Check if any react items are missing disposition codes
								If ErrorMsg EQ '' then
									RemRINos   = Xlate('REACTOR_LOG', ReactorLogID, 'REM_RI_NO', 'X')
									If RemRINos NE '' then
										RemRIDispCDs = Xlate('REACTOR_LOG', ReactorLogID, 'REM_DISP_CD', 'X')
										For each RemRINo in RemRINos using @VM setting vPos
											If RemRIDispCDs<0, vPos> EQ '' then
												ErrorMsg = 'Error in ':Service:' service. Disposition for REACT_ITEM ':RemRINo:' being removed has not been completed.'
											end
										Until ErrorMsg NE ''
										Next RemRINo
									end
									AddedRINos = Xlate('REACTOR_LOG', ReactorLogID, 'REACT_ITEM_IDS', 'X')
									If AddedRINos NE '' then
										for each AddedRINo in AddedRINos using @VM
											RIRec = Database_Services('ReadDataRow', 'REACT_ITEM', AddedRINo)
											If RIRec<REACT_ITEM_RETIRE_DT$> NE '' then
												ErrorMsg = 'Error in ':Service:' service. REACT_ITEM ':AddedRINo:' cannot be added because it is RETIRED.'
											end
										Until ErrorMsg NE ''
										Next AddedRINo
									end
								end
								
								If ErrorMsg EQ '' then
									// Check if we need to "post" any items that are being installed
									InstRINo = ReactorLogRec<REACTOR_LOG_INST_RI_NO$>
									If InstRINo NE '' then
										RIPostBy = ReactorLogRec<REACTOR_LOG_RI_POST_BY$>
										If RIPostBy EQ '' then
											obj_Reactor_Log('PostReactItems',ReactorLogID:@RM:UserID)
											// Pull in a fresh copy of the record with the POST_BY signature set
											ReactorLogRec = Database_Services('ReadDataRow', 'REACTOR_LOG', ReactorLogID)
											If Get_Status(ErrCode) then
												ErrorMsg = 'Error in ':Service:' service. Error calling obj_Reactor_Log("PostReactItems"). Error code: ':ErrCode:'.'
											end
										end
									end
									If ErrorMsg EQ '' then
										// Check if we need to create a REACT_READS record
										ReactWfrCntEnd = ReactorLogRec<REACTOR_LOG_REACT_WFR_CNT_END$>
										If ReactWfrCntEnd EQ 0 then
											CurrDTM = obj_Calendar('CurrDTM')
											obj_React_Reads('Create',ReactorNo:@RM:UserID:@RM:CurrDTM:@RM:'0')
											If Get_Status(ErrCode) then
												ErrorMsg = 'Error in ':Service:' service. Error calling obj_React_Reads("Create"). Error code: ':ErrCode:'.'
											end
										end
										If ErrorMsg EQ '' then
											// Check if injector settings have been entered
											ReactInjSetting = ReactorLogRec<REACTOR_LOG_INJ_SETTING$>
											If ReactInjSetting NE '' then
												plParms  = 'REACT_STATE':@RM
												plParms := ReactorNo:@RM
												plParms := REACT_STATE_CURR_INJ_RL_ID$:@RM
												plParms := ReactorLogID:@RM
												obj_Post_Log('Create',plParms)
												If Get_Status(ErrCode) then
													ErrorMsg = 'Error in ':Service:' service. Error calling obj_Post_Log("Create"). Error code: ':ErrCode:'.'
												end
											end
											If ErrorMsg EQ '' then
												// Check reactor prevent maintenance records
												CurServices = ReactorLogRec<REACTOR_LOG_REACT_SERV_ID$>
												
												Loop
													TestChar = CurServices[-1,1]
												Until TestChar NE @VM or CurServices = ''
													CurServices[-1,1] = ''
												Repeat
												
												CCnt = COUNT(CurServices,@VM) + (CurServices NE '')
												
												For N = 1 to CCnt
													CurService = CurServices<1,N>
													
													Open 'REACTOR_PM' to ReactorPMTable then
														
														Open 'DICT.REACTOR_PM' to DictReactorPMTable then
															
															SearchStr	 = 'REACT_SERV_ID':@VM:CurService:@FM
															SearchStr 	:= 'REACTOR':@VM:ReactorNo:@FM
															SearchStr	:= 'COMPLETE_DATE':@VM:'':@FM
															
															Btree.Extract(SearchStr, 'REACTOR_PM', DictReactorPMTable, OpenPMKeys, '', Flag)
															
															If Flag EQ 0 then
																EndDate = Date()
																* Add Maintenance metric reset
																AssocMetrics = ''
																AssocMetrics = React_Servs_Services('GetAssociatedMetrics', CurService)
																If AssocMetrics NE '' then
																	MetricCount = Dcount(AssocMetrics, @VM)
																	For MetricIndex = 1 to MetricCount
																		ThisMetric = AssocMetrics<1,MetricIndex>
																		Reactor_Services('ResetWfrMetric', ReactorNo, ThisMetric) 
																	Next MetricIndex
																End
																If OpenPMKeys NE '' then
																	* If more than one, which should not happen then close all
																	KCnt = COUNT( OpenPMKeys, @VM ) + (OpenPMKeys NE '')
																	PMResched      = False$
																	For I = 1 to KCnt
																		ThisOpenPMKey  = OpenPMKeys<1,I>
																		
																		otlParms       = 'REACTOR_PM':@RM
																		otlParms      := ThisOpenPMKey:@RM
																		otlParms      := REACTOR_PM_COMPLETE_DATE$:@VM:REACTOR_PM_COMP_RL_NO$:@RM
																		otlParms      := EndDate:@VM:ReactorLogID:@RM
																		If ThisOpenPMKey NE '' then
																			obj_Post_Log('Create',otlParms)		;* Closes previous PM record
																			If Not(Get_Status(ErrCode)) then
																				* Schedule next PM 
																				PMDays = XLATE( 'REACT_SERVS', CurService, REACT_SERVS_PM_DAYS$, 'X' )
																				IF PMDays NE '' THEN
																				    If PMResched EQ False$ then
                                                                                        PMNo = NextKey('REACTOR_PM')
                                                                                        If Error_Services('NoError') then
                                                                                            NewPMRec                              = ''
                                                                                            NewPMRec<REACTOR_PM_ENTRY_ID$>        = UserID
                                                                                            NewPMRec<REACTOR_PM_ENTRY_DATE$>      = Date()
                                                                                            NewPMRec<REACTOR_PM_REACTOR$>         = ReactorNo
                                                                                            NewPMRec<REACTOR_PM_PREV_PM_COMP_DT$> = EndDate
                                                                                            NewPMRec<REACTOR_PM_DUE_DT$>          = EndDate + PMDays
                                                                                            NewPMRec<REACTOR_PM_REACT_SERV_ID$>   = CurService
                                                                                            NewPMRec<REACTOR_PM_ENTRY_RL_NO$>     = ReactorLogID
                                                                                            
                                                                                            Database_Services('WriteDataRow', 'REACTOR_PM', PMNo, NewPMRec)
                                                                                            If Error_Services('NoError') then
                                                                                                PMResched = True$
                                                                                            end else
                                                                                               ErrorMsg = Error_Services('GetMessage') 
                                                                                            end
                                                                                        end else
                                                                                            ErrorMsg = 'Error in ':Service:' service. Error calling NextKey("REACTOR_PM").'
                                                                                        end
																					end
																				end
																			end else
																				ErrorMsg = 'Error in ':Service:' service. Error calling obj_Post_Log("Create"). Error code: ':ErrCode
																			end
																		end
																	Next I
																end
															end else
																ErrorMsg = 'Error in ':Service:' serivce. Error calling Btree.Extract. Error code: ':Flag
															end
														end	else
															ErrorMsg = 'Error in ':Service:' service. Error opening DICT.REACTOR_PM table.'
														end
													end else
														ErrorMsg = 'Error in ':Service:' service. Error opening REACTOR_PM table.'
													end
												Next N
											end
										end
									end
								end
							end else
								ErrorMsg = 'Error in ':Service:' service. Wafer count is missing.'
							end
						end else
							ErrorMsg = 'Error in ':Service:' service. Reactor number is missing.'
						end
					end else
						ActiveChecklistTypes  = Xlate('NICA_ORDERS', ActiveRlNicaOrders, 'ORDER_TYPE', 'X')
						Swap @VM with ',' in ActiveChecklistTypes
						ErrorMsg              = 'Error in ':Service:' service. NICA order(s) ':ActiveChecklistTypes
						ErrorMsg             := ' must be completed prior to signing reactor log.'
					end
				end else
					ErrorMsg = Error_Services('GetMessage')
				end
			end else
				ErrorMsg = 'Error in ':Service:' service. LSL_USERS record "':UserID:'" does not exist.'
			end
		end else
			ErrorMsg = Error_Services('GetMessage')
		end
	end else
		ErrorMsg = 'Error in ':Service:' service. REACTOR_LOG record "':ReactorLogID:'" does not exist.'
	end
	
	If ErrorMsg EQ '' then
		// Set signature, end date, and end time
		ReactorLogRec<REACTOR_LOG_TECH_SIG$> = UserID
		ReactorLogRec<REACTOR_LOG_END_DATE$> = Date()
		ReactorLogRec<REACTOR_LOG_END_TIME$> = Time()
		Database_Services('WriteDataRow', 'REACTOR_LOG', ReactorLogID, ReactorLogRec)
		If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
	end
	
	If ErrorMsg EQ '' then
		Response = True$
	end else
		Error_Services('Add', ErrorMsg)
		Response = False$
	end
	
end service


Service ClearSignature(RLKey)
	
	If RLKey NE '' then
		RLRec = Database_Services('ReadDataRow', 'REACTOR_LOG', RLKey)
		If Error_Services('NoError') then
			RLRec<REACTOR_LOG_TECH_SIG$>            = ''
			RLRec<REACTOR_LOG_END_DATE$>            = ''
			RLRec<REACTOR_LOG_END_TIME$>            = ''
			RLRec<REACTOR_LOG_LO_REVIEWED$>         = ''
			RLRec<REACTOR_LOG_LO_NA$>               = ''
			RLRec<REACTOR_LOG_REACT_WFR_CNT_START$> = ''
			Database_Services('WriteDataRow', 'REACTOR_LOG', RLKey, RLRec, True$, False$, False$)
		end
	end
	
end service


Service SaveReactorLogRecord(RLKey, RLRec)
	
	If ( (RLKey NE '') and (RLRec NE '') ) then
		
		ReactNo         = RLRec<REACTOR_LOG_REACTOR$>
		RawReactItemIds = RLRec<REACTOR_LOG_REACT_ITEM_IDS$>
		rawCnt          = COUNT(RawReactItemIds,@VM) + (RawReactItemIds NE '')
		
		InstRINos = ''
		
		FOR I = 1 TO rawCnt
			IF RawReactItemIds<1,I> NE '' THEN
				InstRINos<1,-1> = obj_React_Item('Serial_RINo',RawReactItemIds<1,I>)
			END
		NEXT I
		
		RLRec<REACTOR_LOG_INST_RI_NO$> = InstRINos
		
		* Remove Calculation
		
		PostedBy = RLRec<REACTOR_LOG_RI_POST_BY$>
		
		IF PostedBy = '' THEN
			
			NewRITypes	= XLATE('REACT_ITEM',InstRINos,REACT_ITEM_RI_TYPE$,'X')
			
			CurrRINos   = Xlate('REACTOR_LOG', RLKey, 'CURR_RI_NO', 'X')
			CurrRITypes = Xlate('REACTOR_LOG', RLKey, 'CURR_RI_TYPE', 'X')
			CurrRIDTMs  = Xlate('REACTOR_LOG', RLKey, 'CURR_RI_DTM', 'X')
			
			nRICnt = COUNT(NewRITypes,@VM) + (NewRITypes NE '')
			cRICnt = COUNT(CurrRITypes,@VM) + (CurrRITypes NE '')
			
			RemRINos    = ''
			RemHistKeys = ''
			
			FOR J = 1 TO nRICnt
				NewRIType = NewRITypes<1,J>
				FOR K = 1 TO cRICnt
					CurrRIType = CurrRITypes<1,K>
					IF CurrRIType[1,1] = NewRIType[1,1] THEN
						RemNo      = CurrRINos<0, K>
						RemInstDTM = CurrRIDTMs<0, K>
						RemHistKey = ReactNo:'*':RemNo:'*':RemInstDTM
						
						LOCATE RemNo IN RemRINos USING @VM SETTING Pos ELSE
							RemRINos = INSERT(RemRINos,1,Pos,0,RemNo)
							RemHistKeys = INSERT(RemHistKeys,1,Pos,0,RemHistKey)
						END
					END
				NEXT K	;* End of Curr Loop
			NEXT J	;* End of New Loop
			
			RLRec<REACTOR_LOG_REM_RIH_KEY$> = RemHistKeys
			
		END	;* End of check for NOT Posted
		
		Database_Services('WriteDataRow', 'REACTOR_LOG', RLKey, RLRec)
		
	end
	
end service


Service IsSigned(ReactorLogID)
	
	Response = 0
	If ReactorLogID EQ '' then
		Response = 'Error, null parameter passed for ReactorLogID'
		return;
	end
	
	//Read record
	ReactorLogRec = Database_Services('ReadDataRow', 'REACTOR_LOG', ReactorLogID)
	
	ReactorLogTechSig = ReactorLogRec<REACTOR_LOG_TECH_SIG$>
	If ReactorLogTechSig then
		Response = 1
	end else
		Response = 0
	end
	
End Service


Service IsMaint(ReactorLogID)
	
	Response = 0
	If ReactorLogID EQ '' then
		Response = 'Error, null parameter passed for ReactorLogID'
		return;
	end
	
	//Read record
	ReactorLogRec = Database_Services('ReadDataRow', 'REACTOR_LOG', ReactorLogID)
	
	ReactorLogCategory = ReactorLogRec<REACTOR_LOG_CATEGORY$>
	If ReactorLogCategory EQ 'M' then
		Response = 1
	end else
		Response = 0
	end
	
End Service


Service GetLogsByReactor(ReactNo)
	
	ReactLogList = ''
	SelectSent  = 'SELECT REACTOR_LOG WITH REACTOR EQ ': ReactNo : ' AND WITH START_DATE GT ' : Date() - 5475 : ' BY-DSND START_DATE'
	
	Set_Status(0)
	RList(SelectSent, TARGET_ACTIVELIST$, "", "", "")
	IF Get_Status(errCode) THEN
		ErrMsg(errCode)
		Response = 0
		RETURN
	END
	IF @RecCount then
		EoF = 0
		NumKeys = @RecCount
		Cnt = 0
		
		Loop
			ReadNext log Else EoF = 1
		until EoF
			ReactLogList := log : @FM
		Repeat
		
	end
	//to here
	GoSub ClearCursors
	ClearSelect TARGET_ACTIVELIST$
	Response = ReactLogList
	
end service


Service GetLogsByReactorAndServID(ReactNo, ServID)

	ServicesPerformed = ''
	
	ServiceList = Reactor_Log_Services('GetLogsByReactor', ReactNo)
	for each rlKey in ServiceList using @FM
		ServiceIDs = XLATE('REACTOR_LOG', rlKey, 18, 'X')
		
		for each ServiceID in ServiceIDs using @VM
			If ServiceID EQ ServID then
				Date = XLATE('REACTOR_LOG', rlKey, 'END_DTM', 'X')
				ServiceDesc = XLATE('REACT_SERVS', ServiceID, 1, 'X')
				ReactItemID = ''
				RLServIDs = XLATE('REACTOR_LOG', rlKey, 18, 'X')
				RLSerialNos = XLATE('REACTOR_LOG', rlKey, 15, 'X')
				RLReactItemIDs = obj_React_Item('Serial_RINo',RLSerialNos)
				Locate ServiceID in RLServIDs using @VM setting ServPos then
					ReactItemID = RLReactItemIDs<1,ServPos>
				end
				ServicesPerformed := ServiceID : @VM : ServiceDesc : @VM: OCONV(Date, 'D4/') : @VM : rlKey : @VM : ReactItemID : @FM
			end 
		Next ServiceID
	Next rlKey
	response = ServicesPerformed
	
end service


Service GetLatestReactorLogsByReactor(ReactNo)
	
	ServicesPerformed = ''
	
	ServiceList = Reactor_Log_Services('GetLogsByReactor', ReactNo)
	//FoundResults = ''
	
	for each rlKey in ServiceList using @FM
		ServiceIDs = XLATE('REACTOR_LOG', rlKey, 18, 'X')
		
		for each ServiceID in ServiceIDs using @VM
			Date = XLATE('REACTOR_LOG', rlKey, 'END_DTM', 'X')
			ServiceDesc = XLATE('REACT_SERVS', ServiceID, 1, 'X')
			ReactItemID = ''
			RLServIDs = XLATE('REACTOR_LOG', rlKey, 18, 'X')
			RLSerialNos = XLATE('REACTOR_LOG', rlKey, 15, 'X')
			RLReactItemIDs = obj_React_Item('Serial_RINo',RLSerialNos)
			Locate ServiceID in RLServIDs using @VM setting ServPos then
				ReactItemID = RLReactItemIDs<1,ServPos>
			end
			ReactItemSN = XLATE('REACT_ITEM', ReactItemID, 10, 'X')
			ServicesPerformed := ServiceID : @VM : rlKey : @VM : ServiceDesc : @VM: OCONV(Date, 'D4/') : @VM: ReactItemID : @FM
		Next ServiceID
	Next rlKey
	//remove duplicates
	sortIndex = ''
	existingServIDs = ''
	SortedArray = ''
	for ServiceIndex = 1 to DCOUNT(ServicesPerformed, @FM)
		LOCATE ServicesPerformed<ServiceIndex, 1> IN existingServIDs using @FM setting DUMMY else
			SortedArray := ServicesPerformed<ServiceIndex> : @FM
			existingServIDs := ServicesPerformed<ServiceIndex, 1> : @FM
		end
	Next ServiceIndex
	
	response = SortedArray
	
end service


Service GetAllServIDs()
	
	ReactServsList = ''
	SelectSent  = 'SELECT REACT_SERVS BY SERV_ID'
	
	Set_Status(0)
	RList(SelectSent, TARGET_ACTIVELIST$, "", "", "")
	IF @RecCount then
		EoF = 0
		NumKeys = @RecCount
		Cnt = 0
		
		Loop
			ReadNext ReactServID Else EoF = 1
		until EoF
			Description = XLATE('REACT_SERVS', ReactServID, 1, 'X')
			ReactServsList := ReactServID : @VM : Description : @FM
		Repeat
		
	end
	//to here
	GoSub ClearCursors
	ClearSelect TARGET_ACTIVELIST$
	Response = ReactServsList
	
end service


Service ConvertRecordToJSON(KeyID, Record, itemURL)
	
	jsonRecord    = ''
	
	If KeyID NE '' then
		
		If Record EQ '' then Record = Database_Services('ReadDataRow', 'REACTOR_LOG', KeyID)
		If Error_Services('NoError') then
			@DICT   = Database_Services('GetTableHandle', 'DICT.REACTOR_LOG')
			@ID     = KeyID
			@RECORD = Record
			objJSON = ''
			If SRP_JSON(objJSON, 'New', 'Object') then
				If SRP_JSON(objReactorLog, 'New', 'Object') then 
					SRP_JSON(objReactorLog, 'SetValue', 'keyId', @ID)
					SRP_JSON(objReactorLog, 'SetValue', 'reactor', {REACTOR})
					SRP_JSON(objReactorLog, 'SetValue', 'reactType', {REACT_TYPE})
					SRP_JSON(objReactorLog, 'SetValue', 'reactTypeDesc', {REACT_TYPE_DESC})
					SRP_JSON(objReactorLog, 'SetValue', 'reactProbId', {REACT_PROB_ID})
					SRP_JSON(objReactorLog, 'SetValue', 'category', {CATEGORY})
					
					// Create an array of service info objects
					If SRP_JSON(objServInfoArray, 'New', 'Array') then
						ReactProbCatIDs = {REACT_PROB_CAT_ID}
						For each ReactProbCatID in ReactProbCatIDs using @VM setting vPos
							objServInfo = ''
							If SRP_JSON(objServInfo, 'New', 'Object') then
								SRP_JSON(objServInfo, 'SetValue', 'reactProbCatId', ReactProbCatID)
								SRP_JSON(objServInfo, 'SetValue', 'reactProbCatDesc', {REACT_PROB_CAT_DESC}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactServId', {REACT_SERV_ID}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactServDesc', {REACT_SERV_DESC}<0, vPos>)
								If {SCHEDULED}<0, vPos> EQ '' then
									SRP_JSON(objServInfo, 'SetValue', 'scheduled', {SCHEDULED}<0, vPos>, 'Null')
								end else
									SRP_JSON(objServInfo, 'SetValue', 'scheduled', {SCHEDULED}<0, vPos>, 'Boolean')
								end
								SRP_JSON(objServInfo, 'SetValue', 'reactServSnType', {REACT_SERV_SN_TYPE}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactItemId', {REACT_ITEM_IDS}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactItemRiNo', {REACT_ITEM_RI_NO}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactItemMfrPartNo', {RI_MFR_PART_NO}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactItemMfrPartRev', {RI_MFR_PART_REV}<0, vPos>)
								SRP_JSON(objServInfo, 'SetValue', 'reactItemMfrSerialNo', {RI_MFR_SERIAL_NO}<0, vPos>)
								
								SRP_JSON(objServInfo, 'SetValue', 'remReactItemId', Field({REM_RIH_KEY}<0, vPos>, '*', 2))
								SRP_JSON(objServInfo, 'SetValue', 'remReactItemDispCd', {REM_DISP_CD}<0, vPos>)
								
								
								SRP_JSON(objServInfoArray, 'Add', objServInfo)
								SRP_JSON(objServInfo, 'Release')
							end
						Next ReactProbCatID
						SRP_JSON(objReactorLog, 'Set', 'servInfo', objServInfoArray)
						SRP_JSON(objServInfoArray, 'Release')
					end
					SRP_JSON(objReactorLog, 'SetValue', 'reactUtilId', {REACT_UTIL_ID})
					objWaferCount = ''
					If SRP_JSON(objWaferCount, 'New', 'Object') then
						SRP_JSON(objWaferCount, 'SetValue', 'startCount', {REACT_WFR_CNT_START})
						StartDTM = OConv({START_DATE}, 'D4/') :' ': OConv({START_TIME}, 'MTH')
						SRP_JSON(objWaferCount, 'SetValue', 'startDtm', StartDTM)
						SRP_JSON(objWaferCount, 'SetValue', 'endCount', {REACT_WFR_CNT_END})
						SRP_JSON(objReactorLog, 'Set', 'waferCount', objWaferCount)
						SRP_JSON(objWaferCount, 'Release')
					end
					SRP_JSON(objReactorLog, 'SetValue', 'entryId', {ENTRY_ID})
					SRP_JSON(objReactorLog, 'SetValue', 'entryDate', OConv({ENTRY_DATE}, 'D4/'))
					SRP_JSON(objReactorLog, 'SetValue', 'techSig', {TECH_SIG})
					EndDTM = OConv({END_DATE}, 'D4/') :' ': OConv({END_TIME}, 'MTH')
					SRP_JSON(objReactorLog, 'SetValue', 'endDtm', Trim(EndDTM))
					SRP_JSON(objReactorLog, 'SetValue', 'elapsedHours', {ELAPSED_HOURS})
					If {LO_NA} EQ '' then
						SRP_JSON(objReactorLog, 'SetValue', 'lockOutTagOutNA', {LO_NA}, 'Null')
					end else
						SRP_JSON(objReactorLog, 'SetValue', 'lockOutTagOutNA', {LO_NA}, 'Boolean')
					end
					If {LO_REVIEWED} EQ '' then
						SRP_JSON(objReactorLog, 'SetValue', 'lockOutTagOutReviewed', {LO_REVIEWED}, 'Null')
					end else
						SRP_JSON(objReactorLog, 'SetValue', 'lockOutTagOutReviewed', {LO_REVIEWED}, 'Boolean')
					end
					If {ROTR} EQ '' then
						SRP_JSON(objReactorLog, 'SetValue', 'ROTR', {ROTR}, 'Null')
					end else
						SRP_JSON(objReactorLog, 'SetValue', 'ROTR', {ROTR}, 'Boolean')
					end
					
					Notes      = {NOTES}
					NotesDTMs  = OConv({NOTES_DTMS}, 'DT2/^H')
					NotesUsers = OConv({NOTES_USERS}, '[CONV_XLATE,LSL_USERS*FIRST_LAST]')
					
					If SRP_JSON(objNotesArray, 'New', 'Array') then
						If Notes NE '' then
							objNote = ''
							For each Note in Notes using @VM setting vPos
								If SRP_JSON(objNote, 'New', 'Object') then
									SRP_JSON(objNote, 'SetValue', 'datetime', NotesDTMs<0, vPos>)
									SRP_JSON(objNote, 'SetValue', 'user', NotesUsers<0, vPos>)
									SRP_JSON(objNote, 'SetValue', 'comment', Notes<0, vPos>)
									SRP_JSON(objNotesArray, 'Add', objNote)
									SRP_JSON(objNote, 'Release')
								end
							Next Note
						end
						SRP_JSON(objReactorLog, 'Set', 'comments', objNotesArray)
						SRP_JSON(objNotesArray, 'Release')
					end
					
					objInjSettings = ''
					If SRP_JSON(objInjSettings, 'New', 'Object') then
						For InjIndex = 1 to 5
							SRP_JSON(objInjSettings, 'SetValue', InjIndex, {CURR_INJ_SETTINGS}<0, InjIndex>)
						Next InjIndex
						SRP_JSON(objReactorLog, 'Set', 'currInjSettings', objInjSettings)
						SRP_JSON(objInjSettings, 'Release')
					end
					
					If {WAFERS_REMOVED} EQ '' then
						SRP_JSON(objReactorLog, 'SetValue', 'wafersRemoved', {WAFERS_REMOVED}, 'Null')
					end else
						SRP_JSON(objReactorLog, 'SetValue', 'wafersRemoved', {WAFERS_REMOVED}, 'Boolean')
					end
					
					// Active NICA Orders
					RlChecklistActive = {CHECKLIST_ACTIVE}
					SRP_JSON(objReactorLog, 'SetValue', 'reactorLogChecklistActive', RlChecklistActive, 'Boolean')
					If RlChecklistActive then
						RlChecklistTypes    = {CHECKLIST_TYPE}
						RlChecklistOrderIds = {CHECKLIST_ORDER_ID}
						objRlChecklistArray = ''
						If SRP_JSON(objRlChecklistArray, 'New', 'Array') then
							objChecklist = ''
							For each RlChecklistType in RlChecklistTypes using @VM setting vPos
								If SRP_JSON(objChecklist, 'New', 'Object') then
									SRP_JSON(objChecklist, 'SetValue', 'reactorLogChecklistType', RlChecklistType)
									RlChecklistOrderId = RlChecklistOrderIds<0, vPos>
									SRP_JSON(objChecklist, 'SetValue', 'reactorLogChecklistOrderId', RlChecklistOrderId)
									SRP_JSON(objRlChecklistArray, 'Add', objChecklist)
									SRP_JSON(objChecklist, 'Release')
								end
							Next RlChecklistType
							SRP_JSON(objReactorLog, 'Set', 'reactorLogChecklists', objRlChecklistArray)
							SRP_JSON(objRlChecklistArray, 'Release')
						end
					end					
					
					loadedRds      = Reactor_Services('GetLoadedRds', {REACTOR})
					loadedRdsArray = ''
					If SRP_JSON(loadedRdsArray, 'New', 'Array') then
						objLoadedRds = ''
						For idx = 1 To 2
							If SRP_JSON(objLoadedRds, 'New', 'Object') then
								loadLockSide = Xlate('RDS', loadedRds<idx>, RDS_LOAD_LOCK_SIDE$, 'X')
								SRP_JSON(objLoadedRds, 'SetValue', 'loadLockSide', loadLockSide)
								currentRds = loadedRds<idx>
								SRP_JSON(objLoadedRds, 'SetValue', 'rds', currentRds)
							end
							SRP_JSON(loadedRdsArray, 'Add', objLoadedRds)
							SRP_JSON(objLoadedRds, 'Release')
						Next idx
						SRP_JSON(objReactorLog, 'Set', 'loadedRds', loadedRdsArray, @FM)
						SRP_JSON(loadedRdsArray, 'Release')
					end

					SRP_JSON(objJSON, 'Set', 'reactorLog', objReactorLog)
					SRP_JSON(objReactorLog, 'Release')
				end
				
				If itemURL NE '' then
					// The itemURL was passed in so add HAL+JSON properties.
					
					// Create the _links property and then all link objects needed for this resource.
					objLinks = ''
					If SRP_JSON(objLinks, 'New', 'Object') then
						// Create a self link.
						objLink = ''
						If SRP_JSON(objLink, 'New', 'Object') then
							SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String')
							SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String')
							SRP_JSON(objLinks, 'Set', 'self', objLink)
							SRP_JSON(objLink, 'Release')
						end
						SRP_JSON(objJSON, 'Set', '_links', objLinks)
						SRP_JSON(objLinks, 'Release')
					end
					
					// Create the _class property for this resource.
					SRP_JSON(objJSON, 'SetValue', '_class', 'resource')
				end
				jsonRecord = SRP_JSON(objJSON, 'Stringify', 'Styled')
				SRP_JSON(objJSON, 'Release')
			end else
				Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.')
			end
		end
	end else
		Error_Services('Add', 'KeyID argument was missing in the ' : Service : ' service.')
	end
	
	Response    = jsonRecord
	
end service


Service ConvertJSONToRecord(JSON)
	
	If JSON NE '' then
		If SRP_JSON(objJSON, 'Parse', JSON) EQ '' then
			objReactorLog = SRP_JSON(objJSON, 'Get', 'reactorLog')
			@ID           = SRP_JSON(objReactorLog, 'GetValue', 'keyId')
			If @ID NE '' then
				@Record = Database_Services('ReadDataRow', 'REACTOR_LOG', @ID)
				If Error_Services('NoError') then
					@Dict               = Database_Services('GetTableHandle', 'DICT.REACTOR_LOG')
					{REACT_PROB_ID}     = SRP_JSON(objReactorLog, 'GetValue', 'reactProbID', '')
					objServInfoArray    = SRP_JSON(objReactorLog, 'Get', 'servInfo')
					NumObjects          = SRP_JSON(objServInfoArray, 'GetCount')
					ReactProbCatIds     = ''
					ReactServIds        = ''
					Scheduled           = ''
					ReactItemIds        = ''
					RemReactItemIds     = ''
					RemReactItemDispCds = ''
					For ArrayIndex = 1 to NumObjects
						ReactProbCatIds<0, ArrayIndex>     = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].reactProbCatId', '')
						ReactServIds<0, ArrayIndex>        = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].reactServId', '')
						Scheduled<0, ArrayIndex>           = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].scheduled', '')
						ReactItemIds<0, ArrayIndex>        = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].reactItemId', '')
						RemReactItemIds<0, ArrayIndex>     = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].remReactItemId', '')
						RemReactItemDispCds<0, ArrayIndex> = SRP_JSON(objServInfoArray, 'GetValue', '[':ArrayIndex:'].remReactItemDispCd', '')
					Next ArrayIndex
					SRP_JSON(objServInfoArray, 'Release')
					Notes         = ''
					NotesDTMs     = ''
					NotesUsers    = ''
					objNotesArray = SRP_JSON(objReactorLog, 'Get', 'comments')
					NumNotes      = SRP_JSON(objNotesArray, 'GetCount')
					TempID        = @ID
					TempRec       = @Record
					TempDict      = @Dict
					For ArrayIndex = 1 to NumNotes
						Notes<0, ArrayIndex>     = SRP_JSON(objNotesArray, 'GetValue', '[':ArrayIndex:'].comment', '')
						NotesDTMs<0, ArrayIndex> = IConv(SRP_JSON(objNotesArray, 'GetValue', '[':ArrayIndex:'].datetime', ''), 'DT')
						User                     = SRP_JSON(objNotesArray, 'GetValue', '[':ArrayIndex:'].user', '')
						If User NE '' then
							Query                     = 'SELECT LSL_USERS WITH FIRST_LAST EQ ':Quote(User)
							RList(Query, TARGET_ACTIVELIST$, '', '', '')
							ReadNext User else Null
							GoSub ClearCursors
						end
						NotesUsers<0, ArrayIndex> = User
					Next ArrayIndex
					SRP_JSON(objNotesArray, 'Release')
					@ID     = TempID
					@Record = TempRec
					@Dict   = TempDict
					{NOTES}                 = Notes
					{NOTES_DTMS}            = NotesDTMs
					{NOTES_USERS}           = NotesUsers
					{REACT_PROB_CAT_ID}     = ReactProbCatIds
					{REACT_SERV_ID}         = ReactServIds
					{SCHEDULED}             = Scheduled
					{REACT_ITEM_IDS}        = ReactItemIds
					{REM_DISP_CD}           = RemReactItemDispCds
					{REACT_UTIL_ID}         = SRP_JSON(objReactorLog, 'GetValue', 'reactUtilId', '')
					{REACT_WFR_CNT_START}   = SRP_JSON(objReactorLog, 'GetValue', 'waferCount.startCount', '')
					{TECH_SIG}              = SRP_JSON(objReactorLog, 'GetValue', 'techSig', '')
					{LO_NA}                 = SRP_JSON(objReactorLog, 'GetValue', 'lockOutTagOutNA', '')
					{LO_REVIEWED}           = SRP_JSON(objReactorLog, 'GetValue', 'lockOutTagOutReviewed', '')
					{ROTR}                  = SRP_JSON(objReactorLog, 'GetValue', 'ROTR', '')
					
					{WAFERS_REMOVED} = SRP_JSON(objReactorLog, 'GetValue', 'wafersRemoved', '')
					objWafersRemovedRdsArray = SRP_JSON(objReactorLog, 'Get', 'wafersRemovedRds')
					wafersRemovedRdsCount = SRP_JSON(objWafersRemovedRdsArray, 'GetCount')
					wafersRemovedRds = ''
					For idx = 1 to wafersRemovedRdsCount
						If (idx GT 1) then wafersRemovedRds := @VM
						rds = SRP_JSON(objWafersRemovedRdsArray, 'GetValue', '[':idx:']', '')
						wafersRemovedRds := rds
					Next idx
					{WAFERS_REMOVED_RDS} = wafersRemovedRds
					SRP_Json(objWafersRemovedRdsArray, 'Release')
					
					{WAFERS_REMOVED} = SRP_JSON(objReactorLog, 'GetValue', 'wafersRemoved', '')
					objWafersRemovedRdsArray = SRP_JSON(objReactorLog, 'Get', 'wafersRemovedRds')
					wafersRemovedRdsCount = SRP_JSON(objWafersRemovedRdsArray, 'GetCount')
					wafersRemovedRds = ''
					For idx = 1 to wafersRemovedRdsCount
						If (idx GT 1) then wafersRemovedRds := @VM
						rds = SRP_JSON(objWafersRemovedRdsArray, 'GetValue', '[':idx:']', '')
						wafersRemovedRds := rds
					Next idx
					{WAFERS_REMOVED_RDS} = wafersRemovedRds
					SRP_Json(objWafersRemovedRdsArray, 'Release')
				end
			end else
				Error_Services('Add', 'Error in ':Service:' service. Null value for reactorLog.keyID.')
			end
			SRP_JSON(objReactorLog, 'Release')
			SRP_JSON(objJSON, 'Release')
		end else
			Error_Services('Add', 'Error in ':Service:' service. Unable to parse JSON payload.')
		end
	end else
		Error_Services('Add', 'Error in ':Service:' service. Null JSON passed in.')
	end
	
	Response = @Record
	
end service


Service GetRlChecklistActive(RLKey)
	
	If RLKey NE '' then
		OrderTypes            = 'ASM_HTR_TUBE_CHANGE' : @VM : 'ASM_HTR_ANNUAL_PM' : @VM : 'ASM_HTR_SEMIANNUAL_PM' : @VM : 'ASM_HTR_FIVE_AND_TEN_YEAR_PM'
		ActiveRlOrderIds      = Nica_Orders_Services('GetActiveOrders', 'REACTOR_LOG', RLKey, OrderTypes)
		Response              = ( ActiveRlOrderIds NE '' )
	end else
		Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
	end
	
end service


Service AddComment(Reactor, NewNote, User)
	
	ReactModeNGKey = Xlate('REACTOR_CHILD_KEY_IDS_NG', Reactor, 'REACT_MODE_KEY_IDS', 'X')
	RLKey          = Xlate('REACT_MODE_NG', ReactModeNGKey, 'START_RL_ID', 'X')
	If RLKey NE '' then
		RLRec = Database_Services('ReadDataRow', 'REACTOR_LOG', RLKey)
		If Error_Services('NoError') then
			Notes                                         = RLRec<REACTOR_LOG_NOTES$>
			NumNotes                                      = DCount(Notes, @VM)
			RLRec<REACTOR_LOG_NOTES$, NumNotes + 1>       = NewNote
			RLRec<REACTOR_LOG_NOTES_DTMS$, NumNotes + 1>  = Datetime()
			RLRec<REACTOR_LOG_NOTES_USERS$, NumNotes + 1> = User
			Database_Services('WriteDataRow', 'REACTOR_LOG', RLKey, RLRec)
		end
	end else
		Error_Services('Add', 'Error in ':Service:' service. Error locating reactor log key for reactor ':Reactor:'.')
	end
	
end service


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

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

