Added in a check for the active flag when adding an operation to a lot. Added in material handler group to the CanUserModifyLot check. Given the addition of a check for the active flag to allow adding an operation. I checked all OPERATION records to ensure that flag has already been set. The only operations that had a value other than true were the OPERATION records related to Return To Fab Lot processing. Tested and verified creating test wafer lots, and creating RTF forms.
1619 lines
72 KiB
Plaintext
1619 lines
72 KiB
Plaintext
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
|
|
|
|
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, Lot_Operation_Services
|
|
Declare function PSN_Services, Return_To_Fab_Services
|
|
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
|
|
$Insert RDS_EQUATES
|
|
$Insert WO_LOG_EQUATES
|
|
$Insert PROD_VER_EQUATES
|
|
$Insert OPERATION_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] : ' 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'
|
|
objRunLog = 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', 'SYSTEM_COMMENT'
|
|
Options LOT_TYPES = 'TW', 'RDS', 'WM_OUT', 'WM_IN', 'WO_MAT', 'LOT'
|
|
Options LEGACY_LOT_TYPES = 'RDS', 'WM_OUT', 'WM_IN', 'WO_MAT'
|
|
|
|
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=LEGACY_LOT_TYPES)
|
|
StartTick = GetTickCount()
|
|
MetricName = 'GetLotIdByLegacyLotIdAndType'
|
|
|
|
ErrorMsg = ''
|
|
Open 'DICT.LOT' to DictLot then
|
|
|
|
SearchString = ''
|
|
SearchString := 'LEGACY_LOT_ID':@VM:LegacyLotId:@FM
|
|
SearchString := 'LEGACY_LOT_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
|
|
|
|
end service
|
|
|
|
|
|
Service CreateNewLot(LotType, ProdName, LotQty, VendorPartNo, VendorLotNo, VendorCode, Username, PrinterID, LegacyLotId)
|
|
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'
|
|
If LegacyLotId NE '' then
|
|
LegacyLotType = LotType
|
|
LotId = Lot_Services('GetLotIdByLegacyLotIdAndType', LegacyLotId, LegacyLotType)
|
|
If LotId EQ '' then
|
|
LotType = 'PROD'
|
|
// Case statement for legacy lot entity types
|
|
NewLotId = Lot_Services('GenerateNewLotId', LegacyLotType)
|
|
If NewLotId NE '' then
|
|
If RowExists('LOT', NewLotId) NE False$ then
|
|
WoNo = ''
|
|
EpiPartNo = ''
|
|
ProdVerNo = ''
|
|
Begin Case
|
|
Case LegacyLotType EQ 'RDS'
|
|
WoNo = XLATE('RDS', LegacyLotId, RDS_WO$, 'X')
|
|
Case LegacyLotType EQ 'WM_IN' OR LegacyLotType EQ 'WM_OUT' OR LegacyLotType EQ 'WO_MAT'
|
|
WoNo = Field(LegacyLotId, '*', 1)
|
|
End Case
|
|
|
|
ProdVerNo = XLATE('WO_LOG', WoNo, WO_LOG_PROD_VER_NO$, 'X')
|
|
EpiPartNo = XLATE('WO_LOG', WoNo, WO_LOG_EPI_PART_NO$, 'X')
|
|
ProdId = EpiPartNo : '*' : ProdVerNo
|
|
ProdSpecId = XLATE('WO_LOG', WoNo, WO_LOG_PROD_SPEC_ID$, 'X')
|
|
If ProdSpecId EQ '' then
|
|
Begin Case
|
|
Case LegacyLotType EQ 'RDS'
|
|
ProdSpecId = XLATE('RDS', LegacyLotId, RDS_PROD_SPEC_ID$, 'X')
|
|
Case Otherwise$
|
|
ProdSpecId = XLATE('PROD_VER', ProdVerNo, PROD_VER_PROC_STEP_PSN$, 'X')
|
|
End Case
|
|
end
|
|
If Not(RowExists('PRODUCT', ProdId)) then ProdId = ''
|
|
LotRec = ''
|
|
LotRec<LOT_TYPE$> = 'PROD'
|
|
LotRec<LOT_PROD_ID$> = ProdId
|
|
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$> = LegacyLotId
|
|
LotRec<LOT_LEGACY_LOT_TYPE$> = LegacyLotType
|
|
LotRec<LOT_WO_LOG_ID$> = WONo
|
|
LotRec<LOT_PROD_SPEC_ID$> = ProdSpecId
|
|
LotRec<LOT_EPI_PART_NO$> = EpiPartNo
|
|
LotRec<LOT_PROD_VER_NO$> = ProdVerNo
|
|
Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
|
|
If Error_Services('NoError') then
|
|
CreatedLotNumber = NewLotId
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. ':Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Failed to generate new LOT id. LOT record "':NewLotId:'" already exists.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Failed to generate new LOT id.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Lot Id ':LotId:' already exists for LegacyLotId ':LegacyLotId:'.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Null LegacyLotId passed in.'
|
|
end
|
|
Case LotType EQ 'TW'
|
|
If ProdName NE '' then
|
|
TWProdID = Test_Wafer_Prod_Services('GetTestWaferProdIDsByPartName', ProdName)
|
|
If TWProdID NE '' then
|
|
If DCount(TWProdID, @VM) EQ 1 then
|
|
NewLotId = Lot_Services('GenerateNewLotId', 'TW');//Don't use this
|
|
If NewLotId NE '' then
|
|
If RowExists('LOT', NewLotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', NewLotId)
|
|
// Ensure the lot record is empty
|
|
If LotRec<LOT_TYPE$> EQ '' AND LotRec<LOT_PROD_ID$> EQ '' AND LotRec<LOT_ORIG_WAFER_QTY$> EQ '' AND LotRec<LOT_WAFER_QTY$> EQ '' then
|
|
LotRec<LOT_TYPE$> = LotType
|
|
LotRec<LOT_PROD_ID$> = TWProdID
|
|
LotRec<LOT_ORIG_WAFER_QTY$> = LotQty
|
|
LotRec<LOT_WAFER_QTY$> = LotQty
|
|
LotRec<LOT_VENDOR_PART_NO$> = VendorPartNo
|
|
LotRec<LOT_VENDOR_LOT_NO$> = VendorLotNo
|
|
LotRec<LOT_VENDOR_CODE$> = VendorCode
|
|
Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
|
|
// Now Ensure that the written lot matches what was just written
|
|
LotRecCheck = Database_Services('ReadDataRow', 'LOT', NewLotId)
|
|
If LotRecCheck EQ LotRec then
|
|
// Lot Created successfully
|
|
CreatedLotNumber = NewLotId
|
|
If RowExists('LOT', CreatedLotNumber) then
|
|
Lot_Services('CreateInitialLotOperationRecords', CreatedLotNumber)
|
|
If Error_Services('NoError') then
|
|
// Check in at first operation
|
|
// Get Curr Operation(Should be first one in sequence)
|
|
ThisLotCurrOpId = Lot_Services('GetLotCurrOperationId', CreatedLotNumber)
|
|
If ThisLotCurrOpId NE '' then
|
|
// Set lot to open
|
|
Lot_Services('OpenLot', CreatedLotNumber)
|
|
if Error_Services('NoError') then
|
|
// Move lot in
|
|
Lot_Services('MoveInLot', CreatedLotNumber, Username)
|
|
if Error_Services('NoError') then
|
|
If PrinterID NE 'WEB' then
|
|
// If PrinterID is set to WEB this means the request comes from OI_Wizard and the client is going to handle printing.
|
|
Labeling_Services('PrintTestWaferLotLabel', CreatedLotNumber, Username, PrinterID)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : CreatedLotNumber : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end
|
|
Lot_Services('MoveOutLot', NewLotId, Username)
|
|
If Error_Services('NoError') then
|
|
Lot_Services('MoveInLot', NewLotId, Username)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
// Close LOT record as there was an error
|
|
Lot_Services('CloseLot', NewLotId)
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
// Close LOT record as there was an error
|
|
Lot_Services('CloseLot', NewLotId)
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, error getting current operation for lot: ' : NewLotId
|
|
end
|
|
end else
|
|
// Close LOT record as there was an error
|
|
// Database_Services('DeleteDataRow', 'LOT', NewLotId, True$, False$)
|
|
Lot_Services('CloseLot', NewLotId)
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot attributes did not write correctly for lot: ' : NewLotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot already had data, lot: ' : NewLotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Created lot: ' : NewLotId : ' not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, no lot id returned.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, ambiguous product passed to routine OR no matching products found.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, product(':ProdName:') passed to routine not found.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Null value passed in for ProdID'
|
|
end
|
|
Case Otherwise$
|
|
ErrorMessage = 'Error in ':Service:' service. Lot Type "':LotType:'" is not currently supported.'
|
|
End Case
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = ProdName
|
|
LogData<3> = Username
|
|
LogData<4> = 'Successfully created lot id ' : CreatedLotNumber : ' of product type ' : ProdName '.'
|
|
Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = ProdName
|
|
LogData<3> = Username
|
|
LogData<4> = ErrorMessage
|
|
Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
Response = CreatedLotNumber
|
|
|
|
End Service
|
|
|
|
|
|
Service CreateNewTestWaferLot(LotType, ProdName, LotQty, VendorPartNo, VendorLotNo, VendorCode, Username, PrinterID)
|
|
|
|
CreatedLotNumber = ''
|
|
ErrorMessage = ''
|
|
If LotType EQ 'TW' then
|
|
If ProdName NE '' then
|
|
TWProdID = Test_Wafer_Prod_Services('GetTestWaferProdIDsByPartName', ProdName)
|
|
If TWProdID NE '' then
|
|
If DCount(TWProdID, @VM) EQ 1 then
|
|
NewLotId = Lot_Services('GenerateNewLotId', 'TW')
|
|
If NewLotId NE '' then
|
|
If RowExists('LOT', NewLotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', NewLotId)
|
|
// Ensure the lot record is empty
|
|
If LotRec<LOT_TYPE$> EQ '' AND LotRec<LOT_PROD_ID$> EQ '' AND LotRec<LOT_ORIG_WAFER_QTY$> EQ '' AND LotRec<LOT_WAFER_QTY$> EQ '' then
|
|
LotRec<LOT_TYPE$> = LotType
|
|
LotRec<LOT_PROD_ID$> = TWProdID
|
|
LotRec<LOT_ORIG_WAFER_QTY$> = LotQty
|
|
LotRec<LOT_WAFER_QTY$> = LotQty
|
|
LotRec<LOT_VENDOR_PART_NO$> = VendorPartNo
|
|
LotRec<LOT_VENDOR_LOT_NO$> = VendorLotNo
|
|
LotRec<LOT_VENDOR_CODE$> = VendorCode
|
|
Database_Services('WriteDataRow', 'LOT', NewLotId, LotRec)
|
|
// Now Ensure that the written lot matches what was just written
|
|
LotRecCheck = Database_Services('ReadDataRow', 'LOT', NewLotId)
|
|
If LotRecCheck EQ LotRec then
|
|
// Lot Created successfully
|
|
CreatedLotNumber = NewLotId
|
|
If RowExists('LOT', CreatedLotNumber) then
|
|
Lot_Services('CreateInitialLotOperationRecords', CreatedLotNumber)
|
|
If Error_Services('NoError') then
|
|
// Check in at first operation
|
|
// Get Curr Operation(Should be first one in sequence)
|
|
ThisLotCurrOpId = Lot_Services('GetLotCurrOperationId', CreatedLotNumber)
|
|
If ThisLotCurrOpId NE '' then
|
|
Lot_Services('MoveInLot', NewLotId, Username)
|
|
if Error_Services('NoError') then
|
|
// Set lot to open
|
|
Lot_Services('OpenLot', CreatedLotNumber)
|
|
if Error_Services('NoError') then
|
|
If PrinterID NE 'WEB' then
|
|
// If PrinterID is set to WEB this means the request comes from OI_Wizard and the client is going to handle printing.
|
|
Labeling_Services('PrintTestWaferLotLabel', CreatedLotNumber, Username, PrinterID)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : CreatedLotNumber : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end
|
|
Lot_Services('MoveOutLot', NewLotId, Username)
|
|
If Error_Services('NoError') then
|
|
Lot_Services('MoveInLot', NewLotId, Username)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, error getting current operation for lot: ' : NewLotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, lot id: ' : NewLotId : ' , ' : Error_Services('GetMessage')
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot attributes did not write correctly for lot: ' : NewLotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Lot already had data, lot: ' : NewLotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, Created lot: ' : NewLotId : ' not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, no lot id returned.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, ambiguous product passed to routine OR no matching products found.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create New Test Wafer Lot Process, product(':ProdName:') passed to routine not found.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Null value passed in for ProdID'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Lot type was not test wafer'
|
|
end
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = ProdName
|
|
LogData<3> = Username
|
|
LogData<4> = 'Successfully created lot id ' : CreatedLotNumber : ' of product type ' : ProdName '.'
|
|
Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = ProdName
|
|
LogData<3> = Username
|
|
LogData<4> = ErrorMessage
|
|
Logging_Services('AppendLog', objTWCreationLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
Response = CreatedLotNumber
|
|
|
|
End Service
|
|
|
|
|
|
Service GenerateInitialLotOperationRecords(LotId)
|
|
|
|
ErrorMessage = ''
|
|
If LotID NE '' then
|
|
if RowExists('LOT', LotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', LotId)
|
|
ProdID = LotRec<LOT_PROD_ID$>
|
|
If ProdID NE '' then
|
|
// Get product operations
|
|
ThisLotOperations = Lot_Services('GetPrescribedOperationsByProdId', ProdId)
|
|
If ThisLotOperations NE '' then
|
|
for each ProdOperationKey in ThisLotOperations using @FM
|
|
OperationRec = Database_Services('ReadDataRow', 'PRODUCT_OPERATION', ProdOperationKey)
|
|
Next operation
|
|
end else
|
|
ErrorMessage = 'No Operations found for ' : ProdId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Prod ID not specified'
|
|
end
|
|
// ID will be LotNum + OperationID
|
|
// Get product operations
|
|
end else
|
|
ErrorMessage = 'Lot ID does not exist.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Lot ID was null'
|
|
end
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service GetPrescribedOperationsByProdId(ProdId, ProdType)
|
|
|
|
ErrorMsg = ''
|
|
ProdOperationKeys = ''
|
|
If ProdId NE '' then
|
|
Begin Case
|
|
Case ProdType = 'TW'
|
|
ProdRec = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', ProdId)
|
|
ProdOperationKeys = ProdRec<TEST_WAFER_PROD_PRODUCT_OPERATIONS$>
|
|
Case Otherwise$
|
|
ErrorMsg = 'Error in ':Service:' service. No matching prod type.'
|
|
End Case
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ProdId passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = ProdOperationKeys
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service CreateInitialLotOperationRecords(LotId)
|
|
ErrorMessage = ''
|
|
If LotId NE '' then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', LotId)
|
|
LotType = LotRec<LOT_TYPE$>
|
|
ProdId = LotRec<LOT_PROD_ID$>
|
|
ThisInitialProdOperations = Lot_Services('GetPrescribedOperationsByProdId', ProdId, LotType)
|
|
If Error_Services('NoError') AND ThisInitialProdOperations NE '' then
|
|
For each ProdOperation in ThisInitialProdOperations using @VM
|
|
|
|
ProdOperationRec = Database_Services('ReadDataRow', 'PRODUCT_OPERATION', ProdOperation)
|
|
OperationID = ProdOperationRec<PRODUCT_OPERATION_OPERATION_ID$>
|
|
OperationSequence = ProdOperationRec<PRODUCT_OPERATION_OPERATION_SEQUENCE$>
|
|
|
|
LotOperationRecID = Rti_Createguid()
|
|
If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then
|
|
LotOperationRec = ''
|
|
LotOperationRec<LOT_OPERATION_LOT_ID$> = LotId
|
|
LotOperationRec<LOT_OPERATION_OPERATION_ID$> = OperationID
|
|
LotOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = OperationSequence
|
|
LotOperationRec<LOT_OPERATION_REWORK$> = False$
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationRecId, LotOperationRec)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = 'Error Writing Lot Operation Record.'
|
|
end
|
|
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'
|
|
ErrorMsg = ''
|
|
LotOperationsInSequence = ''
|
|
If LotID NE '' then
|
|
// Get Operations
|
|
LotOperations = Xlate('LOT', LotId, LOT_LOT_OPERATIONS$, 'X')
|
|
for each LotOperation in LotOperations using @VM
|
|
ThisLotOperationSequence = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_OPERATION_SEQUENCE$, 'X')
|
|
LotOperationsInSequence<ThisLotOperationSequence> = LotOperation
|
|
Next LotOperation
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = LotOperationsInSequence
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetLotCurrOperationId(LotId)
|
|
|
|
ErrorMsg = ''
|
|
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
|
|
ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service'
|
|
end
|
|
Response = CurrOperation
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
|
|
|
|
end service
|
|
|
|
|
|
Service GetLotCurrOperationName(LotId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'GetLotCurrOperationName'
|
|
ErrorMsg = ''
|
|
CurrOperationId = ''
|
|
CurrOperationName = ''
|
|
If LotID NE '' then
|
|
// Get them in sequence first
|
|
LotOperationsInSequence = Lot_Services('GetLotOperationSequence', LotId)
|
|
for each LotOperation in LotOperationsInSequence using @FM
|
|
ThisLotOperationStartDTM = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_IN$, 'X')
|
|
ThisLotOperationEndDTM = Xlate('LOT_OPERATION', LotOperation, LOT_OPERATION_DATETIME_OUT$, 'X')
|
|
If ThisLotOperationEndDTM Eq '' then
|
|
CurrOperationId = LotOperation
|
|
CurrOperationName = Database_Services('ReadDataColumn', 'LOT_OPERATION', CurrOperationId, LOT_OPERATION_OPERATION_ID$, True$, 0, False$)
|
|
end
|
|
until CurrOperationName
|
|
Next LotOperation
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null LotID passed into service.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = CurrOperationName
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service AddLotOperationIntoSequence(LotId, NewOperationId, NewSequence, Rework)
|
|
|
|
ErrorMessage = ''
|
|
If LotId NE '' then
|
|
If NewSequence NE '' AND Num(NewSequence) then
|
|
// Get Current Operations in sequence
|
|
LotCurrOperation = Lot_Services('GetLotCurrOperationId', LotId)
|
|
CurrOperationSequence = Xlate('LOT_OPERATION', LotCurrOperation, LOT_OPERATION_OPERATION_SEQUENCE$, 'X')
|
|
If CurrOperationSequence LE NewSequence then
|
|
// Get Curr Operation Sequence
|
|
Done = False$
|
|
LotCurrOperationSequence = Lot_Services('GetLotOperationSequence', LotId)
|
|
for each Operation in LotCurrOperationSequence using @Fm setting OpPos
|
|
ThisOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', Operation)
|
|
ThisOperationSequence = ThisOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$>
|
|
If ThisOperationSequence GE NewSequence then
|
|
NewOperationSequence = ThisOperationSequence + 1
|
|
ThisOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = NewOperationSequence
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', Operation, ThisOperationRec)
|
|
If Error_Services('HasError') then
|
|
Done = True$
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end
|
|
Until Done
|
|
Next Operation
|
|
If ErrorMessage EQ '' then
|
|
LotOperationRecID = RTI_CreateGUID()
|
|
If Not(RowExists('LOT_OPERATION', LotOperationRecID)) then
|
|
LotOperationRec = ''
|
|
LotOperationRec<LOT_OPERATION_LOT_ID$> = LotId
|
|
LotOperationRec<LOT_OPERATION_OPERATION_ID$> = NewOperationId
|
|
LotOperationRec<LOT_OPERATION_OPERATION_SEQUENCE$> = NewSequence
|
|
LotOperationRec<LOT_OPERATION_REWORK$> = Rework
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', LotOperationRecId, LotOperationRec)
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Lot Operation already existed, cannot overwrite'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Not allowed to add new operations prior to current operation'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Null or invalid sequence passed to routine'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' service. Null LotID passed into service.'
|
|
end
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service IsLotMovedIn(LotId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'IsLotMovedIn'
|
|
|
|
Response = ''
|
|
If RowExists('LOT', LotId) then
|
|
CurrOperId = Lot_Services('GetLotCurrOperationId', LotId)
|
|
CurrOperDtmIn = Database_Services('ReadDataColumn', 'LOT_OPERATION', CurrOperId, LOT_OPERATION_DATETIME_IN$, True$, 0, False$)
|
|
Response = ( (CurrOperDtmIn LE Datetime()) AND (CurrOperDtmIn NE '') )
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
end service
|
|
|
|
|
|
Service IsOperationCompleted(LotOperationId)
|
|
|
|
OperationCompleted = False$
|
|
ErrorMessage = ''
|
|
If RowExists('LOT_OPERATION', LotOperationId) then
|
|
LotOperationDateTimeOut = Database_Services('ReadDataColumn', 'LOT_OPERATION', LotOperationId, LOT_OPERATION_DATETIME_OUT$, True$, 0, False$)
|
|
If LotOperationDateTimeOut NE '' then OperationCompleted = true$
|
|
end else
|
|
ErrorMessage = 'Invalid lot operation id passed to routine.'
|
|
end
|
|
If ErrorMessage NE '' then
|
|
Error_Services('Add', 'Error in ' : Service : ' with Lot OperationId ' : LotOperationId : ' : ' : ErrorMessage)
|
|
end
|
|
Response = OperationCompleted
|
|
|
|
end service
|
|
|
|
|
|
Service StartLot(LotId, Operator)
|
|
|
|
StartTick = GetTickCount()
|
|
ErrorMessage = ''
|
|
If LotId NE '' then
|
|
If RowExists('LOT', LotId) then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'LOT_START', 'Lot started.', '', Operator)
|
|
If Error_Services('NoError') then
|
|
Lot_Services('MoveInLot', LotId, Operator)
|
|
If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process. Lot id was not passed to routine.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Successfully started lot.'
|
|
Logging_Services('AppendLog', objLotStartLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Error starting lot.'
|
|
Logging_Services('AppendLog', objLotStartLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service BeginRun(LotId, Operator, ToolId)
|
|
|
|
StartTick = GetTickCount()
|
|
ErrorMessage = ''
|
|
If ( (LotId NE '') and (Operator NE '') and (ToolId NE '') ) then
|
|
If RowExists('LOT', LotId) then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'BEGIN_RUN', 'Begin run', ToolId, Operator)
|
|
If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process. Lot id, Operator, or ToolId was not passed to routine.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = ToolId
|
|
LogData<4> = 'Successfully began run.'
|
|
Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = ToolId
|
|
LogData<4> = 'Error beginning run.'
|
|
Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service EndRun(LotId, Operator, ToolId)
|
|
|
|
StartTick = GetTickCount()
|
|
ErrorMessage = ''
|
|
If ( (LotId NE '') and (Operator NE '') and (ToolId NE '') ) then
|
|
If RowExists('LOT', LotId) then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'END_RUN', 'End run', ToolId, Operator)
|
|
If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ':Service:' process. Lot id, Operator, or ToolId was not passed to routine.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, Service, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = ToolId
|
|
LogData<4> = 'Successfully ended run.'
|
|
Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = ToolId
|
|
LogData<4> = 'Error ending run.'
|
|
Logging_Services('AppendLog', objLotRunLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service MoveInLot(LotID, Operator)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'MoveInLot'
|
|
ErrorMessage = ''
|
|
ThisLotCurrOperationID = ''
|
|
If LotId NE '' then
|
|
If RowExists('LOT', LotId) then
|
|
ThisLotRec = Database_Services('ReadDataRow', 'LOT', LotId)
|
|
WaferQty = ThisLotRec<LOT_WAFER_QTY$>
|
|
//Possibly Add locking here
|
|
If Error_Services('NoError') then
|
|
ThisLotCurrOperationID = Lot_Services('GetLotCurrOperationId', LotId)
|
|
If ThisLotCurrOperationID NE '' then
|
|
ThisLotCurrOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotCurrOperationID)
|
|
ThisLotCurrOperationRec<LOT_OPERATION_DATETIME_IN$> = Datetime()
|
|
ThisLotCurrOperationRec<LOT_OPERATION_WAFER_IN_QTY$> = WaferQty
|
|
ThisLotCurrOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = Operator
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotCurrOperationID, ThisLotCurrOperationRec)
|
|
If Error_Services('NoError') then
|
|
LotType = XLATE('LOT', LotId, LOT_TYPE$, 'X')
|
|
CurrOperation = XLATE('LOT_OPERATION', ThisLotCurrOperationID, LOT_OPERATION_OPERATION_ID$, 'X')
|
|
If Error_Services('NoError') then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'MOVE_IN', 'Lot moved into operation ' : CurrOperation : '.', '', Operator)
|
|
If Error_Services('NoError') then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'ARRIVAL', 'Lot arrived at operation ' : CurrOperation : '.', '', Operator)
|
|
If Error_Services('HasError') then ErrorMessage = Error_Services('GetMessage')
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Error writing to lot operation record. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Error getting lots current operation.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move In process. Lot id was not passed to routine.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Successfully Moved Lot into operation ' : ThisLotCurrOperationID : '.'
|
|
Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Error moving Lot into operation ' : ThisLotCurrOperationID : '.'
|
|
Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service MoveOutLot(LotID, Operator)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'MoveOutLot'
|
|
ErrorMessage = ''
|
|
ThisLotCurrOperationID = ''
|
|
If LotId NE '' then
|
|
If RowExists('LOT', LotId) then
|
|
ThisLotRec = Database_Services('ReadDataRow', 'LOT', LotId)
|
|
WaferQty = ThisLotRec<LOT_WAFER_QTY$>
|
|
If Error_Services('NoError') then
|
|
ThisLotCurrOperationID = Lot_Services('GetLotCurrOperationId', LotId)
|
|
If ThisLotCurrOperationID NE '' then
|
|
If Lot_Services('IsLotMovedIn', LotId) then
|
|
ThisLotCurrOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotCurrOperationID)
|
|
ThisLotCurrOperationRec<LOT_OPERATION_DATETIME_OUT$> = Datetime()
|
|
ThisLotCurrOperationRec<LOT_OPERATION_WAFER_OUT_QTY$> = WaferQty
|
|
ThisLotCurrOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = Operator
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotCurrOperationID, ThisLotCurrOperationRec)
|
|
If Error_Services('NoError') then
|
|
LotType = XLATE('LOT', LotId, LOT_TYPE$, 'X')
|
|
CurrOperation = XLATE('LOT_OPERATION', ThisLotCurrOperationID, LOT_OPERATION_OPERATION_ID$, 'X')
|
|
If Error_Services('NoError') then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'MOVE_OUT', 'Lot moved out of operation ' : CurrOperation : '.', '', Operator)
|
|
end else
|
|
ErrorMessage = 'Error in Move In process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Error writing to lot operation record. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
CurrOperationName = Field(ThisLotCurrOperationID, '*', 2)
|
|
ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Cannot move out lot from ' :CurrOperationName: ' because it is not moved in.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Error getting lots current operation.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. ' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move Out process for Lot id ' : LotId : '. Lot ID not found in LOT table.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Move Out process. Lot id was not passed to routine.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage EQ '' then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Successfully Moved Lot out of operation ' : ThisLotCurrOperationID : '.'
|
|
Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotID
|
|
LogData<3> = Operator
|
|
LogData<4> = 'Error in Move Out process for Lot id ' : LotId : '. ' : ErrorMessage
|
|
Logging_Services('AppendLog', objLotMoveLog, LogData, @RM, @FM, False$)
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service ConvertLotRecordToJson(LotId, ItemURL, CurrUser, FullObject=BOOLEAN)
|
|
|
|
ErrorMessage = ''
|
|
JsonString = ''
|
|
If FullObject EQ '' then
|
|
FullObject = True$
|
|
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', 'LegacyLotId', LotRec<LOT_LEGACY_LOT_ID$>, 'String')
|
|
SRP_JSON(objLot, 'SetValue', 'LegacyLotType', LotRec<LOT_LEGACY_LOT_TYPE$>, 'String')
|
|
CanUserModifyLot = Lot_Services('CanUserModifyLot', CurrUser)
|
|
SRP_JSON(objLot, 'SetValue', 'CanUserModifyLot', CanUserModifyLot, 'Boolean')
|
|
SRP_JSON(objLot, 'SetValue', 'WorkOrderNo', LotRec<LOT_WO_LOG_ID$>, 'String')
|
|
SRP_JSON(objLot, 'SetValue', 'EpiPartNo', LotRec<LOT_EPI_PART_NO$>, 'String')
|
|
SRP_JSON(objLot, 'SetValue', 'Type', LotRec<LOT_TYPE$>)
|
|
SRP_JSON(objLot, 'SetValue', 'ProdId', LotRec<LOT_PROD_ID$>)
|
|
ProdSpecNo = LotRec<LOT_PROD_SPEC_ID$>
|
|
SRP_JSON(objLot, 'SetValue', 'ProdSpecNo', ProdSpecNo, 'String')
|
|
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$>)
|
|
CurrLotOperationId = Lot_Services('GetLotCurrOperationId', LotId)
|
|
CurrOperation = XLATE('LOT_OPERATION', CurrLotOperationId, LOT_OPERATION_OPERATION_ID$, 'X')
|
|
CurrOperationDesc = XLATE('OPERATION', CurrOperation, OPERATION_OPERATION_DESCRIPTION$, 'X')
|
|
SRP_JSON(objLot, 'SetValue', 'CurrLotOperationId', CurrLotOperationId)
|
|
SRP_JSON(objLot, 'SetValue', 'CurrOperation', CurrOperation)
|
|
SRP_JSON(objLot, 'SetValue', 'CurrOperationDesc', CurrOperationDesc, 'String')
|
|
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 LotRec<LOT_LEGACY_LOT_ID$> NE '' then
|
|
ActiveRTFId = Return_To_Fab_Services('GetOpenReturnToFabRecordIdByCassId', LotRec<LOT_LEGACY_LOT_ID$>)
|
|
end else
|
|
ActiveRTFId = Return_To_Fab_Services('GetOpenReturnToFabRecordIdByCassId', LotId)
|
|
end
|
|
SRP_JSON(objLot, 'SetValue', 'ActiveRTFId', ActiveRTFId, 'String')
|
|
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
|
|
OperationsArrayJson = ''
|
|
If SRP_Json(OperationsArrayJson, 'New', 'Array') then
|
|
LotOperationKeys = Lot_Services('GetLotOperationSequence', LotId)
|
|
for each LotOperationKey in LotOperationKeys using @FM
|
|
ThisLotOperationJsonString = Lot_Operation_Services('ConvertRecordToJson', LotOperationKey)
|
|
If SRP_Json(objLotOperation, 'PARSE', ThisLotOperationJsonString) EQ '' then
|
|
SRP_Json(OperationsArrayJson, 'Add', objLotOperation)
|
|
SRP_Json(objLotOperation, 'Release')
|
|
end
|
|
Next LotOperationKey
|
|
SRP_JSON(objLot, 'Set', 'LotOperations', OperationsArrayJson)
|
|
SRP_JSON(OperationsArrayJson, 'Release')
|
|
Recipes = PSN_Services('GetAllMetrologyRecipes', ProdSpecNo, True$, True$, True$, True$)
|
|
//Add in all lot recipe parameters
|
|
If SRP_JSON(objRecipes, 'New', 'Array') then
|
|
for each Recipe in Recipes using @FM
|
|
//ToolClass : @VM : Recipe : @VM : Stage
|
|
ToolClass = Recipe<1,1>
|
|
RecipeName = Recipe<1,2>
|
|
Stage = Recipe<1,3>
|
|
If SRP_JSON(objRecipe, 'New', 'Object') then
|
|
SRP_JSON(objRecipe, 'SetValue', 'ToolClass', ToolClass, 'String')
|
|
SRP_JSON(objRecipe, 'SetValue', 'RecipeName', RecipeName, 'String')
|
|
SRP_JSON(objRecipe, 'SetValue', 'StageName', Stage, 'String')
|
|
SRP_JSON(objRecipes, 'Add', objRecipe)
|
|
SRP_JSON(objRecipe, 'Release')
|
|
end
|
|
Next Recipe
|
|
SRP_JSON(objLot, 'Set', 'AllRecipes', objRecipes)
|
|
SRP_JSON(objRecipes, 'Release')
|
|
end
|
|
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
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service CloseLot(LotId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'CloseLot'
|
|
ErrorMessage = ''
|
|
If RowExists('LOT', LotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
|
|
LotRec<LOT_OPEN$> = False$
|
|
Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
|
|
If Error_Services('NoError') then
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'CLOSE', 'Lot status set to Closed', '', 'SYSTEM')
|
|
end else
|
|
ErrorMessage = 'Error setting lot ' : LotId : ' to closed.' : Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = 'Unable to Close Lot ' : LotId : '. Lot ID was not found in LOT table.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service AutoCloseTestWaferLot(LotId, CloseUserId)
|
|
|
|
AutoCloseTime = Datetime()
|
|
ErrorMessage = ''
|
|
If MemberOf(CloseUserId, 'LEAD') OR MemberOf(CloseUserId, 'SUPERVISOR') OR CloseUserId EQ 'SYSTEM' then
|
|
LotOperations = Lot_Services('GetLotOperationSequence', LotId)
|
|
for LotOperationIndex = 1 to DCount(LotOperations, @FM)
|
|
ThisLotOperationId = LotOperations<LotOperationIndex>
|
|
ThisOperationCompleted = Lot_Services('IsOperationCompleted', ThisLotOperationId)
|
|
If Error_Services('NoError') then
|
|
if Not(ThisOperationCompleted) then
|
|
ThisLotOperationRec = Database_Services('ReadDataRow', 'LOT_OPERATION', ThisLotOperationId)
|
|
if Error_Services('NoError') then
|
|
CurrLotQty = Database_Services('ReadDataColumn', 'LOT', LotId, LOT_WAFER_QTY$, True$, 0, False$)
|
|
If ThisLotOperationRec<LOT_OPERATION_DATETIME_IN$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_DATETIME_IN$> = AutoCloseTime
|
|
end
|
|
If ThisLotOperationRec<LOT_OPERATION_DATETIME_OUT$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_DATETIME_OUT$> = AutoCloseTime
|
|
end
|
|
if ThisLotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_OPERATOR_IN_ID$> = CloseUserId
|
|
end
|
|
if ThisLotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_OPERATOR_OUT_ID$> = CloseUserId
|
|
end
|
|
if ThisLotOperationRec<LOT_OPERATION_DATETIME_START$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_DATETIME_START$> = AutoCloseTime
|
|
end
|
|
if ThisLotOperationRec<LOT_OPERATION_DATETIME_STOP$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_DATETIME_STOP$> = AutoCloseTime
|
|
end
|
|
If ThisLotOperationRec<LOT_OPERATION_WAFER_IN_QTY$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_WAFER_IN_QTY$> = CurrLotQty
|
|
end
|
|
If ThisLotOperationRec<LOT_OPERATION_WAFER_OUT_QTY$> EQ '' then
|
|
ThisLotOperationRec<LOT_OPERATION_WAFER_OUT_QTY$> = CurrLotQty
|
|
end
|
|
Database_Services('WriteDataRow', 'LOT_OPERATION', ThisLotOperationId, ThisLotOperationRec, True$, False$, False$)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
Next LotOperationIndex
|
|
end else
|
|
ErrorMessage = CloseUserId : ' does not have permission to close this lot.'
|
|
end
|
|
If ErrorMessage EQ '' then
|
|
// Close Lot as there were no validation failures.
|
|
Lot_Services('CloseLot', LotId)
|
|
If Error_Services('NoError') then
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotId
|
|
LogData<3> = CloseUserId
|
|
LogData<4> = 'Successfully marked lot as closed.'
|
|
Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotId
|
|
LogData<3> = CloseUserId
|
|
LogData<4> = 'Error marking lot as closed.' : ErrorMessage
|
|
Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
|
|
// Send a message to FI
|
|
Recipients = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
|
|
SentFrom = 'SYSTEM'
|
|
Subject = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
|
|
Message = 'Error in ' : service : ' with lot id ' : LotId : ' attempting to set CLOSE flag on lot. ' : ErrorMessage
|
|
Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
|
|
Error_Services('Add', 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage)
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = LotId
|
|
LogData<3> = CloseUserId
|
|
LogData<4> = 'Error marking lot as closed.' : ErrorMessage
|
|
Logging_Services('AppendLog', objLotClosureLog, LogData, @RM, @FM, False$)
|
|
// Send a message to FI
|
|
Recipients = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
|
|
SentFrom = 'SYSTEM'
|
|
Subject = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
|
|
Message = 'Error in ' : service : ' with lot id ' : LotId : ' attempting to Auto Close Lot. ' : ErrorMessage
|
|
Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
|
|
Error_Services('Add', 'Error in ' : service : ' with lot ' : LotId : ':' : ErrorMessage)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service HoldLot(LotId, OperatorId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'HoldLot'
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
end service
|
|
|
|
|
|
Service UnholdLot(LotId, OperatorId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'UnholdLot'
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
end service
|
|
|
|
|
|
Service ReduceLotWaferCount(LotId, ReductionQty, OperatorId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'ReduceLotWaferCount'
|
|
|
|
ErrorMessage = ''
|
|
If RowExists('LOT', LotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
|
|
LotType = LotRec<LOT_TYPE$>
|
|
LotHold = LotRec<LOT_HOLD$>
|
|
LotOpen = LotRec<LOT_OPEN$>
|
|
LotCurrWfrQty = LotRec<LOT_WAFER_QTY$>
|
|
LotNewWfrQty = LotCurrWfrQty - ReductionQty
|
|
If LotNewWfrQty LE 25 AND LotNewWfrQty GE 0 then
|
|
LotRec<LOT_WAFER_QTY$> = LotNewWfrQty
|
|
Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
|
|
If Error_Services('NoError') then
|
|
// Write Lot Event
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'REDUCE_WAFER_QTY', 'Reduced wafer count by ' : ReductionQty, '', OperatorId, False$, '')
|
|
if LotNewWfrQty EQ 0 AND LotType EQ 'TW' then
|
|
ServiceParms = 'AutoCloseTestWaferLot' : @VM : LotId : @VM : 'SYSTEM'
|
|
Service_Services('PostProcedure', 'LOT_SERVICES', ServiceParms)
|
|
If Error_Services('HasError') then
|
|
Recipients = Xlate('NOTIFICATION', 'FI_SUPPORT', NOTIFICATION_USER_ID$, 'X')
|
|
SentFrom = 'SYSTEM'
|
|
Subject = 'TEST WAFER LOT AUTO-CLOSURE FAILURE'
|
|
Message = 'Error in ' : service : ' attempting to add auto lot closure for lot id ' : LotId : ' to the service queue.'
|
|
AttachWindow = ''
|
|
AttachKeys = ''
|
|
SendToGroup = ''
|
|
Obj_Notes('Create',Recipients:@RM:SentFrom:@RM:Subject:@RM:Message)
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Error writing Lot Id ' : LotId : ' with new quantity.'
|
|
end
|
|
end else
|
|
Begin Case
|
|
Case LotNewWfrQty GT 25
|
|
ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity great than 25.'
|
|
Case LotNewWfrQty LT 0
|
|
ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity less than 0.'
|
|
End Case
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Reduce Lot Wafer Count service, Lot Id ' : LotId : ' not found in lot table.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service IncreaseLotWaferCount(LotId, IncreaseQty, OperatorId)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'IncreaseLotWaferCount'
|
|
|
|
ErrorMessage = ''
|
|
If RowExists('LOT', LotId) then
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', LotId, True$, 0, False$)
|
|
LotHold = LotRec<LOT_HOLD$>
|
|
LotOpen = LotRec<LOT_OPEN$>
|
|
if LotOpen then
|
|
If Not(LotHold) then
|
|
LotCurrWfrQty = LotRec<LOT_WAFER_QTY$>
|
|
LotNewWfrQty = LotCurrWfrQty + IncreaseQty
|
|
|
|
If LotNewWfrQty LE 25 AND LotNewWfrQty GT 0 then
|
|
LotRec<LOT_WAFER_QTY$> = LotNewWfrQty
|
|
Database_Services('WriteDataRow', 'LOT', LotId, LotRec, True$, False$, False$)
|
|
If Error_Services('NoError') then
|
|
// Write Lot Event
|
|
Lot_Event_Services('CreateLotEvent', LotId, Datetime(), 'INCREASE_WAFER_QTY', 'Increased wafer count by ' : IncreaseQty, '', OperatorId, False$, '')
|
|
end else
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Error writing Lot Id ' : LotId : ' with new quantity.'
|
|
end
|
|
end else
|
|
Begin Case
|
|
Case LotNewWfrQty GT 25
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity great than 25.'
|
|
Case LotNewWfrQty LT 0
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' cannot have a quantity less than 0.'
|
|
End Case
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' is currently on hold.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' is closed.'
|
|
end
|
|
|
|
end else
|
|
ErrorMessage = 'Error in Increase Lot Wafer Count service, Lot Id ' : LotId : ' not found in lot table.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
|
|
Service OpenOIWizardCreateTWLotInBrowser()
|
|
|
|
Command = 'explorer https://goto.infineon.com/oiwizard/Lot/CreateTestWaferLot/'
|
|
SRP_Run_Command(Command)
|
|
|
|
end service
|
|
|
|
|
|
Service CreateNewVoidedLotRecord(LotId, LegacyLotId, LotType=LOT_TYPES, Username)
|
|
|
|
StartTick = GetTickCount()
|
|
MetricName = 'CreateNewVoidedLotRecord'
|
|
|
|
ErrorMessage = ''
|
|
If RowExists('LSL_USERS', Username) then
|
|
If LotType NE '' then
|
|
NewVoidedLotRecordId = RTI_CreateGUID()
|
|
If Not(RowExists('VOIDED_LOT', NewVoidedLotRecordId)) then
|
|
NewVoidedLotRec = ''
|
|
Begin Case
|
|
Case LotType EQ 'RDS'
|
|
WONo = XLate('RDS', LegacyLotId, RDS_WO$, 'X')
|
|
CassNo = XLATE('RDS', LotId, RDS_CASS_NO$, 'X')
|
|
WoMatKey = WONo : '*' : CassNo
|
|
If RowExists('RDS', LegacyLotId) then
|
|
WoNo = Field(LotId, '*', 1)
|
|
NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
|
|
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'RDS'
|
|
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
|
|
end else
|
|
ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. RDS record not found.'
|
|
end
|
|
Case LotType EQ 'WO_MAT'
|
|
If RowExists('WO_MAT', LegacyLotId) then
|
|
WoNo = Field(LotId, '*', 1)
|
|
NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
|
|
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WO_MAT'
|
|
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
|
|
end else
|
|
ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WoMat record not found.'
|
|
end
|
|
Case LotType EQ 'WM_IN'
|
|
If RowExists('WM_IN', LegacyLotId) then
|
|
WoNo = Field(LotId, '*', 1)
|
|
NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
|
|
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WM_IN'
|
|
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
|
|
end else
|
|
ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WM_IN record not found.'
|
|
end
|
|
Case LotType EQ 'WM_OUT'
|
|
If RowExists('WM_OUT', LegacyLotId) then
|
|
WoNo = Field(LotId, '*', 1)
|
|
NewVoidedLotRec<VOIDED_LOT_WORK_ORDER_LOG_ID$> = WoNo
|
|
NewVoidedLotRec<VOIDED_LOT_ENTITY_TYPE$> = 'WM_OUT'
|
|
NewVoidedLotRec<VOIDED_LOT_LEGACY_LOT_ID$> = LegacyLotId
|
|
end else
|
|
ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. WM_OUT record not found.'
|
|
end
|
|
Case Otherwise$
|
|
ErrorMessage = 'Error when creating a voided lot record for ' : LotId : ' of type ' : LotType : '. Non supported lot type.'
|
|
End Case
|
|
If ErrorMessage EQ '' then
|
|
NewVoidedLotRec<VOIDED_LOT_VOID_BY$> = Username
|
|
NewVoidedLotRec<VOIDED_LOT_VOID_DTM$> = Datetime()
|
|
NewVoidedLotRec<VOIDED_LOT_LOT_ID$> = LotId
|
|
Database_Services('WriteDataRow', 'VOIDED_LOT', NewVoidedLotRecordId, NewVoidedLotRec)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Go buy a lottery ticket, we ran into a GUID collision with an existing GUID ' : NewVoidedLotRecordId : ' when trying to create a Voided Lot record for ' : LotId
|
|
end
|
|
end else
|
|
ErrorMessage = 'Null lot type of passed to CreateVoidedLotRecord routine.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Username ' : Username : ' passed to CreateVoidedLotRecord routine does not exist.'
|
|
end
|
|
|
|
EndTick = GetTickCount()
|
|
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
|
|
|
|
|
|
If ErrorMessage NE '' then Error_Services('Add', ErrorMessage)
|
|
|
|
end service
|
|
|
|
Service CanUserModifyLot(UserId)
|
|
|
|
Begin Case
|
|
|
|
Case MemberOf(UserId, 'OI_ADMIN')
|
|
Response = true$
|
|
Case MemberOf(UserId, 'ENGINEERING')
|
|
Response = true$
|
|
Case MemberOf(UserId, 'ENG_TECH')
|
|
Response = true$
|
|
Case MemberOf(UserId, 'SUPERVISOR')
|
|
Response = true$
|
|
Case MemberOf(UserId, 'LEAD')
|
|
Response = true$
|
|
Case MemberOf(UserId, 'MATERIAL_HANDLER')
|
|
Response = true$
|
|
Case UserId EQ 'SYSTEM'
|
|
Response = true$
|
|
Case Otherwise$
|
|
Response = false$
|
|
|
|
End Case
|
|
|
|
end service
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Internal GoSubs
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|