801 lines
37 KiB
Plaintext
801 lines
37 KiB
Plaintext
Compile function TEST_RUN_Services(@Service, @Params)
|
|
#pragma precomp SRP_PreCompiler
|
|
$insert LOGICAL
|
|
$Insert APP_INSERTS
|
|
$Insert TEST_WAFER_PROD_EQUATES
|
|
$Insert TEST_WAFER_TYPES_DISPO_OPTIONS_EQUATES
|
|
$Insert TEST_RUN_EQUATES
|
|
$Insert TEST_RUN_WAFER_EQUATES
|
|
$Insert TEST_RUN_OBJ_EQUATES
|
|
$Insert LOT_EQUATES
|
|
$Insert LOT_OPERATION_EQUATES
|
|
|
|
Declare function Nextkey, Error_Services, Environment_Services, OConv, Logging_Services, SRP_Hashtable, Lot_Services
|
|
Declare function SRP_Datetime, Database_Services, Test_Run_Services, File_Services, Status, delete, Insert, Datetime, SRP_Json, MemberOf
|
|
Declare subroutine Database_Services, Btree.Extract, Error_Services, Logging_Services, Rlist, Test_Run_Services, Lot_Services, SRP_Json
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\TEST_RUN_SERVICES\TestWaferProduct'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Material Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'Notes'
|
|
objLogTWP = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\TEST_RUN_SERVICES\TestRun'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Material Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'User' : @FM : 'Notes'
|
|
objLogTR = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, Headers, '', False$, False$)
|
|
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
GoToService
|
|
|
|
Return Response or ""
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// SERVICES
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
//Test Wafer Product Methods - related to TEST_WAFER_PROD table
|
|
|
|
/*
|
|
Create New Test Wafer Product
|
|
Creates a new entry in the TEST_WAFER_PROD table.
|
|
*/
|
|
Service CreateNewTestWaferProduct(ProductName)
|
|
If ProductName NE '' then
|
|
//Check for existing
|
|
table = 'TEST_WAFER_PROD'
|
|
Open "DICT ":table To @DICT Else
|
|
Error_Services('Add', 'Error opening Test wafer product table')
|
|
Return
|
|
End
|
|
Column = "PART_NAME"
|
|
Value = ProductName
|
|
search_criteria = Column:@VM:Value:@FM
|
|
keylist = ""
|
|
option = ""
|
|
flag = ""
|
|
Btree.Extract(search_criteria, table, @DICT, keylist, option, flag)
|
|
IF keylist EQ '' then
|
|
NewTestWaferProdRec = ''
|
|
NewTestWaferProdRec<TEST_WAFER_PROD_PART_NAME$> = ProductName
|
|
NewTestWaferProdKey = Nextkey('TEST_WAFER_PROD')
|
|
Database_Services('WriteDataRow', table, NewTestWaferProdKey, NewTestWaferProdRec)
|
|
If Error_Services('NoError') then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Successfully created new product type with ID of ' : NewTestWaferProdKey
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Response = NewTestWaferProdKey
|
|
end else
|
|
//Todo Add Logging for failure
|
|
LogData = ''
|
|
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error Creating new test wafer product. ' : Error_Services('GetMessage')
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Response = ''
|
|
end
|
|
end else
|
|
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error Creating new test wafer product. Product already exists!'
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Error_Services('Add', 'Product already exists!')
|
|
Response = ''
|
|
end
|
|
end else
|
|
//Todo Add logging for failure
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Product name was missing'
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Error_Services('Add', 'Product name was missing')
|
|
Response = ''
|
|
end
|
|
end service
|
|
|
|
Service DisableTWProd(TWProdKey)
|
|
If TWProdKey NE '' then
|
|
TWProdRec = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', TWProdKey)
|
|
TWProdRec<TEST_WAFER_PROD_SORT_ORDER$> = 0
|
|
Database_Services('WriteDataRow', 'TEST_WAFER_PROD', TWProdKey, TWProdRec)
|
|
end else
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> DisableTWProd: No TWProdKeySupplied')
|
|
end
|
|
end service
|
|
|
|
/*
|
|
Add disposition option to a test wafer product
|
|
Creates a new disposition entry in the TEST_WAFER_TYPES_DISPO_OPTION table, related to a TEST_WAFER_PROD record
|
|
*/
|
|
Service AddTestWaferProductDispo(TestWaferProdID, DispoName)
|
|
If TestWaferProdID NE '' then
|
|
IF DispoName NE '' then
|
|
MatchingIDs = False$
|
|
CurrentDispoIDs = XLATE('TEST_WAFER_PROD', TestWaferProdID, TEST_WAFER_PROD_WAFER_DISPO_IDS$, 'X')
|
|
For i = 1 to DCount(CurrentDispoIDs, @VM)
|
|
DispoID = CurrentDispoIDs<1, i>
|
|
DispoDescription = Xlate('TEST_WAFER_TYPES_DISPO_OPTIONS', DispoID, TEST_WAFER_TYPES_DISPO_OPTIONS_DISPO_DESCRIPTION$, 'X')
|
|
if DispoName EQ DispoDescription then MatchingIDs = true$
|
|
Until MatchingIDs
|
|
Next i
|
|
if NOT(MatchingIDs) then
|
|
NewTestWaferProdDispoRec = ''
|
|
NewTestWaferProdDispoRec<TEST_WAFER_TYPES_DISPO_OPTIONS_TEST_WAFER_PROD_ID$> = TestWaferProdID
|
|
NewTestWaferProdDispoRec<TEST_WAFER_TYPES_DISPO_OPTIONS_DISPO_DESCRIPTION$> = DispoName
|
|
NewTestWaferProdDispoKey = Nextkey('TEST_WAFER_TYPES_DISPO_OPTIONS')
|
|
Database_Services('WriteDataRow', 'TEST_WAFER_TYPES_DISPO_OPTIONS', NewTestWaferProdDispoKey, NewTestWaferProdDispoRec)
|
|
If Error_Services('NoError') then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Dispo added to ' : TestWaferProdID : '. The dispo key is ' : NewTestWaferProdDispoKey
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
end else
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error adding dispo to TW Prod, ' : Error_Services('GetMessage')
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
end
|
|
end else
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error adding dispo to TW Prod. dispo option already existed.'
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Error_Services('Add', 'Error adding dispo to TW Prod. dispo option already existed.')
|
|
end
|
|
end else
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error adding dispo to TW Prod. The dispo name was missing'
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
end
|
|
end else
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error adding dispo to TW Prod. The product name was missing'
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
end
|
|
end service
|
|
|
|
Service DeleteTestWaferProductDispo(DispoID)
|
|
If DispoID NE '' then
|
|
If RowExists('TEST_WAFER_TYPES_DISPO_OPTIONS', DispoID) then
|
|
Database_Services('DeleteDataRow', 'TEST_WAFER_TYPES_DISPO_OPTIONS', DispoID, True$, False$)
|
|
end else
|
|
errorMessage = 'Error deleting dispo to TW Prod. The dispo id was not found.'
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = errorMessage
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Error_Services('Add', errorMessage)
|
|
end
|
|
end else
|
|
errorMessage = 'Error deleting dispo to TW Prod. The dispo id was missing'
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = errorMessage
|
|
Logging_Services('AppendLog', objLogTWP, LogData, @FM, @VM)
|
|
Error_Services('Add', errorMessage)
|
|
end
|
|
end service
|
|
|
|
Service GetAllTWProdKeysUnformatted()
|
|
keylist = ''
|
|
RList("SELECT TEST_WAFER_PROD WITH SORT_ORDER NE '' BY SORT_ORDER", 5, '', '', '')
|
|
Done = False$
|
|
Loop
|
|
Readnext TWProdKey else Done = True$
|
|
Until Done
|
|
keylist<-1> = TWProdKey
|
|
Repeat
|
|
|
|
Response = keylist
|
|
end service
|
|
|
|
Service GetAllTWProdKeys(ShowSorted)
|
|
keylist = ''
|
|
ProdList = ''
|
|
If ShowSorted then
|
|
RList("SELECT TEST_WAFER_PROD WITH SORT_ORDER NE 0 AND WITH SORT_ORDER NE '' BY SORT_ORDER", 5, '', '', '')
|
|
end else
|
|
RList("SELECT TEST_WAFER_PROD BY SORT_ORDER", 5, '', '', '')
|
|
end
|
|
|
|
Done = False$
|
|
Loop
|
|
Readnext TWProdKey else Done = True$
|
|
Until Done
|
|
keylist<1, -1> = TWProdKey
|
|
Repeat
|
|
for each ProdKey in keylist using @VM setting pPos
|
|
ProdName = Xlate('TEST_WAFER_PROD', ProdKey, TEST_WAFER_PROD_PART_NAME$, 'X')
|
|
if ProdName NE '' then
|
|
ProdList<1, pPos> = ProdKey
|
|
ProdList<2, pPos> = ProdName
|
|
end
|
|
Next ProdKey
|
|
Response = ProdList
|
|
end service
|
|
|
|
Service UpdateTWProdSortOrder(TWProdKey, NewOrder)
|
|
//First get current sort order
|
|
TWProdRec = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', TWProdKey)
|
|
OldSortOrder = TWProdRec<TEST_WAFER_PROD_SORT_ORDER$>
|
|
AllTWProdsSorted = Test_Run_Services('GetAllTWProdKeysUnformatted')
|
|
//Get rid of all zero value sort orders
|
|
i = 1
|
|
LOOP
|
|
UNTIL AllTWProdsSorted<i> = ''
|
|
currSortOrder = Xlate('TEST_WAFER_PROD', AllTWProdsSorted<i>, TEST_WAFER_PROD_SORT_ORDER$, 'X')
|
|
If currSortOrder EQ 0 then
|
|
//Remove it from the list of TWProds with Sorting enabled. The zero's will screw up the next part.
|
|
AllTWProdsSorted = delete(AllTWProdsSorted, i, 0, 0)
|
|
end
|
|
i = i + 1
|
|
REPEAT
|
|
If NewOrder GT 0 then
|
|
AllTWProdsSorted = Insert(AllTWProdsSorted, NewOrder, 0, 0, TWProdKey)
|
|
//Locate the old order and remove it
|
|
i = 1
|
|
LOOP
|
|
UNTIL AllTWProdsSorted<i> = ''
|
|
If i NE NewOrder AND AllTWProdsSorted<i> EQ TWProdKey then
|
|
//Remove it from the list of TWProds with Sorting enabled. The zero's will screw up the next part.
|
|
AllTWProdsSorted = delete(AllTWProdsSorted, i, 0, 0)
|
|
end
|
|
i = i + 1
|
|
REPEAT
|
|
end else
|
|
//Disabling
|
|
Locate TWProdKey in AllTWProdsSorted using @FM setting tPos then
|
|
AllTWProdsSorted = delete(AllTWProdsSorted, tPos, 0, 0)
|
|
end
|
|
TWProdRecToWrite = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', TWProdKey)
|
|
TWProdRecToWrite<TEST_WAFER_PROD_SORT_ORDER$> = 0
|
|
Database_Services('WriteDataRow', 'TEST_WAFER_PROD', TWProdKey, TWProdRecToWrite, 1, 0, 1)
|
|
end
|
|
//Rewrite the entire sort order for all prods
|
|
For each TWProd in AllTWProdsSorted using @FM setting SortOrder
|
|
TWProdRecToWrite = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', TWProd)
|
|
TWProdRecToWrite<TEST_WAFER_PROD_SORT_ORDER$> = SortOrder
|
|
Database_Services('WriteDataRow', 'TEST_WAFER_PROD', TWProd, TWProdRecToWrite, 1, 0, 1)
|
|
Next TWProd
|
|
end service
|
|
|
|
Service GetAllTestRunTypes()
|
|
keylist = ''
|
|
rtList = ''
|
|
RList('SELECT TEST_RUN_TYPE BY RUN_TYPE', 5, '', '', '')
|
|
Done = False$
|
|
Loop
|
|
Readnext RunTypeKey else Done = True$
|
|
Until Done
|
|
keylist<1, -1> = RunTypeKey
|
|
Repeat
|
|
for each RTKey in keylist using @VM setting rPos
|
|
RunTypeName = Xlate('TEST_RUN_TYPE', RTKey, TEST_RUN_TYPE_RUN_TYPE$, 'X')
|
|
if RunTypeName NE '' then
|
|
rtList<1, rPos> = RTKey
|
|
rtList<2, rPos> = RunTypeName
|
|
end
|
|
Next ProdKey
|
|
Response = rtList
|
|
end service
|
|
|
|
Service GetTestWaferLots(ShowOnlyOpenLots)
|
|
ErrorMessage = ''
|
|
TestWaferLotKeys = ''
|
|
SearchString = 'TYPE':@VM:'TW':@FM
|
|
If ShowOnlyOpenLots then
|
|
SearchString := 'OPEN':@VM:True$:@FM
|
|
end
|
|
Open 'DICT.LOT' to @DICT then
|
|
Btree.Extract(SearchString, 'LOT', @DICT, TestWaferLotKeys, '', '')
|
|
end else
|
|
ErrorMessage = 'Error opening LOT dictionary.'
|
|
end
|
|
If ErrorMessage NE '' then
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
Response = TestWaferLotKeys
|
|
end service
|
|
|
|
Service CreateTestRunRecord(RunTypeID, EqpType, EqpID, PSNo, RDSNo, UserID, TWLotIds, TWLotQtys)
|
|
TWRunKey = ''
|
|
Response = ''
|
|
ErrorMessage = ''
|
|
TWTrackingSystemActive = Database_Services('ReadDataColumn', 'APP_INFO', 'NEW_TW_SYSTEM_ACTIVE_SWITCH', 1, True$, 0, False$)
|
|
//Pre-Checks.
|
|
If TWTrackingSystemActive then
|
|
If TWLotIds NE '' then
|
|
for each TWLotId in TWLotIds using @VM setting twLotPos
|
|
ThisTWLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLotId, LOT_WAFER_QTY$, True$, 0, False$)
|
|
If ThisTWLotCurrQty then
|
|
ThisTWLotUsageQty = TWLotQtys<1, twLotPos>
|
|
If ThisTWLotCurrQty LT ThisTWLotUsageQty then
|
|
ErrorMessage = 'Error in Create Test Run Record routine. Lot # ' : TWLotId : ' does not have enough wafers. Please choose ' : ThisTWLotCurrQty : ' wafers or less.'
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create Test Run Record routine. Lot # ' : TWLotId : ' has a zero wafer quantity.'
|
|
end
|
|
Until ErrorMessage NE ''
|
|
Next TWLotId
|
|
end else
|
|
ErrorMessage = 'Error in Create Test Run Record routine. No test wafer lots entered.'
|
|
end
|
|
end
|
|
If ErrorMessage EQ '' then
|
|
If RunTypeID NE '' AND EqpType NE '' AND EqpID NE '' AND UserID NE '' then
|
|
RunDTM = SRP_Datetime('Now')
|
|
TWRunRec = ''
|
|
TWRunRec<TEST_RUN_RUN_DTM$> = RunDTM
|
|
TWRunRec<TEST_RUN_RUN_TYPE_ID$> = RunTypeID
|
|
TWRunRec<TEST_RUN_EQUIPMENT_ID$> = EqpID
|
|
TWRunRec<TEST_RUN_EQUIPMENT_TYPE$> = EqpType
|
|
TWRunRec<TEST_RUN_PROD_SPEC_ID$> = PSNo
|
|
TWRunRec<TEST_RUN_LSL_USER_ID$> = UserID
|
|
TWRunRec<TEST_RUN_RDS_ID$> = RDSNo
|
|
TWRunKey = nextkey('TEST_RUN')
|
|
Database_Services('WriteDataRow', 'TEST_RUN', TWRunKey, TWRunRec)
|
|
If Error_Services('NoError') then
|
|
If RowExists('TEST_RUN', TWRunKey) then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = UserID
|
|
LogData<1, 3> = 'Successfully created new TEST_RUN record with ID of ' : TWRunKey
|
|
Logging_Services('AppendLog', objLogTR, LogData, @FM, @VM)
|
|
//Now create the test wafer usages
|
|
Success = False$
|
|
If TWLotIds NE '' then
|
|
//Supports new logging methods.
|
|
for each TWLotId in TWLotIds using @VM setting twlPos
|
|
LotRec = Database_Services('ReadDataRow', 'LOT', TWLotId, True$, 0, False$)
|
|
IsThisLotOnHold = LotRec<LOT_HOLD$>
|
|
IsThisLotOpen = LotRec<LOT_OPEN$>
|
|
IsThisLotATWLot = LotRec<LOT_TYPE$> EQ 'TW'
|
|
ThisLotCurrQty = LotRec<LOT_WAFER_QTY$>
|
|
ThisLotPartId = LotRec<LOT_PROD_ID$>
|
|
|
|
//
|
|
ThisUsageQty = TWLotQtys<1, twlPos>
|
|
|
|
If IsThisLotOpen then
|
|
If Not(IsThisLotOnHold) then
|
|
If IsThisLotATWLot then
|
|
InAtTWInUse = False$
|
|
Loop
|
|
LotMovedIn = Lot_Services('IsLotMovedIn', TWLotId)
|
|
ThisLotCurrOperationId = Lot_Services('GetLotCurrOperationId', TWLotId)
|
|
ThisLotCurrOperation = Database_Services('ReadDataColumn', 'LOT_OPERATION', ThisLotCurrOperationId, LOT_OPERATION_OPERATION_ID$, True$, 0, False$)
|
|
Begin Case
|
|
Case ThisLotCurrOperation EQ 'TW_IN_USE'
|
|
|
|
If Not(LotMovedIn) then
|
|
Lot_Services('CreateLotEvent', TWLotId, 'TW', Datetime(), 'MOVE_IN', 'Move into TW_IN_USE', '', 0, 0, '', UserID)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
InAtTWInUse = True$
|
|
end
|
|
|
|
Case ThisLotCurrOperation EQ 'TW_READY_TO_USE'
|
|
|
|
If Not(LotMovedIn) then
|
|
Lot_Services('CreateLotEvent', TWLotId, 'TW', Datetime(), 'MOVE_IN', 'Move into TW_READY_TO_USE', '', 0, 0, '', UserID)
|
|
end else
|
|
Lot_Services('CreateLotEvent', TWLotId, 'TW', Datetime(), 'MOVE_OUT', 'Move out of TW_READY_TO_USE', '', 0, 0, '', UserID)
|
|
end
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
Case Otherwise$
|
|
ErrorMessage = 'Error: Lot ':TWLotId:' is currently at ' : ThisLotCurrOperation : '. It cannot be used at this time.'
|
|
End Case
|
|
Until ErrorMessage NE '' Or InAtTWInUse
|
|
Repeat
|
|
If InAtTWInUse then
|
|
if Num(ThisUsageQty) then
|
|
If ThisUsageQty GT 0 then
|
|
//Now check that the usage QTY can be consumed from the TW Lot
|
|
ThisLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLotId, LOT_WAFER_QTY$, True$, 0, False$)
|
|
If ThisUsageQty LE ThisLotCurrQty then
|
|
|
|
Abort = false$
|
|
for i = 1 to ThisUsageQty
|
|
Test_Run_Services('CreateTestRunWaferRecord',TWRunKey, ThisLotPartId, RunTypeID, TWLotId, UserID)
|
|
If Error_Services('HasError') then
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
until ErrorMessage NE ''
|
|
Next i
|
|
If ErrorMessage EQ '' then
|
|
Lot_Services('CreateLotEvent', TWLotId, 'TW', Datetime(), 'REDUCE_WAFER_QTY', ThisUsageQty : ' wafers consumed from lot.', EqpID, ThisUsageQty, 0, '', UserID)
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create Test Run Record routine, ' : TWLotId : ' does not have enough wafers.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create Test Run Record routine, Invalid qty for lot ' : TWLotId : ' passed to routine.'
|
|
end
|
|
end
|
|
|
|
end else
|
|
//Lot is not classified as a test wafer lot.
|
|
end
|
|
end else
|
|
//Lot is on hold
|
|
end
|
|
end else
|
|
//Lot is not open
|
|
end
|
|
until ErrorMessage NE ''
|
|
Next TWLotId
|
|
If ErrorMessage EQ '' then
|
|
//commit everything
|
|
end else
|
|
//commit nothing, there was an error.
|
|
end
|
|
end else
|
|
//Supports legacy TW logging
|
|
Response = TWRunKey
|
|
end
|
|
end else
|
|
ErrorMessage = 'Error in Create Test Run Record routine, Generated Test Run Key did not exist in TEST Run table.'
|
|
end
|
|
|
|
Response = TWRunKey
|
|
end else
|
|
ErrorMessage = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
If RunTypeID EQ '' then
|
|
ErrorMessage := 'Run Type ID Missing. '
|
|
end
|
|
If EqpType EQ '' then
|
|
ErrorMessage := 'Equipment Type ID Missing. '
|
|
end
|
|
If EqpID EQ '' then
|
|
ErrorMessage := 'Equipment ID Missing. '
|
|
end
|
|
If UserID EQ '' then
|
|
ErrorMessage := 'User ID Missing. '
|
|
end
|
|
end
|
|
end
|
|
If ErrorMessage NE '' then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error writing TEST_RUN Record ' : TWRunKey : ': ' : ErrorMessage
|
|
Logging_Services('AppendLog', objLogTR, LogData, @FM, @VM)
|
|
Error_Services('Add', ErrorMessage)
|
|
Response = ''
|
|
end
|
|
end service
|
|
|
|
Service CreateTestRunWaferRecord(TestRunID, TWPartID, TWUsageTypeID, SourceLotId, Username)
|
|
ErrorMessage = ''
|
|
If TestRunID NE '' AND TWPartID NE '' then
|
|
If RowExists('TEST_RUN', TestRunID) then
|
|
//Legacy Code: Pre LOT usage
|
|
TRWaferRec = ''
|
|
TRWaferRec<TEST_RUN_WAFER_TEST_RUN_ID$> = TestRunID
|
|
TRWaferRec<TEST_RUN_WAFER_TEST_WAFER_PROD_ID$> = TWPartID
|
|
TRWaferRec<TEST_RUN_WAFER_TEST_USAGE_TYPE_ID$> = TWUsageTypeID
|
|
TRWaferRec<TEST_RUN_WAFER_SOURCE_LOT_ID$> = SourceLotID
|
|
TRWaferKey = Nextkey('TEST_RUN_WAFER')
|
|
Database_Services('WriteDataRow', 'TEST_RUN_WAFER', TRWaferKey, TRWaferRec)
|
|
If Error_Services('NoError') AND RowExists('TEST_RUN_WAFER', TRWaferKey) then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Successfully wrote ' : TRWaferKey : ' to the TEST_RUN_WAFER table.'
|
|
Logging_Services('AppendLog', objLogTR, LogData, @FM, @VM)
|
|
//Increment Usage in TEST_WAFER_PROD Record
|
|
If ErrorMessage = '' then
|
|
Test_Run_Services('IncrementTWProdUsage', TWPartID)
|
|
Response = TRWaferKey
|
|
end
|
|
end else
|
|
ErrorMessage := 'Error writing TEST_RUN_WAFER record with key of ' : TRWaferKey '. '
|
|
end
|
|
end else
|
|
ErrorMessage := 'Unable to find parent TEST_RUN record. '
|
|
end
|
|
end else
|
|
If TestRunID EQ '' then
|
|
ErrorMessage := 'TestRunID parameter was not passed to CreateTestRunWaferRecord method. '
|
|
end
|
|
If TWPartID EQ '' then
|
|
ErrorMessage := 'TWPartID parameter was not passed to CreateTestRunWaferRecord method. '
|
|
end
|
|
end
|
|
If ErrorMessage NE '' then
|
|
LogData = ''
|
|
LogData<1, 1> = LoggingDTM
|
|
LogData<1, 2> = @User4
|
|
LogData<1, 3> = 'Error Writing to the TEST_RUN_WAFER table. ' : ErrorMessage
|
|
Logging_Services('AppendLog', objLogTR, LogData, @FM, @VM)
|
|
Error_Services('Add', 'Error creating new test run record: ' : ErrorMessage)
|
|
end
|
|
end service
|
|
|
|
Service UseTWFromLot(LotId, UsageQty, Username)
|
|
ErrorMessage = ''
|
|
If RowExists('LOT', LotId) then
|
|
Lot_Services('CreateLotEvent', LotId, 'TW', Datetime(), 'REDUCE_WAFER_QTY', 'Consumed test wafer.', '', UsageQty, 0, '', Username)
|
|
end else
|
|
ErrorMessage = 'Error logging wafer consumption from Lot # ' : LotId : '. Lot does not exist in LOT table.'
|
|
end
|
|
If ErrorMessage EQ '' then
|
|
|
|
end else
|
|
//Log Error
|
|
end
|
|
end service
|
|
|
|
Service GetTestRunById(TestRunID)
|
|
If TestRunID NE '' then
|
|
If RowExists('TEST_RUN', TestRunID) then
|
|
TRRec = Database_Services('ReadDataRow', 'TEST_RUN', TestRunID)
|
|
Response = TRRec
|
|
end else
|
|
Error_Services('Add', 'Test Run ID does not exist in TEST_RUN table')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Test Run ID parameter was not passed to routine.')
|
|
end
|
|
end service
|
|
|
|
Service IncrementTWProdUsage(TWProdKey)
|
|
If TWProdKey NE '' then
|
|
TWProdRec = Database_Services('ReadDataRow', 'TEST_WAFER_PROD', TWProdKey)
|
|
TWProdRec<TEST_WAFER_PROD_USAGE$> = TWProdRec<TEST_WAFER_PROD_USAGE$> + 1
|
|
Database_Services('WriteDataRow', 'TEST_WAFER_PROD', TWProdKey, TWProdRec)
|
|
end
|
|
end service
|
|
|
|
Service GetTestRunObj(TestRunID)
|
|
TestRunObj = ''
|
|
TestRunRec = Test_Run_Services('GetTestRunById', TestRunID)
|
|
//Start getting translated values for object
|
|
TestRunObj<TEST_RUN_OBJ_TEST_RUN_ID$> = TestRunID
|
|
TestRunObj<TEST_RUN_OBJ_RUN_DTM$> = OConv(TestRunRec<TEST_RUN_RUN_DTM$>, 'DT')
|
|
TestRunObj<TEST_RUN_OBJ_RUN_TYPE$> = Xlate('TEST_RUN_TYPE', TestRunRec<TEST_RUN_RUN_TYPE_ID$>, TEST_RUN_TYPE_RUN_TYPE$, 'X')
|
|
TestRunObj<TEST_RUN_OBJ_EQUIPMENT_ID$> = TestRunRec<TEST_RUN_EQUIPMENT_ID$>
|
|
EqpType = TestRunRec<TEST_RUN_EQUIPMENT_TYPE$>
|
|
Begin Case
|
|
Case EqpType EQ 'R'
|
|
TestRunObj<TEST_RUN_OBJ_EQUIPMENT_TYPE$> = 'Reactor'
|
|
Case EqpType EQ 'T'
|
|
TestRunObj<TEST_RUN_OBJ_EQUIPMENT_TYPE$> = 'Non-Reactor'
|
|
End Case
|
|
TestRunObj<TEST_RUN_OBJ_PROD_SPEC_ID$> = TestRunRec<TEST_RUN_PROD_SPEC_ID$>
|
|
TestRunObj<TEST_RUN_OBJ_LSL_USER_ID$> = TestRunRec<TEST_RUN_LSL_USER_ID$>
|
|
TestRunObj<TEST_RUN_OBJ_RDS_ID$> = TestRunRec<TEST_RUN_RDS_ID$>
|
|
|
|
TWKeys = TestRunRec<TEST_RUN_TEST_RUN_WAFER_IDS$>
|
|
TWUsageProds = ''
|
|
TWUsageQtys = ''
|
|
for each TWKey in TWKeys using @VM setting tPos
|
|
TRWRec = Test_Run_Services('GetTestRunWaferByID', TWKey)
|
|
TestWaferProdName = XLATE('TEST_WAFER_PROD', TRWRec<TEST_RUN_WAFER_TEST_WAFER_PROD_ID$>, TEST_WAFER_PROD_PART_NAME$, 'X')
|
|
Locate TestWaferProdName in TWUsageProds setting iPos then
|
|
TWUsageProds<1,iPos> = TestWaferProdName
|
|
TWUsageQtys<1,iPos> = TWUsageQtys<1,iPos> + 1
|
|
end else
|
|
TWUsageProds<1,-1> = TestWaferProdName
|
|
TWUsageQtys<1,-1> = 1
|
|
end
|
|
Next TWKey
|
|
TestRunObj<TEST_RUN_OBJ_TEST_RUN_WAFER_PRODS$> = TWUsageProds
|
|
TestRunObj<TEST_RUN_OBJ_TEST_RUN_WAFER_PRODS_QTYS$> = TWUsageQtys
|
|
|
|
Response = TestRunObj
|
|
end service
|
|
|
|
Service GetTestWaferUsageByDateSpan(StartDtm, StopDtm)
|
|
|
|
TestWaferData = ''
|
|
if StopDTM EQ '' then
|
|
StopDTM = SRP_Datetime('Now')
|
|
end
|
|
If StartDTM EQ '' then
|
|
StartDTM = SRP_Datetime('AddDays', StopDtm, -30)
|
|
end
|
|
//Get a list of Test Run keys
|
|
TestRunKeys = Test_Run_Services('GetTestRunKeysByDateSpan', StartDtm, StopDtm)
|
|
|
|
For each TestRunKey in TestRunKeys using @VM setting tPos
|
|
//Get all Product usages and their quantities
|
|
TestRunRec = Database_Services('ReadDataRow', 'TEST_RUN', TestRunKey)
|
|
TWUsageKeys = TestRunRec<TEST_RUN_TEST_RUN_WAFER_IDS$>
|
|
TWUsageData = ''
|
|
for each TWUsageKey in TWUsageKeys using @VM setting twPos
|
|
TWProdTypeKey = Xlate('TEST_RUN_WAFER', TWUsageKey, TEST_RUN_WAFER_TEST_WAFER_PROD_ID$, 'X')
|
|
TWProdType = Xlate('TEST_WAFER_PROD', TWProdTypeKey, TEST_WAFER_PROD_PART_NAME$, 'X')
|
|
Locate TWProdType in TWUsageData<1> using @VM setting twuPos then
|
|
TWUsageData<2, twuPos> = TWUsageData<2, twuPos> + 1
|
|
end else
|
|
TWUsageData<1, -1> = TWProdType
|
|
TWUsageData<2, -1> = 1
|
|
end
|
|
|
|
|
|
Next TWUsageKey
|
|
|
|
For each TWUsage in TWUsageData<1> using @VM setting aPos
|
|
TWLine = ''
|
|
TWLine<1, TEST_RUN_OBJ_TEST_RUN_ID$> = TestRunKey
|
|
TWLine<1, TEST_RUN_OBJ_RUN_DTM$> = OConv(TestRunRec<TEST_RUN_RUN_DTM$>, 'DT')
|
|
TWLine<1, TEST_RUN_OBJ_RUN_TYPE$> = XLATE('TEST_RUN_TYPE', TestRunRec<TEST_RUN_RUN_TYPE_ID$>, 'RUN_TYPE', 'X')
|
|
TWLine<1, TEST_RUN_OBJ_EQUIPMENT_ID$> = TestRunRec<TEST_RUN_EQUIPMENT_ID$>
|
|
TWLine<1, TEST_RUN_OBJ_EQUIPMENT_TYPE$> = TestRunRec<TEST_RUN_EQUIPMENT_TYPE$>
|
|
TWLine<1, TEST_RUN_OBJ_PROD_SPEC_ID$> = TestRunRec<TEST_RUN_PROD_SPEC_ID$>
|
|
TWLine<1, TEST_RUN_OBJ_LSL_USER_ID$> = TestRunRec<TEST_RUN_LSL_USER_ID$>
|
|
TWLine<1, TEST_RUN_OBJ_RDS_ID$> = TestRunRec<TEST_RUN_RDS_ID$>
|
|
TWLine<1, TEST_RUN_OBJ_TEST_RUN_WAFER_PRODS$> = TWUsage
|
|
TWLine<1, TEST_RUN_OBJ_TEST_RUN_WAFER_PRODS_QTYS$> = TWUsageData<2, aPos>
|
|
TestWaferData<-1> = TWLine
|
|
Next TWUsage
|
|
Next TestRunKey
|
|
|
|
Response = TestWaferData
|
|
end service
|
|
|
|
Service GetTestRunKeysByDateSpan(StartDtm, StopDtm)
|
|
Begin Case
|
|
Case StartDTM EQ '' AND StopDTM EQ ''
|
|
//Set search date for last 24 hour period
|
|
StopDTM = SRP_Datetime('Now')
|
|
StartDTM = SRP_Datetime('AddHours', StopDTM, -24)
|
|
Case StartDTM EQ '' AND StopDTM NE ''
|
|
//Set search start date 24 hours prior to stopDTM
|
|
StartDTM = SRP_Datetime('AddHours', StopDTM, -24)
|
|
Case StartDTM NE '' AND StopDTM EQ ''
|
|
//Set search start date to current dtm
|
|
StopDTM = SRP_Datetime('Now')
|
|
End Case
|
|
|
|
table = "TEST_RUN"
|
|
Open "DICT ":table To @DICT Else
|
|
Error_Services('Add', 'Error opening TEST_RUN dictionary')
|
|
End
|
|
If Error_Services('NoError') then
|
|
srch_strng = "RUN_DTM":@VM:StartDTM:'~':StopDTM:@FM
|
|
keylist = ""
|
|
option = ""
|
|
flag = ""
|
|
Btree.Extract(srch_strng, table, @DICT, keylist, option, flag)
|
|
Response = keylist
|
|
end
|
|
|
|
|
|
|
|
end service
|
|
|
|
Service GetTestRunKeysByEqp(EquipType, EquipID)
|
|
|
|
end service
|
|
|
|
Service GetTestRunKeysByEqpType(EqpType)
|
|
|
|
end service
|
|
|
|
Service GetTestRunKeysByPSN(PSNo)
|
|
|
|
end service
|
|
|
|
Service GetTestRunKeysByRDS(RDSNo)
|
|
table = "TEST_RUN"
|
|
Open "DICT ":table To @DICT Else
|
|
Error_Services('Add', 'Error opening TEST_RUN dictionary')
|
|
End
|
|
If Error_Services('NoError') then
|
|
srch_strng = "RDS_ID":@VM:RDSNo:@FM
|
|
keylist = ""
|
|
option = ""
|
|
flag = ""
|
|
Btree.Extract(srch_strng, table, @DICT, keylist, option, flag)
|
|
Response = keylist
|
|
end
|
|
end service
|
|
|
|
Service GetTestRunWaferByID(TRWaferID)
|
|
If TRWaferID NE '' then
|
|
If RowExists('TEST_RUN_WAFER', TRWaferID) then
|
|
Response = Database_Services('ReadDataRow', 'TEST_RUN_WAFER', TRWaferID)
|
|
If Error_Services('HasError') then
|
|
Response = ''
|
|
Error_Services('Add', 'Error reading TEST_RUN_WAFER record with ID ' : TRWaferID)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'No TEST_RUN_WAFER record found that matches key value.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'TRWaferID was null')
|
|
end
|
|
end service
|
|
|
|
Service GetTestRunWaferKeysByProdID(ProdID)
|
|
|
|
end service
|
|
|
|
Service GenerateTWCSVReport(StartDTM, StopDTM, SavePath)
|
|
If SavePath NE '' then
|
|
CSVData = 'ID' : @VM : 'Run Time' : @VM : 'Test Run Type' : @VM : 'Equipment ID' : @VM : 'Equipment Type' : @VM : 'PSN' : @VM : 'User' : @VM : 'RDS' : @VM : 'Test Wafer Type' : @VM : 'Wfr Qty' : @FM
|
|
CSVData := Test_Run_Services('GetTestWaferUsageByDateSpan', StartDTM, StopDTM)
|
|
swap @VM with ',' in CSVData
|
|
swap @FM with CRLF$ in CSVData
|
|
If Not(File_Services('CheckFileExtension', SavePath, 'csv')) then
|
|
SavePath = SavePath : '.csv'
|
|
end
|
|
OSWrite CSVData To SavePath
|
|
WriteFailure = Status()
|
|
If WriteFailure then
|
|
Begin Case
|
|
Case WriteFailure EQ 1
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, Bad OS filename.')
|
|
Case WriteFailure EQ 2
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, Access denied by operating system.')
|
|
Case WriteFailure EQ 3
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, Disk or directory full.')
|
|
Case WriteFailure EQ 4
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, File does not exist.')
|
|
Case WriteFailure EQ 5
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, Unknown error.')
|
|
Case WriteFailure EQ 6
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, Attempt to write to a read-only file.')
|
|
End Case
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in TEST_RUN_SERVICES -> GenerateTWCSVReport, No SavePath provided.')
|
|
end
|
|
|
|
end service
|
|
|
|
Service IsNewTWSystemActive(UserId)
|
|
IsTWSystemActive = False$
|
|
If UserId EQ '' then
|
|
UserId = @USER4
|
|
end
|
|
TWTrackingSystemActive = Database_Services('ReadDataColumn', 'APP_INFO', 'NEW_TW_SYSTEM_ACTIVE_SWITCH', 1, True$, 0, False$)
|
|
If TWTrackingSystemActive EQ True$ then
|
|
IsTWSystemActive = True$
|
|
end else
|
|
If MemberOf(UserId, 'TW_TRACKING_TEST') then
|
|
IsTWSystemActive = True$
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|