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

    Name        :   Lot_Services

    Description :   Handler program for all LOT 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)
        07/01/25    djs     Corrected error throwing.

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$Insert SERVICE_SETUP
$Insert APP_INSERTS
$Insert LOT_EQUATES
$Insert TEST_WAFER_PROD_EQUATES
$Insert LOT_OPERATION_EQUATES
$Insert PRODUCT_OPERATION_EQUATES
$Insert LOT_EVENT_EQUATES
$Insert NOTIFICATION_EQUATES
$Insert VOIDED_LOT_EQUATES

Declare function TEST_WAFER_PROD_SERVICES, SRP_Datetime, Datetime, Database_Services, Lot_Services, Error_Services, RTI_CREATEGUID
Declare function SRP_Array, SRP_Json, Environment_Services, Logging_Services, MemberOf, Lot_Event_Services, GetTickCount
Declare subroutine Database_Services, Btree.Extract, Lot_Services, Error_Services, Labeling_Services, SRP_Json, Logging_Services
Declare subroutine SRP_Run_Command, Service_Services, obj_notes, Lot_Event_Services, Mona_Services

LogPath      = Environment_Services('GetApplicationRootPath') : '\LogFiles\Lot'
LogDate      = Oconv(Date(), 'D4/')
LogTime      = Oconv(Time(), 'MTS')
LoggingDTM   = LogDate : ' ' : LogTime   ; // Logging DTM

LogFileName      = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' TestWaferLotCreation.csv'
Headers          = 'Logging DTM' : @FM : 'Product Name' : @FM : 'Username' : @FM : 'Message'
objTWCreationLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName    = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotStart.csv'
Headers        = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Username' : @FM : 'Message'
objLotStartLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotRun.csv'
Headers     = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Username' : @FM : 'Tool Id' : @FM : 'Message'
objLotRunLog   = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName   = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotMove.csv'
Headers       = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Username' : @FM : 'Message'
objLotMoveLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName    = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' LotEvent.csv'
Headers        = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Event Type' : @FM : 'Operator' : @FM : 'Begin Wafer Qty' : @FM : 'End Wafer Qty' : @FM : 'Bonus Wafer Qty' : @FM : 'Reduce Wafer Qty' : @FM : 'Message'
objLotEventLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName    = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' TWLotClosure.csv'
Headers        = 'Logging DTM' : @FM : 'Lot Id' : @FM : 'Operator' : @FM : 'Message'
objLotClosureLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

Options EVENT_TYPES = 'MOVE_IN', 'MOVE_OUT', 'HOLD_ON', 'HOLD_OFF', 'REDUCE_WAFER_QTY', 'BONUS_WAFER_QTY', 'COMMENT', 'LOCATION', 'LOAD', 'UNSIGN_LOAD', 'TW_USE', 'CLOSE', 'SIGN_FQA', 'UNSIGN_FQA'
Options LOT_TYPES = 'TW', 'RDS', 'WM_OUT', 'WM_IN', 'WO_MAT', 'LOT'

IsProd = Environment_Services('IsProd')
If IsProd EQ True$ then
	MonaResource = 'GRP_OPENINSIGHT_MES_OP_FE_LOTSERVICES'
end else
	MonaResource = 'GRP_OPENINSIGHT_MES_OP_FE_DEV_LOTSERVICES'
end

GoToService

Return Response or ""

//----------------------------------------------------------------------------------------------------------------------
// Services
//----------------------------------------------------------------------------------------------------------------------

Service GenerateNewLotId(LotType)
	
	NewLotID = ''
	RightNow = Datetime()
	If LotType NE '' then
		ValidLotNum    = False$
		GeneratedLotID = ''
		Begin Case
			Case LotType EQ 'TW'
				Loop
				Until ValidLotNum EQ True$
					LotPrefix = 'TW'
					LotYear   = SRP_Datetime('Year', RightNow)
					LotMonth  = SRP_Datetime('Month', RightNow)
					LotDay    = SRP_Datetime('Day', RightNow)
					LotTime   = SRP_Datetime('Time', RightNow)
					
					GeneratedLotId = LotPrefix : LotYear : LotMonth : LotDay : LotTime
					If Not(RowExists('LOT', GeneratedLotId)) then
						ValidLotNum = True$
					end else
						ValidLotNum = False$
						RightNow    = Datetime()
					end
				Repeat
			Case LotType EQ 'RDS' OR LotType EQ 'WM_IN' OR LotType EQ 'WM_OUT' OR LotType EQ 'WO_MAT'
				Loop
				Until ValidLotNum EQ True$
					LotPrefix = ''
					Begin Case
						Case LotType EQ 'RDS'
							LotPrefix = 'R'
						Case LotType EQ 'WM_IN'
							LotPrefix = 'I'
						Case LotType EQ 'WM_OUT'
							LotPrefix = 'O'
						Case LotType EQ 'WO_MAT'
							LotPrefix = 'M'
					End Case
					HaveLockLotIdSequence = Database_Services('GetKeyIDLock', 'CONFIG', 'LOT_KEY_SEQUENCE_PROD')
					If HaveLockLotIdSequence then
						CurrLotSequence = Database_Services('ReadDataRow', 'CONFIG', 'LOT_KEY_SEQUENCE_PROD', True$, 0, False$)
						NextLotSequence = CurrLotSequence + 1
						Database_Services('WriteDataRow', 'CONFIG', 'LOT_KEY_SEQUENCE_PROD', NextLotSequence, True$, False$, False$)
						Database_Services('ReleaseKeyIDLock', 'CONFIG', 'LOT_KEY_SEQUENCE_PROD')
						GeneratedLotId = LotPrefix : CurrLotSequence
						If Not(RowExists('LOT', GeneratedLotId)) AND CurrLotSequence NE '' then
							ValidLotNum = True$
						end else
							ValidLotNum = False$
						end
					end
				Repeat
			Case Otherwise$
				Null
		End Case
		If GeneratedLotID NE '' AND ValidLotNum then
			// Write the new lot id now so it's reserved
			Database_Services('WriteDataRow', 'LOT', GeneratedLotID, '')
			If RowExists('LOT', GeneratedLotID) then
				NewLotID = GeneratedLotID
			end
		end
	end
	Response = NewLotID
	
end service


Service GetLotIdByLegacyLotIdAndType(LegacyLotId, LegacyLotType)
	
	StartTick  = GetTickCount()
	MetricName = 'GetLotIdByLegacyLotIdAndType'
	ErrorMsg   = ''
	Open 'DICT.LOT' to DictLot then
		SearchString    = ''
		SearchString := 'LEGACY_LOT_ID':@VM:LegacyLotId:@FM
		SearchString := 'TYPE':@VM:LegacyLotType:@FM
		LotIdKeys          = ''
		Btree.Extract(SearchString, 'LOT', DictLot, LotIdKeys, '', '')
		ErrCode         = ''
		IF Get_Status(ErrCode) then
			ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract. Error code ':ErrCode:'.'
		end else
			Response = LotIdKeys<1,1>
		end
	end else
		ErrorMsg = 'Error in ':Service:' service. Error opening LOT dictionary.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
	If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
	
end service


Service CreateNewLot(LotType, ProdName, LotQty, VendorPartNo, VendorLotNo, VendorCode, Username, PrinterID, LotId)
	
	StartTick = GetTickCount()
	MetricName = 'CreateNewLot'
	
	CreatedLotNumber = ''
	ErrorMessage     = ''
	Begin Case
		Case LotType EQ 'RDS' OR LotType EQ 'WM_IN' OR LotType EQ 'WM_OUT' OR LotType EQ 'WO_MAT'
			// Case statement for legacy lot entity types
			NewLotId = Lot_Services('GenerateNewLotId', LotType)
			If NewLotId NE '' then
				If RowExists('LOT', NewLotId) NE False$ then
					LotRec                      = ''					
					LotRec<LOT_TYPE$>           = LotType
					LotRec<LOT_PROD_ID$>        = ''
					LotRec<LOT_ORIG_WAFER_QTY$> = LotQty
					LotRec<LOT_WAFER_QTY$>      = LotQty
					LotRec<LOT_VENDOR_PART_NO$> = VendorPartNo
					LotRec<LOT_VENDOR_LOT_NO$>  = VendorLotNo
					LotRec<LOT_VENDOR_CODE$>    = VendorCode
					LotRec<LOT_LEGACY_LOT_ID$>    = LotId
					Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
					If Error_Services('HasError') then
						ErrorMessage = 'Error in ':Service:' service. ':Error_Services('GetMessage')
					end else
						CreatedLotNumber = NewLotId
					end
				end else
					ErrorMessage = 'Error in ':Service:' service. LOT record "':NewLotId:'" already exists.'
				end
			end else
				ErrorMessage = 'Error in ':Service:' service. No lot ID passed in.'
			end
		Case LotType EQ 'TW'
			If ProdName NE '' then
				TWProdID = Test_Wafer_Prod_Services('GetTestWaferProdIDsByPartName', ProdName)
				If TWProdID NE '' then
					If DCount(TWProdID, @VM) EQ 1 then
						NewLotId = Lot_Services('GenerateNewLotId', 'TW');//Don't use this
						If NewLotId NE '' then
							If RowExists('LOT', NewLotId) then
								LotRec = Database_Services('ReadDataRow', 'LOT', NewLotId)
								// Ensure the lot record is empty
								If LotRec<LOT_TYPE$> EQ '' AND LotRec<LOT_PROD_ID$> EQ '' AND LotRec<LOT_ORIG_WAFER_QTY$> EQ '' AND LotRec<LOT_WAFER_QTY$> EQ '' then
									LotRec<LOT_TYPE$>           = LotType
									LotRec<LOT_PROD_ID$>        = TWProdID
									LotRec<LOT_ORIG_WAFER_QTY$> = LotQty
									LotRec<LOT_WAFER_QTY$>      = LotQty
									LotRec<LOT_VENDOR_PART_NO$> = VendorPartNo
									LotRec<LOT_VENDOR_LOT_NO$>  = VendorLotNo
									LotRec<LOT_VENDOR_CODE$>    = VendorCode
									Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
									// Now Ensure that the written lot matches what was just written
									LotRecCheck                 = Database_Services('ReadDataRow', 'LOT', NewLotId)
									If LotRecCheck EQ LotRec then
										// Lot Created successfully
										CreatedLotNumber = NewLotId
										If RowExists('LOT', CreatedLotNumber) then
											Lot_Services('CreateInitialLotOperationRecords', CreatedLotNumber)
											If Error_Services('NoError') then
												// Check in at first operation
												// Get Curr Operation(Should be first one in sequence)
												ThisLotCurrOpId = Lot_Services('GetLotCurrOperationId', CreatedLotNumber)
												If ThisLotCurrOpId NE ''  then
													// Set lot to open
													Lot_Services('OpenLot', CreatedLotNumber)
													if Error_Services('NoError') then
														// Move lot in
														Lot_Services('MoveInLot', CreatedLotNumber, Username)
														if Error_Services('NoError') then
															If PrinterID NE 'WEB' then
																// If PrinterID is set to WEB this means the request comes from OI_Wizard and the client is going to handle printing.
																Labeling_Services('PrintTestWaferLotLabel', CreatedLotNumber, Username, PrinterID)
																If Error_Services('HasError') then
																	ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : CreatedLotNumber : ' , ' : Error_Services('GetMessage')
																end
															end
															Lot_Services('MoveOutLot', NewLotId, Username)
															If Error_Services('NoError') then
																Lot_Services('MoveInLot', NewLotId, Username)
																If Error_Services('HasError') then
																	ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
																end
															end else
																ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
															end
														end else
															ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
														end
													end else
														// Close LOT record as there was an error
														Lot_Services('CloseLot', NewLotId)
														ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
													end
												end else
													// Close LOT record as there was an error
													Lot_Services('CloseLot', NewLotId)
													ErrorMessage = 'Error in Create New Test Wafer Lot Process, error getting current operation for lot: ' : NewLotId
												end
											end else
												// Close LOT record as there was an error
												// Database_Services('DeleteDataRow', 'LOT', NewLotId, True$, False$)
												Lot_Services('CloseLot', NewLotId)
												ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
											end
										end
									end else
										ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot attributes did not write correctly for lot: ' : NewLotId
									end
								end else
									ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot already had data, lot: ' : NewLotId
								end
							end else
								ErrorMessage = 'Error in Create New Test Wafer Lot Process, Created lot: ' : NewLotId : ' not found in LOT table.'
							end
						end else
							ErrorMessage = 'Error in Create New Test Wafer Lot Process, no lot id returned.'
						end
					end else
						ErrorMessage = 'Error in Create New Test Wafer Lot Process, ambiguous product passed to routine OR no matching products found.'
					end
				end else
					ErrorMessage = 'Error in Create New Test Wafer Lot Process, product(':ProdName:') passed to routine not found.'
				end
			end else
				ErrorMessage = 'Null value passed in for ProdID'
			end    		
		Case Otherwise$
			ErrorMessage = 'Error in ':Service:' service. Lot Type "':LotType:'" is not currently supported.'
	End Case
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = ProdName
		LogData<3> = Username
		LogData<4> = 'Successfully created lot id ' : CreatedLotNumber : ' of product type ' : ProdName '.'
		Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = ProdName
		LogData<3> = Username
		LogData<4> = ErrorMessage
		Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)
	end
	Response = CreatedLotNumber
	
End Service


Service CreateNewTestWaferLot(LotType, ProdName, LotQty, VendorPartNo, VendorLotNo, VendorCode, Username, PrinterID)
	
	CreatedLotNumber = ''
	ErrorMessage     = ''
	If LotType EQ 'TW' then
		If ProdName NE '' then
			TWProdID = Test_Wafer_Prod_Services('GetTestWaferProdIDsByPartName', ProdName)
			If TWProdID NE '' then
				If DCount(TWProdID, @VM) EQ 1 then
					NewLotId = Lot_Services('GenerateNewLotId', 'TW')
					If NewLotId NE '' then
						If RowExists('LOT', NewLotId) then
							LotRec = Database_Services('ReadDataRow', 'LOT', NewLotId)
							// Ensure the lot record is empty
							If LotRec<LOT_TYPE$> EQ '' AND LotRec<LOT_PROD_ID$> EQ '' AND LotRec<LOT_ORIG_WAFER_QTY$> EQ '' AND LotRec<LOT_WAFER_QTY$> EQ '' then
								LotRec<LOT_TYPE$>           = LotType
								LotRec<LOT_PROD_ID$>        = TWProdID
								LotRec<LOT_ORIG_WAFER_QTY$> = LotQty
								LotRec<LOT_WAFER_QTY$>      = LotQty
								LotRec<LOT_VENDOR_PART_NO$> = VendorPartNo
								LotRec<LOT_VENDOR_LOT_NO$>  = VendorLotNo
								LotRec<LOT_VENDOR_CODE$>    = VendorCode
								Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
								// Now Ensure that the written lot matches what was just written
								LotRecCheck                 = Database_Services('ReadDataRow', 'LOT', NewLotId)
								If LotRecCheck EQ LotRec then
									// Lot Created successfully
									CreatedLotNumber = NewLotId
									If RowExists('LOT', CreatedLotNumber) then
										Lot_Services('CreateInitialLotOperationRecords', CreatedLotNumber)
										If Error_Services('NoError') then
											// Check in at first operation
											// Get Curr Operation(Should be first one in sequence)
											ThisLotCurrOpId = Lot_Services('GetLotCurrOperationId', CreatedLotNumber)
											If ThisLotCurrOpId NE ''  then
												Lot_Services('MoveInLot', NewLotId, Username)
												if Error_Services('NoError') then
													// Set lot to open
													Lot_Services('OpenLot', CreatedLotNumber)
													if Error_Services('NoError') then
														If PrinterID NE 'WEB' then
															// If PrinterID is set to WEB this means the request comes from OI_Wizard and the client is going to handle printing.
															Labeling_Services('PrintTestWaferLotLabel', CreatedLotNumber, Username, PrinterID)
															If Error_Services('HasError') then
																ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : CreatedLotNumber : ' , ' : Error_Services('GetMessage')
															end
														end
														Lot_Services('MoveOutLot', NewLotId, Username)
														If Error_Services('NoError') then
															Lot_Services('MoveInLot', NewLotId, Username)
															If Error_Services('HasError') then
																ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
															end
														end else
															ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
														end
													end else
														ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
													end
												end else
													ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
												end
											end else
												ErrorMessage = 'Error in Create New Test Wafer Lot Process, error getting current operation for lot: ' : NewLotId
											end
										end else
											ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
										end
									end
								end else
									ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot attributes did not write correctly for lot: ' : NewLotId
								end
							end else
								ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot already had data, lot: ' : NewLotId
							end
						end else
							ErrorMessage = 'Error in Create New Test Wafer Lot Process, Created lot: ' : NewLotId : ' not found in LOT table.'
						end
					end else
						ErrorMessage = 'Error in Create New Test Wafer Lot Process, no lot id returned.'
					end
				end else
					ErrorMessage = 'Error in Create New Test Wafer Lot Process, ambiguous product passed to routine OR no matching products found.'
				end
			end else
				ErrorMessage = 'Error in Create New Test Wafer Lot Process, product(':ProdName:') passed to routine not found.'
			end
		end else
			ErrorMessage = 'Null value passed in for ProdID'
		end
	end else
		ErrorMessage = 'Lot type was not test wafer'
	end
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = ProdName
		LogData<3> = Username
		LogData<4> = 'Successfully created lot id ' : CreatedLotNumber : ' of product type ' : ProdName '.'
		Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = ProdName
		LogData<3> = Username
		LogData<4> = ErrorMessage
		Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)
	end
	Response = CreatedLotNumber
	
End Service


Service GenerateInitialLotOperationRecords(LotId)
	
	ErrorMessage = ''
	If LotID NE '' then
		if RowExists('LOT', LotId) then
			LotRec            = Database_Services('ReadDataRow', 'LOT', LotId)
			ProdID            = LotRec<LOT_PROD_ID$>
			If ProdID NE '' then
				// Get product operations
				ThisLotOperations = Lot_Services('GetPrescribedOperationsByProdId', ProdId)
				If ThisLotOperations NE '' then
					for each ProdOperationKey in ThisLotOperations using @FM
						OperationRec      = Database_Services('ReadDataRow', 'PRODUCT_OPERATION', ProdOperationKey)
					Next operation
				end else
					ErrorMessage = 'No Operations found for ' : ProdId 
				end
			end else
				ErrorMessage = 'Prod ID not specified'
			end
			// ID will be LotNum + OperationID
			// Get product operations
		end else
			ErrorMessage = 'Lot ID does not exist.'
		end
	end else
		ErrorMessage = 'Lot ID was null'
	end
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


Service GetPrescribedOperationsByProdId(ProdId, ProdType)
	
	ErrorMsg          = ''
	ProdOperationKeys = ''
	If ProdId NE '' then
		Begin Case
			Case ProdType = 'TW'
				ProdRec           = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', ProdId)
				ProdOperationKeys = ProdRec<TEST_WAFER_PROD_PRODUCT_OPERATIONS$>
			Case Otherwise$
				ErrorMsg = 'Error in ':Service:' service. No matching prod type.'
		End Case
	end else
		ErrorMsg = 'Error in ':Service:' service. Null ProdId passed into service.'
	end
	
	If ErrorMsg EQ '' then 
		Response = ProdOperationKeys
	end else
		Error_Services('Add', ErrorMsg)
	end
	
end service


Service CreateInitialLotOperationRecords(LotId)
	
	ErrorMessage = ''
	If LotId NE '' then
		LotRec                    = Database_Services('ReadDataRow', 'LOT', LotId)
		LotType                   = LotRec<LOT_TYPE$>
		ProdId                    = LotRec<LOT_PROD_ID$>
		ThisInitialProdOperations = Lot_Services('GetPrescribedOperationsByProdId', ProdId, LotType)
		If Error_Services('NoError') AND ThisInitialProdOperations NE '' then
			For each ProdOperation in ThisInitialProdOperations using @VM
				ProdOperationRec  = Database_Services('ReadDataRow', 'PRODUCT_OPERATION', ProdOperation)
				OperationID       = ProdOperationRec<PRODUCT_OPERATION_OPERATION_ID$>
				OperationSequence = ProdOperationRec<PRODUCT_OPERATION_OPERATION_SEQUENCE$>
				LotOperationRecID = Rti_Createguid()
				If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then
					LotOperationRec                                    = ''
					LotOperationRec<LOT_OPERATION_LOT_ID$>             = LotId
					LotOperationRec<LOT_OPERATION_OPERATION_ID$>       = OperationID
					LotOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = OperationSequence
					LotOperationRec<LOT_OPERATION_REWORK$>             = False$
					Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationRecId, LotOperationRec)
					TestRec                                            = Database_Services('ReadDataRow', 'LOT', LotId)
				end else
					ErrorMessage = 'Error in ':Service:' service. Lot Operation already existed, cannot overwrite.'
				end
			Next Operation
		end else
			ErrorMessage = 'Error in ':Service:' service. Error getting prescribed operations for lot# ' : LotId
		end
	end else
		ErrorMessage = 'Error in ':Service:' service. Null LotID passed into service.'
	end
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


// Returns a @FM delimited list of operations in sequence
Service GetLotOperationSequence(LotId)
	
	StartTick               = GetTickCount()
	MetricName              = 'GetLotOperationSequence'
	ErrorMsg                = ''
	LotOperationsInSequence = ''
	If LotID NE '' then
		// Get Operations
		LotOperations           = Xlate('LOT', LotId, LOT_LOT_OPERATIONS$, 'X')
		for each LotOperation in LotOperations using @VM
			ThisLotOperationSequence                          = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_OPERATION_SEQUENCE$, 'X')
			LotOperationsInSequence<ThisLotOperationSequence> = LotOperation
		Next LotOperation
	end else
		ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
	If ErrorMsg EQ '' then
		Response = LotOperationsInSequence
	end else
		Error_Services('Add', ErrorMsg)
	end
	
end service


Service GetLotCurrOperationId(LotId)
	
	StartTick     = GetTickCount()
	MetricName    = 'GetLotCurrOperationId'
	ErrorMsg      = ''
	CurrOperation = ''
	If LotID NE '' then
		// Get them in sequence first
		LotOperationsInSequence = Lot_Services('GetLotOperationSequence', LotId)
		for each LotOperation in LotOperationsInSequence using @FM 
			ThisLotOperationStartDTM = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_IN$, 'X')
			ThisLotOperationEndDTM   = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_OUT$, 'X')
			If ThisLotOperationEndDTM Eq '' then
				CurrOperation = LotOperation
			end
		until CurrOperation
		Next LotOperation
	end else
		ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service'
	end
	Response = CurrOperation
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
	If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
	
end service


Service GetLotCurrOperationName(LotId)
	
	StartTick         = GetTickCount()
	MetricName        = 'GetLotCurrOperationName'
	ErrorMsg          = ''
	CurrOperationId   = ''
	CurrOperationName = ''
	If LotID NE '' then
		// Get them in sequence first
		LotOperationsInSequence = Lot_Services('GetLotOperationSequence', LotId)
		for each LotOperation in LotOperationsInSequence using @FM 
			ThisLotOperationStartDTM = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_IN$, 'X')
			ThisLotOperationEndDTM   = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_OUT$, 'X')
			If ThisLotOperationEndDTM Eq '' then
				CurrOperationId   = LotOperation
				CurrOperationName = Database_Services('ReadDataColumn', 'LOT_OPERATION', CurrOperationId, LOT_OPERATION_OPERATION_ID$, True$, 0, False$)
			end
		until CurrOperationName
		Next LotOperation
	end else
		ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
	If ErrorMsg EQ '' then
		Response = CurrOperationName
	end else
		Error_Services('Add', ErrorMsg)
	end
	
end service


Service AddLotOperationIntoSequence(LotId, NewOperationId, NewSequence, Rework)
	
	ErrorMessage = ''
	If LotId NE '' then
		If NewSequence NE '' AND Num(NewSequence) then
			// Get Current Operations in sequence
			LotCurrOperation      = Lot_Services('GetLotCurrOperationId', LotId)
			CurrOperationSequence = Xlate('LOT_OPERATION', LotCurrOperation, LOT_OPERATION_OPERATION_SEQUENCE$, 'X')
			If CurrOperationSequence LE NewSequence then
				// Get Curr Operation Sequence
				Done                     = False$
				LotCurrOperationSequence = Lot_Services('GetLotOperationSequence', LotId)
				for each Operation in LotCurrOperationSequence using @Fm setting OpPos
					ThisOperationRec      = Database_Services('ReadDataRow', 'LOT_OPERATION', Operation)
					ThisOperationSequence = ThisOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$>
					If ThisOperationSequence GE NewSequence then
						NewOperationSequence                                = ThisOperationSequence + 1
						ThisOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = NewOperationSequence
						Database_Services('WriteDataRow', 'LOT_OPERATION', Operation, ThisOperationRec)
						If Error_Services('HasError') then
							Done         = True$
							ErrorMessage = Error_Services('GetMessage')
						end
					end
				Until Done
				Next Operation
				If ErrorMessage EQ '' then
					LotOperationRecID                                  = RTI_CreateGUID()
					If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then
						LotOperationRec                                    = ''
						LotOperationRec<LOT_OPERATION_LOT_ID$>             = LotId
						LotOperationRec<LOT_OPERATION_OPERATION_ID$>       = NewOperationId
						LotOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = NewSequence
						LotOperationRec<LOT_OPERATION_REWORK$>             = Rework
						Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationRecId, LotOperationRec)
					end else
						ErrorMessage = 'Error in ':Service:' service. Lot Operation already existed, cannot overwrite'
					end
				end
			end else
				ErrorMessage = 'Error in ':Service:' service. Not allowed to add new operations prior to current operation'
			end
		end else
			ErrorMessage = 'Error in ':Service:' service. Null or invalid sequence passed to routine'
		end
	end else
		ErrorMessage = 'Error in ':Service:' service. Null LotID passed into service.'
	end
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


Service IsLotMovedIn(LotId)
	
	StartTick = GetTickCount()
	MetricName = 'IsLotMovedIn'
	
	Response = ''
	If RowExists('LOT', LotId) then
		CurrOperId    = Lot_Services('GetLotCurrOperationId', LotId)
		CurrOperDtmIn = Database_Services('ReadDataColumn', 'LOT_OPERATION', CurrOperId, LOT_OPERATION_DATETIME_IN$, True$, 0, False$)
		Response      =  ( (CurrOperDtmIn LE Datetime()) AND (CurrOperDtmIn NE '') )
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
end service


Service IsOperationCompleted(LotOperationId)
	
	OperationCompleted = False$
	ErrorMessage = ''
	If RowExists('LOT_OPERATION', LotOperationId) then
		LotOperationDateTimeOut = Database_Services('ReadDataColumn', 'LOT_OPERATION', LotOperationId, LOT_OPERATION_DATETIME_OUT$, True$, 0, False$)
		If LotOperationDateTimeOut NE '' then OperationCompleted = true$
	end else
		ErrorMessage = 'Invalid lot operation id passed to routine.'
	end
	If ErrorMessage NE '' then
		Error_Services('Add', 'Error in ' : Service : ' with Lot OperationId ' : LotOperationId : ' : ' : ErrorMessage)
	end
	Response = OperationCompleted
	
end service


Service StartLot(LotId, Operator)
	
	StartTick = GetTickCount()
	ErrorMessage           = ''
	If LotId NE '' then
		If RowExists('LOT', LotId) then
			Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'LOT_START', 'Lot started.', '', Operator)
			If Error_Services('NoError') then
				Lot_Services('MoveInLot', LotId, Operator)
				If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
			end else
				ErrorMessage = Error_Services('GetMessage')
			end
		end else
			ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
		end
	end else
		ErrorMessage = 'Error in ':Service:' process. Lot id was not passed to routine.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)     
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Successfully started lot.'
		Logging_Services('AppendLog', objLotStartLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Error starting lot.'
		Logging_Services('AppendLog', objLotStartLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)    	
	end
	
end service


Service BeginRun(LotId, Operator, ToolId)
	
	StartTick    = GetTickCount()
	ErrorMessage = ''
	If ( (LotId NE '') and (Operator NE '') and (ToolId NE '') ) then
		If RowExists('LOT', LotId) then
			Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'BEGIN_RUN', 'Begin run', ToolId, Operator)
			If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
		end else
			ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
		end
	end else
		ErrorMessage = 'Error in ':Service:' process. Lot id, Operator, or ToolId was not passed to routine.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)    
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = ToolId
		LogData<4> = 'Successfully began run.'
		Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = ToolId
		LogData<4> = 'Error beginning run.'
		Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)    	
	end
	
end service


Service EndRun(LotId, Operator, ToolId)
	
	StartTick    = GetTickCount()
	ErrorMessage = ''
	If ( (LotId NE '') and (Operator NE '') and (ToolId NE '') ) then
		If RowExists('LOT', LotId) then
			Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'END_RUN', 'End run', ToolId, Operator)
			If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
		end else
			ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
		end
	end else
		ErrorMessage = 'Error in ':Service:' process. Lot id, Operator, or ToolId was not passed to routine.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)    
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = ToolId
		LogData<4> = 'Successfully ended run.'
		Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = ToolId
		LogData<4> = 'Error ending run.'
		Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)    	
	end
	
end service


Service MoveInLot(LotID, Operator)
	
	StartTick              = GetTickCount()
	MetricName             = 'MoveInLot'
	ErrorMessage           = ''
	ThisLotCurrOperationID = ''
	If LotId NE '' then
		If RowExists('LOT', LotId) then
			ThisLotRec = Database_Services('ReadDataRow', 'LOT', LotId)
			WaferQty   = ThisLotRec<LOT_WAFER_QTY$>
			//Possibly Add locking here
			If Error_Services('NoError') then
				ThisLotCurrOperationID                                 = Lot_Services('GetLotCurrOperationId', LotId)
				If ThisLotCurrOperationID NE '' then
					ThisLotCurrOperationRec                                = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotCurrOperationID)
					ThisLotCurrOperationRec<LOT_OPERATION_DATETIME_IN$>    = Datetime()
					ThisLotCurrOperationRec<LOT_OPERATION_WAFER_IN_QTY$>   = WaferQty
					ThisLotCurrOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = Operator
					Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotCurrOperationID, ThisLotCurrOperationRec)
					If Error_Services('NoError') then
						LotType       = XLATE('LOT', LotId, LOT_TYPE$, 'X')
						CurrOperation = XLATE('LOT_OPERATION', ThisLotCurrOperationID, LOT_OPERATION_OPERATION_ID$, 'X')
						If Error_Services('NoError') then
							Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'MOVE_IN', 'Lot moved into operation ' : CurrOperation : '.', '', Operator)
							If Error_Services('NoError') then
								Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'ARRIVAL', 'Lot arrived at operation ' : CurrOperation : '.', '', Operator)
								If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
							end else
								ErrorMessage = Error_Services('GetMessage')
							end
						end else
							ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage') 
						end
					end else
						ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Error writing to lot operation record. ' : Error_Services('GetMessage')    
					end
				end else
					ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Error getting lots current operation.'
				end
			end else
				ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
			end
		end else
			ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
		end
	end else
		ErrorMessage = 'Error in Move In process. Lot id was not passed to routine.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Successfully Moved Lot into operation ' : ThisLotCurrOperationID : '.'
		Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Error moving Lot into operation ' : ThisLotCurrOperationID : '.'
		Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)
	end
	
end service


Service MoveOutLot(LotID, Operator)
	
	StartTick              = GetTickCount()
	MetricName             = 'MoveOutLot'
	ErrorMessage           = ''
	ThisLotCurrOperationID = ''
	If LotId NE '' then
		If RowExists('LOT', LotId) then
			ThisLotRec = Database_Services('ReadDataRow', 'LOT', LotId)
			WaferQty   = ThisLotRec<LOT_WAFER_QTY$>
			If Error_Services('NoError') then
				ThisLotCurrOperationID                                  = Lot_Services('GetLotCurrOperationId', LotId)
				If ThisLotCurrOperationID NE '' then
					If Lot_Services('IsLotMovedIn', LotId) then
						ThisLotCurrOperationRec                                 = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotCurrOperationID)
						ThisLotCurrOperationRec<LOT_OPERATION_DATETIME_OUT$>    = Datetime()
						ThisLotCurrOperationRec<LOT_OPERATION_WAFER_OUT_QTY$>   = WaferQty
						ThisLotCurrOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = Operator
						Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotCurrOperationID, ThisLotCurrOperationRec)
						If Error_Services('NoError') then
							LotType       = XLATE('LOT', LotId, LOT_TYPE$, 'X')
							CurrOperation = XLATE('LOT_OPERATION', ThisLotCurrOperationID, LOT_OPERATION_OPERATION_ID$, 'X')
							If Error_Services('NoError') then
								Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'MOVE_OUT', 'Lot moved out of operation ' : CurrOperation : '.', '', Operator)
							end else
								ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage') 
							end
						end else
							ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Error writing to lot operation record. ' : Error_Services('GetMessage')
						end
					end else
						CurrOperationName = Field(ThisLotCurrOperationID, '*', 2)
						ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Cannot move out lot from ' :CurrOperationName: ' because it is not moved in.'
					end
				end else
					ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Error getting lots current operation.'
				end
			end else
				ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
			end
		end else
			ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
		end
	end else
		ErrorMessage = 'Error in Move Out process. Lot id was not passed to routine.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage EQ '' then
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Successfully Moved Lot out of operation ' : ThisLotCurrOperationID : '.'
		Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
	end else
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotID
		LogData<3> = Operator
		LogData<4> = 'Error in Move Out process for Lot id ' : LotId : '. ' : ErrorMessage
		Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
		Error_Services('Add', ErrorMessage)
	end
	
end service


Service ConvertLotRecordToJson(LotId, ItemURL, CurrUser, FullObject=BOOLEAN)
	
	ErrorMessage = ''
	JsonString   = ''
	If FullObject EQ '' then FullObject = True$
	If RowExists('LOT', LotId) then
		objJSON = ''
		If SRP_JSON(objJSON, 'New', 'Object') then
			LotRec = Database_Services('ReadDataRow', 'LOT', LotId)
			If Error_Services('NoError') then
				If SRP_JSON(objLot, 'New', 'Object') then
					SRP_JSON(objLot, 'SetValue', 'LotId', LotId)
					SRP_JSON(objLot, 'SetValue', 'Type', LotRec<LOT_TYPE$>)
					SRP_JSON(objLot, 'SetValue', 'ProdId', LotRec<LOT_PROD_ID$>)
					Begin Case
						Case LotRec<LOT_TYPE$> = 'TW'
							ProdName = XLATE('TEST_WAFER_PROD', LotRec<LOT_PROD_ID$>, TEST_WAFER_PROD_PART_NAME$, 'X')
						Case Otherwise$
							ProdName = ''
					End Case
					SRP_JSON(objLot, 'SetValue', 'ProdName', ProdName)
					SRP_JSON(objLot, 'SetValue', 'OrigWaferQty', LotRec<LOT_ORIG_WAFER_QTY$>)
					SRP_JSON(objLot, 'SetValue', 'WaferQty', LotRec<LOT_WAFER_QTY$>)
					SRP_JSON(objLot, 'SetValue', 'VendorPartNo', LotRec<LOT_VENDOR_PART_NO$>)
					SRP_JSON(objLot, 'SetValue', 'VendorLotNo', LotRec<LOT_VENDOR_LOT_NO$>)
					SRP_JSON(objLot, 'SetValue', 'Vendor', LotRec<LOT_VENDOR_CODE$>)
					CurrOperation = Lot_Services('GetLotCurrOperationId', LotId)
					CurrOperation = XLATE('LOT_OPERATION', CurrOperation, LOT_OPERATION_OPERATION_ID$, 'X')
					SRP_JSON(objLot, 'SetValue', 'CurrOperation', CurrOperation)
					MostRecentEventId = LotRec<LOT_MOST_RECENT_LOT_EVENT_ID$>
					MostRecentEventDtmIConv = Xlate('LOT_EVENT', MostRecentEventId, LOT_EVENT_EVENT_DATETIME$, 'X')
					MostRecentEventDtmOConv = OConv(MostRecentEventDtmIConv, 'DT')
					SRP_JSON(objLot, 'SetValue', 'MostRecentEventDateTime', MostRecentEventDtmOConv)
					If FullObject then
						// Events Array
						EventsArrayJson     = ''
						If SRP_Json(EventsArrayJson, 'New', 'Array') then
							LotEventKeys = Lot_Event_Services('GetLotEventsInSequence', LotId)
							for each LotEventKey in LotEventKeys using @FM
								objEvent = ''
								EventRec = Database_Services('ReadDataRow', 'LOT_EVENT', LotEventKey)
								If SRP_Json(objEvent, 'New', 'Object') then
									SRP_JSON(objEvent, 'SetValue', 'LotEventId', LotEventKey)
									SRP_JSON(objEvent, 'SetValue', 'LotId', EventRec<LOT_EVENT_LOT_ID$>)
									SRP_JSON(objEvent, 'SetValue', 'LotEventType', EventRec<LOT_EVENT_LOT_EVENT_TYPE$>)
									SRP_JSON(objEvent, 'SetValue', 'EventDatetime', OConv(EventRec<LOT_EVENT_EVENT_DATETIME$>, 'DT'))
									SRP_JSON(objEvent, 'SetValue', 'EventNote', EventRec<LOT_EVENT_EVENT_NOTE$>)
									SRP_JSON(objEvent, 'SetValue', 'EquipmentId', EventRec<LOT_EVENT_EQUIPMENT_ID$>)
									SRP_JSON(objEvent, 'SetValue', 'EventReduceWaferQty', EventRec<LOT_EVENT_EVENT_REDUCE_WAFER_QTY$>)
									SRP_JSON(objEvent, 'SetValue', 'EventBonusWaferQty', EventRec<LOT_EVENT_EVENT_BONUS_WAFER_QTY$>)
									SRP_JSON(objEvent, 'SetValue', 'EventBeginWaferQty', EventRec<LOT_EVENT_EVENT_BEGIN_WAFER_QTY$>)
									SRP_JSON(objEvent, 'SetValue', 'EventEndWaferQty', EventRec<LOT_EVENT_EVENT_END_WAFER_QTY$>)
									SRP_JSON(objEvent, 'SetValue', 'EventOperationId', EventRec<LOT_EVENT_EVENT_OPERATION_ID$>)
									SRP_JSON(objEvent, 'SetValue', 'EventOperatorId', EventRec<LOT_EVENT_EVENT_OPERATOR_ID$>)
									SRP_JSON(objEvent, 'SetValue', 'Sequence', EventRec<LOT_EVENT_SEQUENCE$>)
									SRP_JSON(EventsArrayJson, 'Add', objEvent)
									SRP_JSON(objEvent, 'Release')
								end
							Next LotEventKey
							SRP_JSON(objLot, 'Set', 'LotEvents', EventsArrayJson)
							SRP_JSON(EventsArrayJson, 'Release')
						end else
							ErrorMessage = 'Error Creating Events JSON Array'
						end
						// Operations Array
						OperationsArrayJson = ''
						If SRP_Json(OperationsArrayJson, 'New', 'Array') then
							LotOperationKeys = Lot_Services('GetLotOperationSequence', LotId)
							for each LotOperationKey in LotOperationKeys using @FM
								objOperation = ''
								OperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', LotOperationKey)
								If SRP_Json(objOperation, 'New', 'Object') then
									SRP_JSON(objOperation, 'SetValue', 'LotOperationId', LotOperationKey)
									SRP_JSON(objOperation, 'SetValue', 'LotId', OperationRec<LOT_OPERATION_LOT_ID$>)
									SRP_JSON(objOperation, 'SetValue', 'OperationId', OperationRec<LOT_OPERATION_OPERATION_ID$>)
									SRP_JSON(objOperation, 'SetValue', 'DatetimeIn', OConv(OperationRec<LOT_OPERATION_DATETIME_IN$>, 'DT'))
									SRP_JSON(objOperation, 'SetValue', 'DatetimeOut', Oconv(OperationRec<LOT_OPERATION_DATETIME_OUT$>, 'DT'))
									SRP_JSON(objOperation, 'SetValue', 'EquipmentId', OperationRec<LOT_OPERATION_EQUIPMENT_ID$>)
									SRP_JSON(objOperation, 'SetValue', 'WaferInQty', OperationRec<LOT_OPERATION_WAFER_IN_QTY$>)
									SRP_JSON(objOperation, 'SetValue', 'WaferOutQty', OperationRec<LOT_OPERATION_WAFER_OUT_QTY$>)
									SRP_JSON(objOperation, 'SetValue', 'OperatorInId', OperationRec<LOT_OPERATION_OPERATOR_IN_ID$>)
									SRP_JSON(objOperation, 'SetValue', 'OperatorOutId', OperationRec<LOT_OPERATION_OPERATOR_OUT_ID$>)
									SRP_JSON(objOperation, 'SetValue', 'OperationSequence', OperationRec<LOT_OPERATION_OPERATION_SEQUENCE$>)
									SRP_JSON(objOperation, 'SetValue', 'Rework', OperationRec<LOT_OPERATION_REWORK$>)
									SRP_JSON(objOperation, 'SetValue', 'DatetimeStart', OConv(OperationRec<LOT_OPERATION_DATETIME_START$>, 'DT'))
									SRP_JSON(objOperation, 'SetValue', 'DatetimeStop', OConv(OperationRec<LOT_OPERATION_DATETIME_STOP$>, 'DT'))
									SRP_JSON(OperationsArrayJson, 'Add', objOperation)
									SRP_JSON(objOperation, 'Release')
								end
								
							Next LotOperationKey
							SRP_JSON(objLot, 'Set', 'LotOperations', OperationsArrayJson)
							SRP_JSON(OperationsArrayJson, 'Release')
						end else
							ErrorMessage = 'Error Creating Operations JSON Array'
						end
					end
					
					SRP_JSON(objJSON, 'Set', 'Lot', objLot)
					SRP_JSON(objLot, 'Release')
				end else
					ErrorMessage = 'Error creating new Lot Json Object'
				end
			end else
				ErrorMessage = 'Error reading ':LotId:' from lot table.'
			end
			JsonString = SRP_JSON(objJSON, 'Stringify', 'Styled')
			SRP_JSON(objJSON, 'Release')
		end else
			ErrorMessage = 'Error creating new Json Object'
		end
	end else
		ErrorMessage = 'Invalid or null lot number passed to routine.'
	end
	
	If ErrorMessage EQ '' then
		Response = JsonString
	end else
		Error_Services('Add', ErrorMessage)    	
	end
	
end service


Service OpenLot(LotId)
	
	StartTick = GetTickCount()
	MetricName = 'OpenLot'
	
	ErrorMessage = ''
	If RowExists('LOT', LotId) then
		LotRec            = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
		LotRec<LOT_OPEN$> = True$
		Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
		If Error_Services('NoError') then
			Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'OPEN', 'Lot status set to Open.', '', 'SYSTEM')									 
		end else
			ErrorMessage = 'Error setting lot ' : LotId : ' to open.' : Error_Services('GetMessage')
		end
	end else
		ErrorMessage = 'Unable to Open Lot ' : LotId : '. Lot ID was not found in LOT table.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage NE ''  then Error_Services('Add', ErrorMessage)
	
end service


Service CloseLot(LotId)
	
	StartTick    = GetTickCount()
	MetricName   = 'CloseLot'
	ErrorMessage = ''
	If RowExists('LOT', LotId) then
		LotRec            = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
		LotRec<LOT_OPEN$> = False$
		Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
		If Error_Services('NoError') then
			Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'CLOSE', 'Lot status set to Closed', '', 'SYSTEM')
		end else
			ErrorMessage = 'Error setting lot ' : LotId : ' to closed.' : Error_Services('GetMessage')    
		end
	end else
		ErrorMessage = 'Unable to Close Lot ' : LotId : '. Lot ID was not found in LOT table.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


Service AutoCloseTestWaferLot(LotId, CloseUserId)
	
	AutoCloseTime = Datetime()
	ErrorMessage = ''
	If MemberOf(CloseUserId, 'LEAD') OR MemberOf(CloseUserId, 'SUPERVISOR') OR CloseUserId EQ 'SYSTEM' then
		LotOperations = Lot_Services('GetLotOperationSequence', LotId)
		for LotOperationIndex = 1 to DCount(LotOperations, @FM)
			ThisLotOperationId = LotOperations<LotOperationIndex>
			ThisOperationCompleted = Lot_Services('IsOperationCompleted', ThisLotOperationId)
			If Error_Services('NoError') then
				if Not(ThisOperationCompleted) then
					ThisLotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotOperationId)
					if Error_Services('NoError') then
						CurrLotQty = Database_Services('ReadDataColumn', 'LOT', LotId, LOT_WAFER_QTY$, True$, 0, False$)
						If ThisLotOperationRec<LOT_OPERATION_DATETIME_IN$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_DATETIME_IN$> = AutoCloseTime
						end
						If ThisLotOperationRec<LOT_OPERATION_DATETIME_OUT$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_DATETIME_OUT$> = AutoCloseTime
						end
						if ThisLotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = CloseUserId
						end
						if ThisLotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = CloseUserId
						end
						if ThisLotOperationRec<LOT_OPERATION_DATETIME_START$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_DATETIME_START$> = AutoCloseTime
						end
						if ThisLotOperationRec<LOT_OPERATION_DATETIME_STOP$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_DATETIME_STOP$> = AutoCloseTime
						end
						If ThisLotOperationRec<LOT_OPERATION_WAFER_IN_QTY$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_WAFER_IN_QTY$> = CurrLotQty
						end
						If ThisLotOperationRec<LOT_OPERATION_WAFER_OUT_QTY$> EQ '' then
							ThisLotOperationRec<LOT_OPERATION_WAFER_OUT_QTY$> = CurrLotQty
						end
						Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotOperationId, ThisLotOperationRec, True$, False$, False$)
						If Error_Services('HasError') then
							ErrorMessage = Error_Services('GetMessage')
						end
					end else
						ErrorMessage = Error_Services('GetMessage')
					end
				end
			end else
				ErrorMessage = Error_Services('GetMessage')
			end
		Next LotOperationIndex
	end else
		ErrorMessage = CloseUserId : ' does not have permission to close this lot.'
	end
	If ErrorMessage EQ ''  then
		// Close Lot as there were no validation failures.
		Lot_Services('CloseLot', LotId)
		If Error_Services('NoError') then
			LogData    = ''
			LogData<1> = LoggingDTM
			LogData<2> = LotId
			LogData<3> = CloseUserId
			LogData<4> = 'Successfully marked lot as closed.'
			Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
		end else
			ErrorMessage = Error_Services('GetMessage')
			LogData    = ''
			LogData<1> = LoggingDTM
			LogData<2> = LotId
			LogData<3> = CloseUserId
			LogData<4> = 'Error marking lot as closed.' : ErrorMessage
			Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
			// Send a message to FI
			Recipients   = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
			SentFrom     = 'SYSTEM'
			Subject      = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
			Message      = 'Error in ' : service : ' with lot id ' : LotId : ' attempting to set CLOSE flag on lot. ' : ErrorMessage
			Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
			Error_Services('Add', 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage)
		end
	end else
		ErrorMessage = 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage
		LogData    = ''
		LogData<1> = LoggingDTM
		LogData<2> = LotId
		LogData<3> = CloseUserId
		LogData<4> = 'Error marking lot as closed.' : ErrorMessage
		Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
		// Send a message to FI
		Recipients   = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
		SentFrom     = 'SYSTEM'
		Subject      = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
		Message      = 'Error in ' : service : ' with lot id ' : LotId : ' attempting to Auto Close Lot. ' : ErrorMessage
		Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
		Error_Services('Add', 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage)
	end
	
end service


Service HoldLot(LotId, OperatorId)
	
	StartTick = GetTickCount()
	MetricName = 'HoldLot'
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
end service


Service UnholdLot(LotId, OperatorId)
	
	StartTick = GetTickCount()
	MetricName = 'UnholdLot'
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
end service


Service ReduceLotWaferCount(LotId, ReductionQty, OperatorId)
	
	StartTick = GetTickCount()
	MetricName = 'ReduceLotWaferCount'
	
	ErrorMessage = ''
	If RowExists('LOT', LotId) then
		LotRec        = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
		LotType		  = LotRec<LOT_TYPE$>
		LotHold       = LotRec<LOT_HOLD$>
		LotOpen       = LotRec<LOT_OPEN$>
		LotCurrWfrQty = LotRec<LOT_WAFER_QTY$>
		LotNewWfrQty  = LotCurrWfrQty - ReductionQty
		If LotNewWfrQty LE 25 AND LotNewWfrQty GE 0 then
			LotRec<LOT_WAFER_QTY$> = LotNewWfrQty
			Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
			If Error_Services('NoError') then
				// Write Lot Event
				Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'REDUCE_WAFER_QTY', 'Reduced wafer count by ' : ReductionQty, '', OperatorId, False$, '')
				if LotNewWfrQty EQ 0  AND LotType EQ 'TW' then
					ServiceParms = 'AutoCloseTestWaferLot' : @VM : LotId : @VM : 'SYSTEM'
					Service_Services('PostProcedure', 'LOT_SERVICES', ServiceParms)
					If Error_Services('HasError') then
						Recipients   = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
						SentFrom     = 'SYSTEM'
						Subject      = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
						Message      = 'Error in ' : service : ' attempting to add auto lot closure for lot id ' : LotId : ' to the service queue.'
						AttachWindow = ''
						AttachKeys   = ''
						SendToGroup  = ''
						Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
					end
				end
			end else
				ErrorMessage = 'Error in Increase Lot Wafer Count service, Error writing Lot Id ' : LotId : ' with new quantity.'
			end
		end else
			Begin Case
				Case LotNewWfrQty GT 25
					ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity great than 25.'
				Case LotNewWfrQty LT 0
					ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity less than 0.'
			End Case
		end
	end else
		ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' not found in lot table.' 
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
	
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


Service IncreaseLotWaferCount(LotId, IncreaseQty, OperatorId)
	
	StartTick = GetTickCount()
	MetricName = 'IncreaseLotWaferCount'
	
	ErrorMessage = ''
	If RowExists('LOT', LotId) then
		LotRec        = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
		LotHold       = LotRec<LOT_HOLD$>
		LotOpen       = LotRec<LOT_OPEN$>
		if LotOpen then
			If Not(LotHold) then
				LotCurrWfrQty = LotRec<LOT_WAFER_QTY$>
				LotNewWfrQty  = LotCurrWfrQty + IncreaseQty
				
				If LotNewWfrQty LE 25 AND LotNewWfrQty GT 0 then
					LotRec<LOT_WAFER_QTY$> = LotNewWfrQty
					Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
					If Error_Services('NoError') then
						// Write Lot Event
						Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'INCREASE_WAFER_QTY', 'Increased wafer count by ' : IncreaseQty, '', OperatorId, False$, '')
					end else
						ErrorMessage = 'Error in Increase Lot Wafer Count service, Error writing Lot Id ' : LotId : ' with new quantity.' 
					end
				end else
					Begin Case
						Case LotNewWfrQty GT 25
							ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity great than 25.'
						Case LotNewWfrQty LT 0
							ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity less than 0.'
					End Case
				end    
			end else
				ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' is currently on hold.'
			end
		end else
			ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' is closed.'
		end
		
	end else
		ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' not found in lot table.' 
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
	
end service


Service OpenOIWizardCreateTWLotInBrowser()
	
	Command = 'explorer https://goto.infineon.com/oiwizard/Lot/CreateTestWaferLot/'
	SRP_Run_Command(Command)
	
end service


Service CreateNewVoidedLotRecord(LotId, LegacyLotId, LotType=LOT_TYPES, Username)
	
	StartTick = GetTickCount()
	MetricName = 'CreateNewVoidedLotRecord'
	
	ErrorMessage = ''
	If RowExists('LSL_USERS', Username) then
		If LotType NE '' then
			NewVoidedLotRecordId = RTI_CreateGUID()
			If Not(RowExists('VOIDED_LOT', NewVoidedLotRecordId)) then
				NewVoidedLotRec = ''
				Begin Case
					Case LotType EQ 'RDS'
						WONo = XLate('RDS', LegacyLotId, RDS_WO$, 'X')
						CassNo = XLATE('RDS', LotId, RDS_CASS_NO$, 'X')
						WoMatKey = WONo : '*' : CassNo
						If RowExists('RDS', LegacyLotId) then
							WoNo = Field(LotId, '*', 1)
							NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
							NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'RDS'
							NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
						end else
							ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. RDS record not found.'
						end
					Case LotType EQ 'WO_MAT'
						If RowExists('WO_MAT', LegacyLotId) then
							WoNo = Field(LotId, '*', 1)
							NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
							NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WO_MAT'
							NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
						end else
							ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WoMat record not found.'
						end
					Case LotType EQ 'WM_IN'
						If RowExists('WM_IN', LegacyLotId) then
							WoNo = Field(LotId, '*', 1)
							NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
							NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WM_IN'
							NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
						end else
							ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WM_IN record not found.'
						end
					Case LotType EQ 'WM_OUT'
						If RowExists('WM_OUT', LegacyLotId) then
							WoNo = Field(LotId, '*', 1)
							NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
							NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WM_OUT'
							NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
						end else
							ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WM_OUT record not found.'
						end
					Case Otherwise$
						ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. Non supported lot type.'
				End Case
				If ErrorMessage EQ '' then
					NewVoidedLotRec<VOIDED_LOT_VOID_BY$> = Username
					NewVoidedLotRec<VOIDED_LOT_VOID_DTM$> = Datetime()
					NewVoidedLotRec<VOIDED_LOT_LOT_ID$> = LotId
					Database_Services('WriteDataRow', 'VOIDED_LOT', NewVoidedLotRecordId, NewVoidedLotRec)
					If Error_Services('HasError') then
						ErrorMessage = Error_Services('GetMessage')
					end
				end
			end else
				ErrorMessage = 'Go buy a lottery ticket, we ran into a GUID collision with an existing GUID ' : NewVoidedLotRecordId : ' when trying to create a Voided Lot record for ' : LotId
			end
		end else
			ErrorMessage = 'Null lot type of passed to CreateVoidedLotRecord routine.'
		end
	end else
		ErrorMessage = 'Username ' : Username : ' passed to CreateVoidedLotRecord routine does not exist.'
	end
	
	EndTick = GetTickCount()
	Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)    
	
	If ErrorMessage NE ''  then Error_Services('Add', ErrorMessage)
	
end service

//----------------------------------------------------------------------------------------------------------------------
// Internal GoSubs
//----------------------------------------------------------------------------------------------------------------------



