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

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
$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

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] : ' 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'
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'
	
	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)
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
    
    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
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
        Error_Services('Add', ErrorMessage)
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = ProdName
        LogData<3> = Username
        LogData<4> = ErrorMessage
        Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
    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
end service

Service GetPrescribedOperationsByProdId(ProdId, ProdType)
    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$
                    //error, no matching prod type.
            End Case
        end else
            //Error: ProdID was null
        end
    Response = ProdOperationKeys
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 = 'Lot Operation already existed, cannot overwrite'
                end
                
            Next Operation
        end else
            ErrorMessage = 'Error getting prescribed operations for lot# ' : LotId
        end

    end else
        ErrorMessage = 'Lot ID was null'
    end
    If ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end
end service

//Returns a @FM delimited list of operations in sequence
Service GetLotOperationSequence(LotId)
	StartTick = GetTickCount()
    MetricName = 'GetLotOperationSequence'
	
    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
        //error: lot id was null
    end
    Response = LotOperationsInSequence
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
end service

Service GetLotCurrOperationId(LotId)
	StartTick = GetTickCount()
    MetricName = 'GetLotCurrOperationId'
	
    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
        //error: lot id was null
    end
    Response = CurrOperation
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
end service

Service GetLotCurrOperationName(LotId)
	StartTick = GetTickCount()
    MetricName = 'GetLotCurrOperationName'
	
    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
        //error: lot id was null
    end
    Response = CurrOperationName
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
                        //Error: Lot Operation already existed, cannot overwrite
                    end
                end
            end else
                //Error: Not allowed to add new operations prior to current operation
            end
        end else
            //Error: null or invalid sequence passed to routine
        end
    end else
        //Error: Lot id was null
    end
    If ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end
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$)
        If CurrOperDtmIn LE Datetime() AND CurrOperDtmIn NE '' then
            Response = True$
        end else
            Response = False$
        end
    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 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)
                            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
     If ErrorMessage NE '' 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$)
         Error_Services('Add', ErrorMessage)
     end
     
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
	If ErrorMessage NE '' 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$)
		Error_Services('Add', ErrorMessage)
	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
	
	EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
end service

Service ConvertLotRecordToJson(LotId, ItemURL, CurrUser, FullObject=BOOLEAN)

    ErrorMessage = ''
    JsonString   = ''
    If FullObject EQ '' then
        FullObject = True$
    end
    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 NE '' then
        Error_Services('Add', ErrorMessage)
    end
    Response = JsonString
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
    If ErrorMessage NE ''  then
        Error_Services('Add', ErrorMessage)
    end
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
    If ErrorMessage NE ''  then
        Error_Services('Add', ErrorMessage)
    end
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
	if ErrorMessage NE '' then
		Error_Services('Add', ErrorMessage)
	end
	
	EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
    if ErrorMessage NE '' then
        Error_Services('Add', ErrorMessage)
    end
    
    EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
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
	If ErrorMessage NE ''  then
		//Todo Log Error Message
	end
	
	EndTick = GetTickCount()
    Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
end service

