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 = LotType LotRec = '' LotRec = LotQty LotRec = LotQty LotRec = VendorPartNo LotRec = VendorLotNo LotRec = VendorCode LotRec = 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 EQ '' AND LotRec EQ '' AND LotRec EQ '' AND LotRec EQ '' then LotRec = LotType LotRec = TWProdID LotRec = LotQty LotRec = LotQty LotRec = VendorPartNo LotRec = VendorLotNo LotRec = 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 EQ '' AND LotRec EQ '' AND LotRec EQ '' AND LotRec EQ '' then LotRec = LotType LotRec = TWProdID LotRec = LotQty LotRec = LotQty LotRec = VendorPartNo LotRec = VendorLotNo LotRec = 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 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 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 ProdId = LotRec 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 OperationSequence = ProdOperationRec LotOperationRecID = Rti_Createguid() If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then LotOperationRec = '' LotOperationRec = LotId LotOperationRec = OperationID LotOperationRec = OperationSequence LotOperationRec = 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 = 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 If ThisOperationSequence GE NewSequence then NewOperationSequence = ThisOperationSequence + 1 ThisOperationRec = 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 = LotId LotOperationRec = NewOperationId LotOperationRec = NewSequence LotOperationRec = 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 //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 = Datetime() ThisLotCurrOperationRec = WaferQty ThisLotCurrOperationRec = 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 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 = Datetime() ThisLotCurrOperationRec = WaferQty ThisLotCurrOperationRec = 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) SRP_JSON(objLot, 'SetValue', 'ProdId', LotRec) Begin Case Case LotRec = 'TW' ProdName = XLATE('TEST_WAFER_PROD', LotRec, TEST_WAFER_PROD_PART_NAME$, 'X') Case Otherwise$ ProdName = '' End Case SRP_JSON(objLot, 'SetValue', 'ProdName', ProdName) SRP_JSON(objLot, 'SetValue', 'OrigWaferQty', LotRec) SRP_JSON(objLot, 'SetValue', 'WaferQty', LotRec) SRP_JSON(objLot, 'SetValue', 'VendorPartNo', LotRec) SRP_JSON(objLot, 'SetValue', 'VendorLotNo', LotRec) SRP_JSON(objLot, 'SetValue', 'Vendor', LotRec) CurrOperation = Lot_Services('GetLotCurrOperationId', LotId) CurrOperation = XLATE('LOT_OPERATION', CurrOperation, LOT_OPERATION_OPERATION_ID$, 'X') SRP_JSON(objLot, 'SetValue', 'CurrOperation', CurrOperation) MostRecentEventId = LotRec 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) SRP_JSON(objEvent, 'SetValue', 'LotEventType', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventDatetime', OConv(EventRec, 'DT')) SRP_JSON(objEvent, 'SetValue', 'EventNote', EventRec) SRP_JSON(objEvent, 'SetValue', 'EquipmentId', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventReduceWaferQty', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventBonusWaferQty', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventBeginWaferQty', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventEndWaferQty', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventOperationId', EventRec) SRP_JSON(objEvent, 'SetValue', 'EventOperatorId', EventRec) SRP_JSON(objEvent, 'SetValue', 'Sequence', EventRec) 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) SRP_JSON(objOperation, 'SetValue', 'OperationId', OperationRec) SRP_JSON(objOperation, 'SetValue', 'DatetimeIn', OConv(OperationRec, 'DT')) SRP_JSON(objOperation, 'SetValue', 'DatetimeOut', Oconv(OperationRec, 'DT')) SRP_JSON(objOperation, 'SetValue', 'EquipmentId', OperationRec) SRP_JSON(objOperation, 'SetValue', 'WaferInQty', OperationRec) SRP_JSON(objOperation, 'SetValue', 'WaferOutQty', OperationRec) SRP_JSON(objOperation, 'SetValue', 'OperatorInId', OperationRec) SRP_JSON(objOperation, 'SetValue', 'OperatorOutId', OperationRec) SRP_JSON(objOperation, 'SetValue', 'OperationSequence', OperationRec) SRP_JSON(objOperation, 'SetValue', 'Rework', OperationRec) SRP_JSON(objOperation, 'SetValue', 'DatetimeStart', OConv(OperationRec, 'DT')) SRP_JSON(objOperation, 'SetValue', 'DatetimeStop', OConv(OperationRec, '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 = 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 = 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 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 EQ '' then ThisLotOperationRec = AutoCloseTime end If ThisLotOperationRec EQ '' then ThisLotOperationRec = AutoCloseTime end if ThisLotOperationRec EQ '' then ThisLotOperationRec = CloseUserId end if ThisLotOperationRec EQ '' then ThisLotOperationRec = CloseUserId end if ThisLotOperationRec EQ '' then ThisLotOperationRec = AutoCloseTime end if ThisLotOperationRec EQ '' then ThisLotOperationRec = AutoCloseTime end If ThisLotOperationRec EQ '' then ThisLotOperationRec = CurrLotQty end If ThisLotOperationRec EQ '' then ThisLotOperationRec = 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 LotHold = LotRec LotOpen = LotRec LotCurrWfrQty = LotRec LotNewWfrQty = LotCurrWfrQty - ReductionQty If LotNewWfrQty LE 25 AND LotNewWfrQty GE 0 then LotRec = 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 LotOpen = LotRec if LotOpen then If Not(LotHold) then LotCurrWfrQty = LotRec LotNewWfrQty = LotCurrWfrQty + IncreaseQty If LotNewWfrQty LE 25 AND LotNewWfrQty GT 0 then LotRec = 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 = WoNo NewVoidedLotRec = 'RDS' NewVoidedLotRec = 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 = WoNo NewVoidedLotRec = 'WO_MAT' NewVoidedLotRec = 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 = WoNo NewVoidedLotRec = 'WM_IN' NewVoidedLotRec = 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 = WoNo NewVoidedLotRec = 'WM_OUT' NewVoidedLotRec = 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 = Username NewVoidedLotRec = Datetime() NewVoidedLotRec = 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 //----------------------------------------------------------------------------------------------------------------------