From 86595476d5f406dcfde1e97f5652414fefb95d9d Mon Sep 17 00:00:00 2001 From: "Ouellette Jonathan (CSC FI SPS MESLEO)" Date: Tue, 11 Mar 2025 18:55:44 +0100 Subject: [PATCH] Merged PR 12618: Moved TW Reqd check after check for RDS supplier lot no Moved TW Reqd check after check for RDS supplier lot no --- LSL2/STPROC/SCAN_SERVICES.txt | 4116 +++++++++++++++++---------------- 1 file changed, 2063 insertions(+), 2053 deletions(-) diff --git a/LSL2/STPROC/SCAN_SERVICES.txt b/LSL2/STPROC/SCAN_SERVICES.txt index ef2f29e..51a64e0 100644 --- a/LSL2/STPROC/SCAN_SERVICES.txt +++ b/LSL2/STPROC/SCAN_SERVICES.txt @@ -62,7 +62,7 @@ objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, Comma$, He LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM GoToService else - Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.') + Error_Services('Add', Service : ' is not a valid service request within the ' : ServiceModule : ' module.') end Return Response OR '' @@ -81,13 +81,13 @@ Options SCAN_TYPES = 'LOCATION', 'TOOL' Service AddNotAcceptableReason(Reason) - - If Len(NotAcceptableReasons@) then - NotAcceptableReasons@ := @FM : Reason - end else - NotAcceptableReasons@ = Reason - end - + + If Len(NotAcceptableReasons@) then + NotAcceptableReasons@ := @FM : Reason + end else + NotAcceptableReasons@ = Reason + end + end service @@ -97,9 +97,9 @@ end service // Returns the most current not acceptable reason. //---------------------------------------------------------------------------------------------------------------------- Service GetNotAcceptableReason() - - Response = NotAcceptableReasons@[-1, 'B' : @FM] - + + Response = NotAcceptableReasons@[-1, 'B' : @FM] + End Service @@ -109,9 +109,9 @@ End Service // Returns the stack of not acceptable reasons. This will be @FM delimited. //---------------------------------------------------------------------------------------------------------------------- Service GetNotAcceptableReasons() - - Response = NotAcceptableReasons@ - + + Response = NotAcceptableReasons@ + End Service @@ -121,9 +121,9 @@ End Service // Clears all not acceptable reasons. //---------------------------------------------------------------------------------------------------------------------- Service ClearNotAcceptableReasons() - - NotAcceptableReasons@ = '' - + + NotAcceptableReasons@ = '' + End Service @@ -142,13 +142,13 @@ End Service // end //---------------------------------------------------------------------------------------------------------------------- Service HasNotAcceptableReason() - - If Len(NotAcceptableReasons@) then - Response = True$ - end else - Response = False$ - end - + + If Len(NotAcceptableReasons@) then + Response = True$ + end else + Response = False$ + end + End Service @@ -159,13 +159,13 @@ End Service // HasError service and exists for improved readability. //---------------------------------------------------------------------------------------------------------------------- Service NoNotAcceptableReason() - - If Len(NotAcceptableReasons@) then - Response = False$ - end else - Response = True$ - end - + + If Len(NotAcceptableReasons@) then + Response = False$ + end else + Response = True$ + end + End Service @@ -175,22 +175,22 @@ End Service // Creates a new database row in the SCANS table. Retruns the Key ID to the SCANS table if successful. //---------------------------------------------------------------------------------------------------------------------- Service CreateScansRow(ScanType=SCAN_TYPES) - - ScanID = RTI_CreateGUID() - - If ScanID NE '' then - ScansRow = '' - ScansRow = Date() - ScansRow = Time() - ScansRow = ScanType - ScansRow = False$ - Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow, True$, False$, True$) - end else - Error_Services('Add', 'ScanID was not created in the ' : Service : ' service.') - end - - Response = ScanID - + + ScanID = RTI_CreateGUID() + + If ScanID NE '' then + ScansRow = '' + ScansRow = Date() + ScansRow = Time() + ScansRow = ScanType + ScansRow = False$ + Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow, True$, False$, True$) + end else + Error_Services('Add', 'ScanID was not created in the ' : Service : ' service.') + end + + Response = ScanID + end service @@ -200,20 +200,20 @@ end service // Returns the database row from the SCANS table for the indicated Scan ID. The default format is MultiValue. //---------------------------------------------------------------------------------------------------------------------- Service GetScansRow(ScanID, ReturnJSON) - - ScansRow = '' - - If ScanID NE '' then - ScansRow = Database_Services('ReadDataRow', 'SCANS', ScanID) - If ReturnJSON EQ True$ then - ScansRow = Scan_Services('ConvertMVScanToJSON', ScanID, ScansRow) - end - end else - Error_Services('Add', 'ScanID argument was missing in the ' : Service : ' service.') - end - - Response = ScansRow - + + ScansRow = '' + + If ScanID NE '' then + ScansRow = Database_Services('ReadDataRow', 'SCANS', ScanID) + If ReturnJSON EQ True$ then + ScansRow = Scan_Services('ConvertMVScanToJSON', ScanID, ScansRow) + end + end else + Error_Services('Add', 'ScanID argument was missing in the ' : Service : ' service.') + end + + Response = ScansRow + end service @@ -223,13 +223,13 @@ end service // Returns the database row from the SCANS table for the indicated Scan ID. The default format is MultiValue. //---------------------------------------------------------------------------------------------------------------------- Service SetScansRow(ScanID, ScansRow) - - If (ScanID NE '') AND (ScansRow NE '') then - Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow) - end else - Error_Services('Add', 'ScanID or ScansRow argument was missing in the ' : Service : ' service.') - end - + + If (ScanID NE '') AND (ScansRow NE '') then + Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow) + end else + Error_Services('Add', 'ScanID or ScansRow argument was missing in the ' : Service : ' service.') + end + end service @@ -242,309 +242,315 @@ end service // evaluated on a case by case basis. //---------------------------------------------------------------------------------------------------------------------- Service ProcessScanData(ScanID, ScanJSON) - - If ( (ScanID NE '') AND (ScanJSON NE '') ) then - hScanJSON = '' - ParseResponse = SRP_JSON(hScanJSON, 'PARSE', ScanJSON) - If (ParseResponse EQ '') then - - ScanData = SRP_JSON(hScanJSON, 'GetValue', 'scanData') - // Code 3of9 encodes the asterisk and underscore characters. These need to be decoded. - If ScanData NE '' then Scan_Services('DecodeScanData', ScanData) - // Confirm that this is a valid Scan ID. - ScansRow = Database_Services('ReadDataRow', 'SCANS', ScanID) - If Error_Services('NoError') then - // Use the system variables to evaluate calculated columns easily. - @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') - @ID = ScanID - @RECORD = ScansRow - Action = '' - ColumnIndex = '' - ColumnValue = '' - - // Identify the scan data based on the data identifier prefix (if any). Otherwise, assume this is a - // type of cassette ID (i.e., RDS or WMO). - Begin Case - - //DPC - 3/18/20 - added validation to allow 1T scans to be interpreted as RDS or Supplier Lot code - //1T could be supplier lot (Global Wafer and Sumco Japan) or could be IFX internal lot (RDS) - //2T is always supplier lot - Case ( (ScanData[1, 2] EQ '1T') or (ScanData[1, 2] EQ '2T') ) - // Supplier lot scan. - Convert '_' to '-' in ScanData - LotID = ScanData[3, 999] - Begin Case - Case ( RowExists('RDS', LotId) EQ True$ AND ScanData[1, 2] EQ '1T') - ScansRow = LotID - Case ScanData[1, 4] EQ '1TTW' - ValidTWLot = False$ - If RowExists('LOT', LotId) then - TWLots = ScansRow - Locate LotId in TWLots using @VM setting twPos then - Error_Services('Add', LotID : ' has already been added as a test wafer lot being used.') - end else - LotCurrentOperation = Lot_Services('GetLotCurrOperationName', LotId) - If LotCurrentOperation NE 'TW_CREATE' AND LotCurrentOperation NE 'TW_CLOSE' then - LotCurrWfrQty = Database_Services('ReadDataColumn', 'LOT', LotId, LOT_WAFER_QTY$, True$, 0, False$) - If LotCurrWfrQty GT 0 then - ScansRow = LotID - end else - Error_Services('Add', LotID : ' does not have enough wafers to be used.') - end - end else - Error_Services('Add', LotID : ' is not at a valid operation for use.') - end - end - end else - Error_Services('Add', LotID : ' is not a valid test wafer lot ID.') - end - - Case Otherwise$ - ScansRow = LotID - End Case - Case ScanData[1, 5] EQ 'RESET' - - ScansRow = 'RESET' - ScansRow = '' - ScansRow = '' - ScansRow = '' - ScansRow = '' - - Case ScanData[1, 2] EQ '1H' - // Employee ID scan. Set the EMPLOYEE_ID column and check the - // EMPLOYEE_AUTHORIZED and EMPLOYEE_NOT_AUTHORIZED_REASON column values to determine if the - // scan data is valid. - {EMPLOYEE_ID} = ScanData[3, 999] - EmployeeAuthorized = {EMPLOYEE_AUTHORIZED} - EmployeeActive = Xlate('LSL_USERS', {EMPLOYEE_ID}, 'ACTIVE', 'X') - - ScansRow = 0 - Begin Case - Case EmployeeAuthorized NE True$ - // Regardless of the not authorized reason, the scan data will be considered invalid. - EmployeeNotAuthorizedReason = {EMPLOYEE_NOT_AUTHORIZED_REASON} - Error_Services('Add', EmployeeNotAuthorizedReason) - Case EmployeeActive NE True$ - Error_Services('Add', 'Inactive employee.') - Case Otherwise$ - ScansRow = {EMPLOYEE_ID} - End Case - - Case ScanData[1, 3] EQ '10S' - - // Tool ID scan. A determination needs to be made to see if this is a transfer tool or a process - // tool. Transfer tools do not require employee authorization, but process tools do. - // - // If this is a non-existent tool or if the current Employee ID is not authorized - // will the scan data be considered invalid. However, if there is no Employee ID, then do not - // use this to invalidate the scan data. - ScanData = ScanData[4, 999] - ToolID = ScanData[1, '.'] - LoadLock = ScanData[Col2() + 1, 1] - ToolRow = Database_Services('ReadDataRow', 'TOOL', ToolID) - If Error_Services('NoError') then - ScansRow = 'TOOL' - ToolType = ToolRow<2> - Begin Case - Case ToolType _EQC 'Reactor' - // Clear the Location ID and set the Tool ID column to determine if the current Employee ID - // is authorized. - {LOCATION_ID} = '' - {TOOL_ID} = ToolID - EmployeeAuthorized = {EMPLOYEE_AUTHORIZED} - If (EmployeeAuthorized NE True$) AND ({EMPLOYEE_ID} NE '') then - // Regardless of the not authorized reason, the scan data will be considered invalid. - EmployeeNotAuthorizedReason = {EMPLOYEE_NOT_AUTHORIZED_REASON} - Error_Services('Add', EmployeeNotAuthorizedReason) - end else - * If LoadLock EQ '' then LoadLock = 'NA' ; // NA means Not Applicable. - ReactorID = ToolID[2, 999] - LoadLockReq = Xlate('REACTOR', ReactorID, 'LOAD_LOCK_REQ', 'X') - //LoadLockReq = Xlate('REACTOR', ReactorID, REACTOR_PICK_PLACE$, 'X') - - Begin Case - Case (LoadLockReq EQ True$) - If (LoadLock NE '') then - If ( (LoadLock EQ 'L') or (LoadLock EQ 'R') ) then - If ScansRow NE '' then - ScansRow = '' - end else - ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. - end - ScansRow = '' ; // Make sure the Location ID is cleared. - ScansRow = ToolID - ScansRow = LoadLock - end else - Error_Services('Add', 'Invalid load lock value "':LoadLock:'".') - end - end else - Error_Services('Add', 'A load lock side "L" or "R" is required for reactor ':ReactorID:'.') - end - Case (LoadLockReq EQ False$) - If ScansRow NE '' then - ScansRow = '' - end else - ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. - end - ScansRow = '' ; // Make sure the Location ID is cleared. - ScansRow = ToolID - ScansRow = LoadLock - End Case - - end - Case ToolType _EQC 'Transfer' - Error_Services('Add', 'Tool type ':ToolType:' is not currently supported by the barcode application.') - // Code below may be implemented down the road. - // This is a transfer tool. Just update the scan resource. - * ScansRow = '' ; // Make sure the Location ID is cleared. - * ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. - * ScansRow = ToolID - Case Otherwise$ - Error_Services('Add', 'Tool type ':ToolType:' is not currently supported by the barcode application.') - End Case - end else - Error_Services('Add', ToolID : ' is not a valid tool ID.') - end - - Case ScanData[1, 2] EQ '1L' - // Location ID scan. Only if this is a non-existent location will the scan data be considered - // invalid. - LocationID = ScanData[3, 999] - Convert '.' to '*' in LocationID - LocationRow = Database_Services('ReadDataRow', 'LOCATION', LocationID) - Convert '*' to '.' in LocationID - If Error_Services('NoError') then - ScansRow = 'LOCATION' - If ScansRow NE '' then ScansRow = '' - ScansRow = '' ; // Make sure the Tool ID is cleared. - ScansRow = '' ; // Make sure the Tool Load Lock is cleared. - ScansRow = '' ; // Make sure the Transfer Tool ID is cleared. - ScansRow = LocationID - end else - Error_Services('Add', LocationID : ' is not a valid location ID.') - end - - Case ScanData[1, 2] EQ '1B' - // Carrier/boat ID scan. Only if this is a non-existent carrier will the scan data be considered - // invalid. - ScanData = ScanData[3, 999] - PLNo = ScanData[1, '.'] - BoatID = ScanData[Col2() + 1, '.'] - If BoatID NE '' then - ScansRow = '' ; // Make sure the Location ID is cleared. - ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. - ScansRow = BoatID - ScansRow = PLNo - end else - Error_Services('Add', ScanData : ' is not a valid boat ID.') - end - Case ScanData[1, 3] EQ 'PWD' - // Password/Signature scan. If the scan is not ready to be accepted or the password does - // not match the password of the employee ID scanned then this will be an invalid scan, - // otherwise the scan will be accepted. - Password = ScanData[4, 999] - If Password NE '' then - EmployeeID = ScansRow - If EmployeeID NE '' then - Authenticated = Security_Services('AuthenticateLSLCredentials', EmployeeID, Password) - If Authenticated EQ True$ then - ScansRow = 1 - end else - ScansRow = 0 - Error_Services('Add', 'Invalid password for user ':EmployeeID:'.') - end - end else - Error_Services('Add', 'An employee ID must be scanned before scanning a password.') - end - end else - Error_Services('Add', 'Invalid password scanned.') - end - Case ScanData[1, 8] EQ 'OVERRIDE' - - Type = ScansRow - - if {EMPLOYEE_ID} NE '' AND ScansRow EQ 1 then - - Username = {EMPLOYEE_ID} - - - Member = False$ - Groups = 'LEAD':@VM:'SUPERVISOR':@VM:'ENGINEER':@VM:'ENG_TECH':@VM:'ROTR_OVERRIDE' - - For each Group in Groups using @VM - Member = MemberOf(Username, Group) - Until Member EQ True$ - Next Group - - if Member EQ True$ then - - IF Type EQ 'ROTR' then - - - Reactor = {TOOL_ID}[2,999] - RDSNo = {CASSETTE_IDS} - Comment = ScanData[13, 999] - //Perform the Override here - overrideLogTable = 'RDS':@VM:'REACTOR' - overrideLogKey = RDSNo:@VM:Reactor - overrideLogUser = {EMPLOYEE_ID} - overrideLogComment = Comment - overrideLogCategory = 'ROTR_BLOCK' - overrideLogCause = Xlate('REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, 'X') - orKey = Override_Log_Services('Create', overrideLogTable, overrideLogKey, overrideLogUser, overrideLogComment, overrideLogCategory, overrideLogCause) - - - //Add override key to RDS - RDSRec = Xlate('RDS', RDSNo, '', 'X') - RDSRec = Insert(RDSRec, RDS_OVERRIDE_KEYS$, 1, 0, orKey) - - //Clear Set ROTR status to Passing and clear reason - ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor, True$, 0, False$) - ReactorRec = 'P' - - rotrStatusReason = ReactorRec - ReactorRec = rotrStatusReason - ReactorRec = '' - - ReactorRec = RDSNo - - rotrOverrideCount = ReactorRec - ReactorRec = rotrOverrideCount + 1 - Database_Services('WriteDataRow', 'REACTOR', Reactor, ReactorRec, True$, False$, True$) - Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$) - - ScansRow= '' - Result = 'Override Performed successfully' - end - - end else - Error_Services('Add', 'Selected Employee is not authorized to perform an override') - end - end - Case ScanData[1, 2] EQ '5T' - //Tencor Scan - Note this is only for loading cassette ID into Tencor tool - ScansRow = 'TENCOR_LOAD' - ScansRow= ScanData[3,99] - Case ScanData[1, 16] EQ 'TWQUANTITYUPDATE' - - TWLot = Field(ScanData, '|', 2) - TWLotQuantity = Field(ScanData, '|', 3) - ThisScanTWLots = ScansRow - - Locate TWLot in ThisScanTWLots using @VM setting twPOS then - ScansRow = TWLotQuantity - end - - Case ScanData[1, 17] EQ 'TESTRUNTYPEUPDATE' - TestRunTypeId = Field(ScanData, '|', 2) - ScansRow = TestRunTypeId - //ScansRow = TestRunTypeName - - Case Len(ScanData) GE 22 and ScanData[1, 22] EQ 'LAST_CASSETTE_TEST_ACK' - RDSNo = {CASSETTE_IDS} - Reactor = {TOOL_ID}[2,999] - - WO = Xlate('RDS', RDSNo, RDS_WO$, 'X') + + If ( (ScanID NE '') AND (ScanJSON NE '') ) then + hScanJSON = '' + ParseResponse = SRP_JSON(hScanJSON, 'PARSE', ScanJSON) + If (ParseResponse EQ '') then + + ScanData = SRP_JSON(hScanJSON, 'GetValue', 'scanData') + // Code 3of9 encodes the asterisk and underscore characters. These need to be decoded. + If ScanData NE '' then Scan_Services('DecodeScanData', ScanData) + // Confirm that this is a valid Scan ID. + ScansRow = Database_Services('ReadDataRow', 'SCANS', ScanID) + If Error_Services('NoError') then + // Use the system variables to evaluate calculated columns easily. + @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') + @ID = ScanID + @RECORD = ScansRow + Action = '' + ColumnIndex = '' + ColumnValue = '' + + // Identify the scan data based on the data identifier prefix (if any). Otherwise, assume this is a + // type of cassette ID (i.e., RDS or WMO). + Begin Case + + //DPC - 3/18/20 - added validation to allow 1T scans to be interpreted as RDS or Supplier Lot code + //1T could be supplier lot (Global Wafer and Sumco Japan) or could be IFX internal lot (RDS) + //2T is always supplier lot + Case ( (ScanData[1, 2] EQ '1T') or (ScanData[1, 2] EQ '2T') ) + // Supplier lot scan. + Convert '_' to '-' in ScanData + LotID = ScanData[3, 999] + Begin Case + Case ( RowExists('RDS', LotId) EQ True$ AND ScanData[1, 2] EQ '1T') + ScansRow = LotID + Case ScanData[1, 4] EQ '1TTW' + ValidTWLot = False$ + If RowExists('LOT', LotId) then + TWLots = ScansRow + Locate LotId in TWLots using @VM setting twPos then + Error_Services('Add', LotID : ' has already been added as a test wafer lot being used.') + end else + LotCurrentOperation = Lot_Services('GetLotCurrOperationName', LotId) + If LotCurrentOperation NE 'TW_CREATE' AND LotCurrentOperation NE 'TW_CLOSE' then + LotCurrWfrQty = Database_Services('ReadDataColumn', 'LOT', LotId, LOT_WAFER_QTY$, True$, 0, False$) + If LotCurrWfrQty GT 0 then + If ScansRow EQ '' AND ScansRow NE '' then + ScansRow = 4;//Standard Sampling + end + ScansRow = LotID + ThisScanTWLots = ScansRow + Locate LotID in ThisScanTWLots using @VM setting twPOS then + ScansRow = 1 + end + end else + Error_Services('Add', LotID : ' does not have enough wafers to be used.') + end + end else + Error_Services('Add', LotID : ' is not at a valid operation for use.') + end + end + end else + Error_Services('Add', LotID : ' is not a valid test wafer lot ID.') + end + + Case Otherwise$ + ScansRow = LotID + End Case + Case ScanData[1, 5] EQ 'RESET' + + ScansRow = 'RESET' + ScansRow = '' + ScansRow = '' + ScansRow = '' + ScansRow = '' + + Case ScanData[1, 2] EQ '1H' + // Employee ID scan. Set the EMPLOYEE_ID column and check the + // EMPLOYEE_AUTHORIZED and EMPLOYEE_NOT_AUTHORIZED_REASON column values to determine if the + // scan data is valid. + {EMPLOYEE_ID} = ScanData[3, 999] + EmployeeAuthorized = {EMPLOYEE_AUTHORIZED} + EmployeeActive = Xlate('LSL_USERS', {EMPLOYEE_ID}, 'ACTIVE', 'X') + + ScansRow = 0 + Begin Case + Case EmployeeAuthorized NE True$ + // Regardless of the not authorized reason, the scan data will be considered invalid. + EmployeeNotAuthorizedReason = {EMPLOYEE_NOT_AUTHORIZED_REASON} + Error_Services('Add', EmployeeNotAuthorizedReason) + Case EmployeeActive NE True$ + Error_Services('Add', 'Inactive employee.') + Case Otherwise$ + ScansRow = {EMPLOYEE_ID} + End Case + + Case ScanData[1, 3] EQ '10S' + + // Tool ID scan. A determination needs to be made to see if this is a transfer tool or a process + // tool. Transfer tools do not require employee authorization, but process tools do. + // + // If this is a non-existent tool or if the current Employee ID is not authorized + // will the scan data be considered invalid. However, if there is no Employee ID, then do not + // use this to invalidate the scan data. + ScanData = ScanData[4, 999] + ToolID = ScanData[1, '.'] + LoadLock = ScanData[Col2() + 1, 1] + ToolRow = Database_Services('ReadDataRow', 'TOOL', ToolID) + If Error_Services('NoError') then + ScansRow = 'TOOL' + ToolType = ToolRow<2> + Begin Case + Case ToolType _EQC 'Reactor' + // Clear the Location ID and set the Tool ID column to determine if the current Employee ID + // is authorized. + {LOCATION_ID} = '' + {TOOL_ID} = ToolID + EmployeeAuthorized = {EMPLOYEE_AUTHORIZED} + If (EmployeeAuthorized NE True$) AND ({EMPLOYEE_ID} NE '') then + // Regardless of the not authorized reason, the scan data will be considered invalid. + EmployeeNotAuthorizedReason = {EMPLOYEE_NOT_AUTHORIZED_REASON} + Error_Services('Add', EmployeeNotAuthorizedReason) + end else + * If LoadLock EQ '' then LoadLock = 'NA' ; // NA means Not Applicable. + ReactorID = ToolID[2, 999] + LoadLockReq = Xlate('REACTOR', ReactorID, 'LOAD_LOCK_REQ', 'X') + //LoadLockReq = Xlate('REACTOR', ReactorID, REACTOR_PICK_PLACE$, 'X') + + Begin Case + Case (LoadLockReq EQ True$) + If (LoadLock NE '') then + If ( (LoadLock EQ 'L') or (LoadLock EQ 'R') ) then + If ScansRow NE '' then + ScansRow = '' + end else + ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. + end + ScansRow = '' ; // Make sure the Location ID is cleared. + ScansRow = ToolID + ScansRow = LoadLock + end else + Error_Services('Add', 'Invalid load lock value "':LoadLock:'".') + end + end else + Error_Services('Add', 'A load lock side "L" or "R" is required for reactor ':ReactorID:'.') + end + Case (LoadLockReq EQ False$) + If ScansRow NE '' then + ScansRow = '' + end else + ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. + end + ScansRow = '' ; // Make sure the Location ID is cleared. + ScansRow = ToolID + ScansRow = LoadLock + End Case + + end + Case ToolType _EQC 'Transfer' + Error_Services('Add', 'Tool type ':ToolType:' is not currently supported by the barcode application.') + // Code below may be implemented down the road. + // This is a transfer tool. Just update the scan resource. + * ScansRow = '' ; // Make sure the Location ID is cleared. + * ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. + * ScansRow = ToolID + Case Otherwise$ + Error_Services('Add', 'Tool type ':ToolType:' is not currently supported by the barcode application.') + End Case + end else + Error_Services('Add', ToolID : ' is not a valid tool ID.') + end + + Case ScanData[1, 2] EQ '1L' + // Location ID scan. Only if this is a non-existent location will the scan data be considered + // invalid. + LocationID = ScanData[3, 999] + Convert '.' to '*' in LocationID + LocationRow = Database_Services('ReadDataRow', 'LOCATION', LocationID) + Convert '*' to '.' in LocationID + If Error_Services('NoError') then + ScansRow = 'LOCATION' + If ScansRow NE '' then ScansRow = '' + ScansRow = '' ; // Make sure the Tool ID is cleared. + ScansRow = '' ; // Make sure the Tool Load Lock is cleared. + ScansRow = '' ; // Make sure the Transfer Tool ID is cleared. + ScansRow = LocationID + end else + Error_Services('Add', LocationID : ' is not a valid location ID.') + end + + Case ScanData[1, 2] EQ '1B' + // Carrier/boat ID scan. Only if this is a non-existent carrier will the scan data be considered + // invalid. + ScanData = ScanData[3, 999] + PLNo = ScanData[1, '.'] + BoatID = ScanData[Col2() + 1, '.'] + If BoatID NE '' then + ScansRow = '' ; // Make sure the Location ID is cleared. + ScansRow = ScansRow ; // Make sure only the first Cassette ID is tracked. + ScansRow = BoatID + ScansRow = PLNo + end else + Error_Services('Add', ScanData : ' is not a valid boat ID.') + end + Case ScanData[1, 3] EQ 'PWD' + // Password/Signature scan. If the scan is not ready to be accepted or the password does + // not match the password of the employee ID scanned then this will be an invalid scan, + // otherwise the scan will be accepted. + Password = ScanData[4, 999] + If Password NE '' then + EmployeeID = ScansRow + If EmployeeID NE '' then + Authenticated = Security_Services('AuthenticateLSLCredentials', EmployeeID, Password) + If Authenticated EQ True$ then + ScansRow = 1 + end else + ScansRow = 0 + Error_Services('Add', 'Invalid password for user ':EmployeeID:'.') + end + end else + Error_Services('Add', 'An employee ID must be scanned before scanning a password.') + end + end else + Error_Services('Add', 'Invalid password scanned.') + end + Case ScanData[1, 8] EQ 'OVERRIDE' + + Type = ScansRow + + if {EMPLOYEE_ID} NE '' AND ScansRow EQ 1 then + + Username = {EMPLOYEE_ID} + + + Member = False$ + Groups = 'LEAD':@VM:'SUPERVISOR':@VM:'ENGINEER':@VM:'ENG_TECH':@VM:'ROTR_OVERRIDE' + + For each Group in Groups using @VM + Member = MemberOf(Username, Group) + Until Member EQ True$ + Next Group + + if Member EQ True$ then + + IF Type EQ 'ROTR' then + + + Reactor = {TOOL_ID}[2,999] + RDSNo = {CASSETTE_IDS} + Comment = ScanData[13, 999] + //Perform the Override here + overrideLogTable = 'RDS':@VM:'REACTOR' + overrideLogKey = RDSNo:@VM:Reactor + overrideLogUser = {EMPLOYEE_ID} + overrideLogComment = Comment + overrideLogCategory = 'ROTR_BLOCK' + overrideLogCause = Xlate('REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, 'X') + orKey = Override_Log_Services('Create', overrideLogTable, overrideLogKey, overrideLogUser, overrideLogComment, overrideLogCategory, overrideLogCause) + + + //Add override key to RDS + RDSRec = Xlate('RDS', RDSNo, '', 'X') + RDSRec = Insert(RDSRec, RDS_OVERRIDE_KEYS$, 1, 0, orKey) + + //Clear Set ROTR status to Passing and clear reason + ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor, True$, 0, False$) + ReactorRec = 'P' + + rotrStatusReason = ReactorRec + ReactorRec = rotrStatusReason + ReactorRec = '' + + ReactorRec = RDSNo + + rotrOverrideCount = ReactorRec + ReactorRec = rotrOverrideCount + 1 + Database_Services('WriteDataRow', 'REACTOR', Reactor, ReactorRec, True$, False$, True$) + Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$) + + ScansRow= '' + Result = 'Override Performed successfully' + end + + end else + Error_Services('Add', 'Selected Employee is not authorized to perform an override') + end + end + Case ScanData[1, 2] EQ '5T' + //Tencor Scan - Note this is only for loading cassette ID into Tencor tool + ScansRow = 'TENCOR_LOAD' + ScansRow= ScanData[3,99] + Case ScanData[1, 16] EQ 'TWQUANTITYUPDATE' + + TWLot = Field(ScanData, '|', 2) + TWLotQuantity = Field(ScanData, '|', 3) + ThisScanTWLots = ScansRow + + Locate TWLot in ThisScanTWLots using @VM setting twPOS then + ScansRow = TWLotQuantity + end + + Case ScanData[1, 17] EQ 'TESTRUNTYPEUPDATE' + TestRunTypeId = Field(ScanData, '|', 2) + ScansRow = TestRunTypeId + + Case Len(ScanData) GE 22 and ScanData[1, 22] EQ 'LAST_CASSETTE_TEST_ACK' + RDSNo = {CASSETTE_IDS} + Reactor = {TOOL_ID}[2,999] + + WO = Xlate('RDS', RDSNo, RDS_WO$, 'X') CassNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X') WoMatKey = WO:'*':CassNo WoMatRecord = Database_Services('ReadDataRow', 'WO_MAT', WoMatKey) @@ -557,655 +563,658 @@ Service ProcessScanData(ScanID, ScanJSON) Reactor_Log_Services('AddComment', Reactor, ConfirmNote, {EMPLOYEE_ID}) Result = 'Test wafer requirement acknowledged' - Case ScanData EQ '' - // Most likely receiving RDS data, so nothing to do here. - Null - Case Otherwise$ - // Assume this is intended to be a Cassette ID scan (either WMO or RDS). Only if this is a - // non-existent carrier will the scan data be considered invalid. - ColumnIndex = SCANS.CASSETTE_IDS$ - CassetteID = ScanData - - ValidCassetteID = False$ ; // Assume Cassette ID is not valid for now. - If Num(CassetteID) then - // Might be an RDS number. - RDSRow = Database_Services('ReadDataRow', 'RDS', CassetteID) - If Error_Services('NoError') then - ValidCassetteID = True$ - end - end else - // Might be a WMO number. - If DCount(CassetteID, '.') EQ 3 then - // Passes the format test. - If ( (CassetteID[1, 1] EQ 'O') or (CassetteID[1, 1] EQ 'I') ) then - IOFlag = CassetteID[1, 1] - CassetteID = CassetteID[2, 999] - end else - IOFlag = '' - end - Convert '.' to '*' in CassetteID - WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', CassetteID) - Convert '*' to '.' in CassetteID - If Error_Services('NoError') then - ValidCassetteID = True$ - end - end - end - If ValidCassetteID EQ True$ then - // This is a valid Cassette ID that needs to be added to this resource. If the Tool - // ID is not populated, then append this Cassette ID to the array, otherwise replace - // the existing Cassette ID with this one. - If ScansRow EQ '' then - // Only append if it doesn't already exists. - Locate CassetteID in ScansRow using @VM setting vPos else - ScansRow = CassetteID - end - end else - ScansRow = CassetteID - end - end else - Error_Services('Add', CassetteID : ' is not a valid Cassette ID.') - end - End Case - - If Error_Services('NoError') then - // Process Scan row data here to determine the type of scan (i.e. Location, Pre-Epi + Load, or Unload). - ScanType = ScansRow - CassetteIDs = ScansRow - NumCass = DCount(CassetteIDs, @VM) - EmployeeID = ScansRow - Begin Case - Case ScanType EQ 'RESET' - Action = 'RESET' - - Case ScanType EQ 'TENCOR_LOAD' - Action = 'TENCOR_LOAD' - If (CassetteIDs EQ '') then - Scan_Services('AddNotAcceptableReason', 'At least one cassette must be scanned to complete a Tencor scan.') - end - - Case ScanType EQ 'LOCATION' - Action = 'PLACE' - If (EmployeeID EQ '') then - Scan_Services('AddNotAcceptableReason', 'EmployeeID required to complete a location scan.') - end - If (CassetteIDs EQ '') then - Scan_Services('AddNotAcceptableReason', 'At least one cassette must be scanned to complete a location scan.') - end - LastCassScanned = CassetteIDs<0, NumCass> - CurrStage = Xlate('RDS', LastCassScanned, 'CURR_STAGE', 'X') - If CurrStage EQ 'UNLOAD' then - Error_Services('Add', '(':LastCassScanned:') Cassette is currently loaded on a tool and is ineligble for a location scan.') - end - - Case ScanType EQ 'TOOL' - // Check if cassette field is populated. If so, then check the cassette's current status to - // determine what the next action will be (i.e. Pre-Epi+Load, Unload, etc.). Ensure we are - // working with an RDS and not a WM_IN or WM_OUT cassette ID. They are not used during the - // "RDS" process. - If (CassetteIDs NE '') then - TestWaferLotData = ScansRow - Abort = False$ - If TestWaferLotData NE '' then - ThisTestRunType = ScansRow - If ThisTestRunType NE '' then - for each TWLot in TestWaferLotData using @VM setting twPOS - If ScansRow NE '' OR ScansRow GT 0 then - TWLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_WAFER_QTY$, True$, 0, False$) - ThisCurrUsageQty = ScansRow - If TWLotCurrQty GT 0 then - If TWLotCurrQty GE ThisCurrUsageQty then - TWLotCurrOperation = Lot_Services('GetLotCurrOperationName', TWLot) - If TWLotCurrOperation NE 'TW_CREATE' AND TWLotCurrOperation NE 'TW_CLOSE' then - TWLotCurrOpen = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_OPEN$, True$, 0, False$) - If Not(TWLotCurrOpen) then - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is closed and cannot be used at this time.') - end - end else - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is currently at ':TWLotCurrOperation:' and cannot be used at this time.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' does not have enough wafers. Please select ' : TWLotCurrQty : ' wafers or less.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' has no wafers and cannot be logged for usage.') - end - end else - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' must have a quantity associated with it.') - end - Until Abort - Next TWLot - end else - Scan_Services('AddNotAcceptableReason', 'A test run type is required to log test wafer usage.') - end - end - // Ensure only one cassette is scanned - If Not(Abort) then - If (NumCass EQ 1) then - CassetteID = CassetteIDs<0, NumCass> - // Ensure we are working with an RDS and not a WM_OUT/WM_IN cassette - If (Count(CassetteID, '.') EQ 0) then - - RDSNo = CassetteID - RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) - - WONo = RDSRec - CassNo = RDSRec - CurrStatus = obj_WO_Mat('CurrStatus', WONo:'*':CassNo) - - - // RDS Format - IsEpiPro = RDS_Services('IsEpiPro', CassetteID) - If IsEpiPro EQ False$ then - // Non-EpiPro RDS - WONo = Xlate('RDS', CassetteID, 'WO', 'X') - CassNo = Xlate('RDS', CassetteID, 'CASS_NO', 'X') - WOMatKey = WONo:'*':CassNo - WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') - If Index(WOMatLocs,'PTI',1) else Error_Services('Add', 'Cassette ':CassetteID:' failed due to missing PTI.') - end else - // EpiPro RDS - OutCassNos = Xlate('RDS', CassetteID, 'OUT_CASS_NO', 'X') - OutCassNos = SRP_Array('Clean', OutCassNos, 'TrimAndMakeUnique', @VM) - For each OutCassNo in OutCassNos using @VM setting oPos - WONo = Xlate('RDS', CassetteID, 'WO', 'X') - CassNo = OutCassNo - WOMatKey = WONo:'*':CassNo - WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') - If Index(WOMatLocs,'PTI',1) else Error_Services('Add', 'Cassette ':CassetteID:' failed due to missing PTI.') - Next OutCassNo - end - - If Error_Services('NoError') then - If CurrStatus NE 'HOLD' then - If (EmployeeID NE '') then - * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - If CurrStage EQ 'VER' then - VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') - If VerSupplID NE False$ then - SupplVerInstAckReq = True$ - end else - SupplVerInstAckReq = False$ - end - end else - SupplVerInstAckReq = False$ - end - - If CurrStage EQ 'LOAD' OR CurrStage EQ 'VER' then - LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') - If LoadSupplID NE False$ then - SupplLoadInstAckReq = True$ - end else - SupplLoadInstAckReq = False$ - end - end else - SupplLoadInstAckReq = False$ - end - - If CurrStage EQ 'UNLOAD' then - UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') - If UnloadSupplID NE False$ then - SupplUnloadInstAckReq = True$ - end else - SupplUnloadInstAckReq = False$ - end - end else - SupplUnloadInstAckReq = False$ - end - - If CurrStage EQ 'POST' then - PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') - If PostSupplID NE False$ then - SupplPostInstAckReq = True$ - end else - SupplPostInstAckReq = False$ - end - end else - SupplPostInstAckReq = False$ - end - - RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') - PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') - FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') - LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') - QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') - LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') - UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') - PostInstAckReq = Xlate('RDS', RDSno, 'POST_INST_ACK_REQ' , 'X') - WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') - // Parse JSON objects - hRDS = SRP_JSON(hScanJSON, 'Get', 'rds') - If (hRDS NE 0) then - - If (SupplVerInstAckReq NE False$) then - SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplVerInstAck') - If (SupplAck EQ True$) then - Supplement_Services('AcknowledgeSupplement', VerSupplID, ScansRow) - end - end - If (SupplLoadInstAckReq NE False$) then - SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplLoadInstAck') - If (SupplAck EQ True$) then - Supplement_Services('AcknowledgeSupplement', LoadSupplID, ScansRow) - end - end - If (SupplUnloadInstAckReq NE False$) then - SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplUnloadInstAck') - If (SupplAck EQ True$) then - Supplement_Services('AcknowledgeSupplement', UnloadSupplID, ScansRow) - end - end - If (SupplPostInstAckReq NE False$) then - SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplPostInstAck') - If (SupplAck EQ True$) then - Supplement_Services('AcknowledgeSupplement', PostSupplID, ScansRow) - end - end - If RDSLayerInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'rdsLayerInstAck') - If PreInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'preInstAck') - If FwiInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'fwiInstAck') - If LwiInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'lwiInstAck') - If QAInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'qaInstAck') - If LoadInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'loadInstAck') - If UnloadInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'unloadInstAck') - If PostInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'postInstAck') - If WaferCountInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'waferCountInstAck') - - Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$) - - * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - If CurrStage EQ 'VER' then - VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') - If VerSupplID NE False$ then - SupplVerInstAckReq = True$ - end else - SupplVerInstAckReq = False$ - end - end else - SupplVerInstAckReq = False$ - end - - If CurrStage EQ 'LOAD' OR CurrStage EQ 'VER' then - LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') - If LoadSupplID NE False$ then - SupplLoadInstAckReq = True$ - end else - SupplLoadInstAckReq = False$ - end - end else - SupplLoadInstAckReq = False$ - end - - If CurrStage EQ 'UNLOAD' then - UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') - If UnloadSupplID NE False$ then - SupplUnloadInstAckReq = True$ - end else - SupplUnloadInstAckReq = False$ - end - end else - SupplUnloadInstAckReq = False$ - end - - If CurrStage EQ 'POST' then - PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') - If PostSupplID NE False$ then - SupplPostInstAckReq = True$ - end else - SupplPostInstAckReq = False$ - end - end else - SupplPostInstAckReq = False$ - end - - RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') - PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') - FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') - LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') - QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') - LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') - UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') - PostInstAckReq = Xlate('RDS', RDSNo, 'POST_INST_ACK_REQ' , 'X') - WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') - - SRP_JSON(hRDS, 'Release') - end - - ToolID = ScansRow - Reactor = ToolID[-1, 'BR'] - Username = ScansRow - WaferCountAck = RDSRec - LLSide = ScansRow - WaferQty = '' - If WaferCountAck EQ True$ then - WaferQty = RDSRec - end else - WaferQty = RDSRec - end - // Check signature fields to determine where the lot is in the RDS process. The service should - // use the signatures in the RDS table, not the WO_MAT table, so that we can support both - // EpiPro and non-EpiPro lots. - WONo = RDSRec - CassNo = RDSRec - CurrStatus = obj_WO_Mat('CurrStatus', WONo:'*':CassNo) - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - - Begin Case - - Case CurrStage _EQC 'VER' - Action = 'LOAD' - - // Check if both the PRE and LOAD stages are ready to sign - // If a Pre Clean is required, then the OpenInsight UI must be used for now until support for cleans operations - // is added to the barcode web application. - LotNo = RDSRec - PreCleanReq = False$ - CleanInspKeyID = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') - * If CleanInspKeyID NE '' then PreCleanReq = Xlate('CLEAN_INSP', CleanInspKeyID, 'SPEC_CLEAN_REQ', 'X') - PSN = RDSRec - PrePRSStageKey = PSN:'*PRE' - PreCleanReq = Xlate('PRS_STAGE', PrePRSStageKey, 'CLEAN_SIG_REQ', 'X') - - If ( (PreCleanReq EQ False$) or (PreCleanReq EQ '') ) then - // The first run on a reactor requires that RDS Layer parameters be entered manually. This is when Prove-in - // occurs. - RunOrderNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X') - If RunOrderNo GT 1 then - // Wafer is eligible to have recipe parameters automatically applied from the previous cassette. - // Only copy RDS layer parameters if they do not already exist. This way we do not overwrite - // manually entered parameters. - LSParmsComp = Xlate('RDS', RDSNo, 'LS_PARMS_COMP', 'X') - FirstParmsComp = LSParmsComp<1,1> - If (FirstParmsComp EQ False$) then RDS_Services('CopyRDSLayerParameters', RDSNo) - //Test Wafer logging verification - IsTWLoggingReqd = RDS_Services('IsTWLoggingReqd', RDSNo) - If IsTWLoggingReqd NE True$ OR TestWaferLotData NE '' then - - // Supplier lot verification - ScannedSuppLot = ScansRow - RDSSuppLot = RDSRec - If (ScannedSuppLot NE '') then - If (ScannedSuppLot _EQC RDSSuppLot) then - WaferCountAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ', 'X') - If WaferCountAckReq EQ False$ then - PreStageReady = '' - LoadStageReady = '' - PreStageReady = QA_Services('PreEpiSignatureReady', RDSNo, Username, WaferQty, Reactor) - If PreStageReady EQ True$ then - LoadStageReady = QA_Services('LoadSignatureReady', RDSNo, Username, WaferQty, LLSide, True$, Reactor) - If (LoadStageReady NE True$) then - // Why is it not ready? - ErrorMsg = Error_Services('GetMessage') - Begin Case - Case IndexC(ErrorMsg, 'supplement', 1) - // Clear the error to return a JSON payload and handle the acknowledgements. - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', ErrorMsg) - Case IndexC(ErrorMsg, 'ROTR', 1) - ROTRBlock = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS$, True$, 0, False$) - ROTRBlockReason = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, True$, 0, False$) - ROTREnabled = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ENABLE_ROTR$, True$, 0, False$) - If ( (ROTRBlock NE 'P') AND (ROTREnabled EQ True$) ) then - // Clear the error to return a JSON payload and allow for OVERRIDE scan. - ScansRow = True$ - ScansRow = ROTRBlockReason - ScansRow = 'ROTR' - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', "ROTR Load Block Enabled") - end else - ScansRow = False$ - ScansRow = '' - ScansRow = '' - end - End Case - end - end else - // Why is it not ready? - ErrorMsg = Error_Services('GetMessage') - Begin Case - Case IndexC(ErrorMsg, 'supplement', 1) - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', ErrorMsg) - End Case - end - end else - Scan_Services('AddNotAcceptableReason', 'The cassette wafer count must be verified against the scheduled wafer count to proceed.') - end - end else - ScansRow = '' - Error_Services('Add', '(':CassetteID:') Supplier lot mismatch.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Supplier lot scan required in order to complete a tool scan.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafers are required to be logged with this run.') - end - end else - Error_Services('Add', '(':CassetteID:') The first run must be completed using the OpenInsight user interface.') - end - end else - Error_Services('Add', '(':CassetteID:') A pre-clean is required for this RDS. The OpenInsight user interface must be used to proceed.') - end - Case CurrStage _EQC 'LOAD' - Action = 'LOAD' - IsTWLoggingReqd = RDS_Services('IsTWLoggingReqd', RDSNo) - If IsTWLoggingReqd NE True$ OR TestWaferLotData NE '' then - ScannedSuppLot = ScansRow - RDSSuppLot = RDSRec - If (ScannedSuppLot NE '') then - If (ScannedSuppLot _EQC RDSSuppLot) then - // Scheduled tool verification (only supports reactors at the moment) - ClearSelect - SchedTool = Xlate('RDS', RDSNo, 'SCHED_REACTOR', 'X') - ClearSelect - SchedTool = 'R':SchedTool - ScanTool = ScansRow - If SchedTool EQ ScanTool then - // Check if LOAD stage is ready to sign - RDSLayerAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ', 'X') - If RDSLayerAckReq EQ False$ then - If LWIInstAckReq EQ False$ then - If LoadInstAckReq EQ False$ then - LoadStageReady = QA_Services('LoadSignatureReady', RDSNo, Username, WaferQty, LLSide) - If (LoadStageReady NE True$) then - // Why is it not ready? - ErrorMsg = Error_Services('GetMessage') - Begin Case - Case IndexC(ErrorMsg, 'supplement', 1) - // Clear the error to return a JSON payload and handle the acknowledgements. - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', ErrorMsg) - Case IndexC(ErrorMsg, 'ROTR', 1) - ROTRBlock = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS$, True$, 0, False$) - ROTRBlockReason = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, True$, 0, False$) - ROTREnabled = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ENABLE_ROTR$, True$, 0, False$) - If ( (ROTRBlock NE 'P') AND (ROTREnabled EQ True$) ) then - // Clear the error to return a JSON payload and allow for OVERRIDE scan. - ScansRow = True$ - ScansRow = ROTRBlockReason - ScansRow = 'ROTR' - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', "ROTR Load Block Enabled") - end else - ScansRow = False$ - ScansRow = '' - ScansRow = '' - end - End Case - end - end else - Scan_Services('AddNotAcceptableReason', 'The LOAD stage engineering instructions must be acknowledged before the load operation can be signed.') - end - end else - Scan_Services('AddNotAcceptableReason', 'The LWI stage engineering instructions must be acknowledged before the load operation can be signed.') - end - end else - ErrorMessage = 'RDS layer parameters must be reviewed for accuracy and acknowledged before the load operation can be signed.' - Scan_Services('AddNotAcceptableReason', ErrorMessage) - end - end else - Error_Services('Add', 'Scanned tool ':ScanTool:' does not match the scheduled tool ':SchedTool:'. (':RDSNo:')') - end - end else - ScansRow = '' - Error_Services('Add', '(':CassetteID:') Supplier lot mismatch.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Supplier lot scan required in order to complete a tool scan.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafers are required to be logged with this run.') - end - - Case CurrStage _EQC 'UNLOAD' - Action = 'UNLOAD' - // Check if UNLOAD stage is ready to sign - If ( (LWIInstAckReq EQ False$) or (LWIInstAckReq EQ '') ) then - - If ( (UnloadInstAckReq EQ False$) or (UnloadInstAckReq EQ '') ) then - If ( (PostInstAckReq EQ False$) or (PostInstAckReq EQ '') ) then - UnloadStageReady = QA_Services('UnloadSignatureReady', RDSNo, Username, Reactor) - If Not(UnloadStageReady) then - // Why is it not ready? - ErrorMsg = Error_Services('GetMessage') - Begin Case - Case IndexC(ErrorMsg, 'supplement', 1) - Error_Services('Clear') - Scan_Services('AddNotAcceptableReason', ErrorMsg) - Case Otherwise$ - // Keep error on Error_Services stack and return 400 level error. - End Case - end - end else - ScanMsg = 'The POST stage engineering instructions must be acknowledged before the load operation can be signed.' - Scan_Services('AddNotAcceptableReason', ScanMsg) - end - end else - ScanMsg = 'The UNLOAD stage engineering instructions must be acknowledged before the load operation can be signed.' - Scan_Services('AddNotAcceptableReason', ScanMsg) - end - end else - ScanMsg = 'The LWI stage engineering instructions must be acknowledged before the load operation can be signed.' - Scan_Services('AddNotAcceptableReason', ScanMsg) - end - Case CurrStage _EQC 'COMP' - Action = 'COMP' - Error_Services('Add', '(':CassetteID:") Cassette has already been FQA'd.") - Case Otherwise$ - Action = CurrStage - Error_Services('Set', '(':CassetteID:') The ':CurrStage:' is not currently supported by the barcode application.') - End Case - end else - Scan_Services('AddNotAcceptableReason', 'EmployeeID required to complete a tool scan.') - end - end else - Error_Services('Add', '(':CassetteID:') Process Error: cassette is on Hold and may not be signed off.') - end - end - end else - Error_Services('Add', '(':CassetteID:') WMI/WMO cassette are not currently supported for tool scans. The OpenInsight user interface must be used in order to proceed.') - end - end else - // Currently we are only supporting loading one cassette onto a tool at a time. - Error_Services('Add', '(':CassetteID:') Only one cassette can be loaded onto a tool at a time.') - end - end - - end else - If ScansRow NE '' then - ThisTestRunType = ScansRow - ThisUser = ScansRow - If ThisTestRunType NE '' then - If RowExists('LSL_USERS', ThisUser) then - TestWaferLotData = ScansRow - Abort = False$ - for each TWLot in TestWaferLotData using @VM setting twPOS - If ScansRow NE '' OR ScansRow GT 0 then - TWLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_WAFER_QTY$, True$, 0, False$) - ThisCurrUsageQty = ScansRow - If TWLotCurrQty GT 0 then - If TWLotCurrQty GE ThisCurrUsageQty then - TWLotCurrOperation = Lot_Services('GetLotCurrOperationName', TWLot) - If TWLotCurrOperation NE 'TW_CREATE' AND TWLotCurrOperation NE 'TW_CLOSE' then - TWLotCurrOpen = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_OPEN$, True$, 0, False$) - If Not(TWLotCurrOpen) then - - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is closed and cannot be used at this time.') - end - end else - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is currently at ':TWLotCurrOperation:' and cannot be used at this time.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' does not have enough wafers. Please select ' : TWLotCurrQty : ' wafers or less.') - end - end else - Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' has no wafers and cannot be logged for usage.') - end - end else - Abort = True$ - Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' must have a quantity associated with it.') - end - Until Abort - Next TWLot - end else - Scan_Services('AddNotAcceptableReason', 'A User ID Scan is required to log test wafer usage.') - end - end else - Scan_Services('AddNotAcceptableReason', 'A test run type is required to log test wafer usage.') - end - end else - Scan_Services('AddNotAcceptableReason', 'A cassette must be scanned in order to complete a tool scan.') - end - end - - Case Otherwise$ - Scan_Services('AddNotAcceptableReason', 'A location ID or tool ID must be scanned to proceed.') - End Case - end - // If the the scan data is valid, update the scan log before returning to the calling process. - If Error_Services('NoError') then - If Scan_Services('NoNotAcceptableReason') then - ScansRow = True$ - ScansRow = '' - end else - ScansRow = False$ - ScansRow = Scan_Services('GetNotAcceptableReason') - end - end else - ScansRow = False$ - ScansRow = Error_Services('GetMessage') - end - If ScanData NE '' then - ScansRow = Date() - ScansRow = Time() - ScansRow = ScanData - end - ScansRow = Action - // Save error message if present as Database_Services will clear any errors. - ErrorMessage = '' - If Error_Services('HasError') then - ErrorMessage = Error_Services('GetMessage') - end - Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow, True$, False$, True$) - // Restore pre-existing error message if present. - If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) - end - end else - Error_Services('Add', 'Unable to parse the JSON scan data in the ':Service:' service.') - end - SRP_JSON(hScanJSON, 'Release') - end else - Error_Services('Add', 'ScanID or ScanJSON argument was missing in the ' : Service : ' service.') - end - + Case ScanData EQ '' + // Most likely receiving RDS data, so nothing to do here. + Null + Case Otherwise$ + // Assume this is intended to be a Cassette ID scan (either WMO or RDS). Only if this is a + // non-existent carrier will the scan data be considered invalid. + ColumnIndex = SCANS.CASSETTE_IDS$ + CassetteID = ScanData + + ValidCassetteID = False$ ; // Assume Cassette ID is not valid for now. + If Num(CassetteID) then + // Might be an RDS number. + RDSRow = Database_Services('ReadDataRow', 'RDS', CassetteID) + If Error_Services('NoError') then + ValidCassetteID = True$ + end + end else + // Might be a WMO number. + If DCount(CassetteID, '.') EQ 3 then + // Passes the format test. + If ( (CassetteID[1, 1] EQ 'O') or (CassetteID[1, 1] EQ 'I') ) then + IOFlag = CassetteID[1, 1] + CassetteID = CassetteID[2, 999] + end else + IOFlag = '' + end + Convert '.' to '*' in CassetteID + WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', CassetteID) + Convert '*' to '.' in CassetteID + If Error_Services('NoError') then + ValidCassetteID = True$ + end + end + end + If ValidCassetteID EQ True$ then + // This is a valid Cassette ID that needs to be added to this resource. If the Tool + // ID is not populated, then append this Cassette ID to the array, otherwise replace + // the existing Cassette ID with this one. + If ScansRow EQ '' then + // Only append if it doesn't already exists. + Locate CassetteID in ScansRow using @VM setting vPos else + ScansRow = CassetteID + end + end else + ScansRow = CassetteID + end + end else + Error_Services('Add', CassetteID : ' is not a valid Cassette ID.') + end + End Case + + If Error_Services('NoError') then + // Process Scan row data here to determine the type of scan (i.e. Location, Pre-Epi + Load, or Unload). + ScanType = ScansRow + CassetteIDs = ScansRow + NumCass = DCount(CassetteIDs, @VM) + EmployeeID = ScansRow + Begin Case + Case ScanType EQ 'RESET' + Action = 'RESET' + + Case ScanType EQ 'TENCOR_LOAD' + Action = 'TENCOR_LOAD' + If (CassetteIDs EQ '') then + Scan_Services('AddNotAcceptableReason', 'At least one cassette must be scanned to complete a Tencor scan.') + end + + Case ScanType EQ 'LOCATION' + Action = 'PLACE' + If (EmployeeID EQ '') then + Scan_Services('AddNotAcceptableReason', 'EmployeeID required to complete a location scan.') + end + If (CassetteIDs EQ '') then + Scan_Services('AddNotAcceptableReason', 'At least one cassette must be scanned to complete a location scan.') + end + LastCassScanned = CassetteIDs<0, NumCass> + CurrStage = Xlate('RDS', LastCassScanned, 'CURR_STAGE', 'X') + If CurrStage EQ 'UNLOAD' then + Error_Services('Add', '(':LastCassScanned:') Cassette is currently loaded on a tool and is ineligble for a location scan.') + end + + Case ScanType EQ 'TOOL' + // Check if cassette field is populated. If so, then check the cassette's current status to + // determine what the next action will be (i.e. Pre-Epi+Load, Unload, etc.). Ensure we are + // working with an RDS and not a WM_IN or WM_OUT cassette ID. They are not used during the + // "RDS" process. + If (CassetteIDs NE '') then + TestWaferLotData = ScansRow + Abort = False$ + If TestWaferLotData NE '' then + ThisTestRunType = ScansRow + If ThisTestRunType NE '' then + for each TWLot in TestWaferLotData using @VM setting twPOS + If ScansRow NE '' OR ScansRow GT 0 then + TWLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_WAFER_QTY$, True$, 0, False$) + ThisCurrUsageQty = ScansRow + If TWLotCurrQty GT 0 then + If TWLotCurrQty GE ThisCurrUsageQty then + TWLotCurrOperation = Lot_Services('GetLotCurrOperationName', TWLot) + If TWLotCurrOperation NE 'TW_CREATE' AND TWLotCurrOperation NE 'TW_CLOSE' then + TWLotCurrOpen = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_OPEN$, True$, 0, False$) + If Not(TWLotCurrOpen) then + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is closed and cannot be used at this time.') + end + end else + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is currently at ':TWLotCurrOperation:' and cannot be used at this time.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' does not have enough wafers. Please select ' : TWLotCurrQty : ' wafers or less.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' has no wafers and cannot be logged for usage.') + end + end else + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Test Wafer Lot ':TWLot:' must have a quantity associated with it.') + end + Until Abort + Next TWLot + end else + Scan_Services('AddNotAcceptableReason', 'A test run type is required to log test wafer usage.') + end + end + // Ensure only one cassette is scanned + If Not(Abort) then + If (NumCass EQ 1) then + CassetteID = CassetteIDs<0, NumCass> + // Ensure we are working with an RDS and not a WM_OUT/WM_IN cassette + If (Count(CassetteID, '.') EQ 0) then + + RDSNo = CassetteID + RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) + + WONo = RDSRec + CassNo = RDSRec + CurrStatus = obj_WO_Mat('CurrStatus', WONo:'*':CassNo) + + + // RDS Format + IsEpiPro = RDS_Services('IsEpiPro', CassetteID) + If IsEpiPro EQ False$ then + // Non-EpiPro RDS + WONo = Xlate('RDS', CassetteID, 'WO', 'X') + CassNo = Xlate('RDS', CassetteID, 'CASS_NO', 'X') + WOMatKey = WONo:'*':CassNo + WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') + If Index(WOMatLocs,'PTI',1) else Error_Services('Add', 'Cassette ':CassetteID:' failed due to missing PTI.') + end else + // EpiPro RDS + OutCassNos = Xlate('RDS', CassetteID, 'OUT_CASS_NO', 'X') + OutCassNos = SRP_Array('Clean', OutCassNos, 'TrimAndMakeUnique', @VM) + For each OutCassNo in OutCassNos using @VM setting oPos + WONo = Xlate('RDS', CassetteID, 'WO', 'X') + CassNo = OutCassNo + WOMatKey = WONo:'*':CassNo + WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') + If Index(WOMatLocs,'PTI',1) else Error_Services('Add', 'Cassette ':CassetteID:' failed due to missing PTI.') + Next OutCassNo + end + + If Error_Services('NoError') then + If CurrStatus NE 'HOLD' then + If (EmployeeID NE '') then + * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + If CurrStage EQ 'VER' then + VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') + If VerSupplID NE False$ then + SupplVerInstAckReq = True$ + end else + SupplVerInstAckReq = False$ + end + end else + SupplVerInstAckReq = False$ + end + + If CurrStage EQ 'LOAD' OR CurrStage EQ 'VER' then + LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') + If LoadSupplID NE False$ then + SupplLoadInstAckReq = True$ + end else + SupplLoadInstAckReq = False$ + end + end else + SupplLoadInstAckReq = False$ + end + + If CurrStage EQ 'UNLOAD' then + UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') + If UnloadSupplID NE False$ then + SupplUnloadInstAckReq = True$ + end else + SupplUnloadInstAckReq = False$ + end + end else + SupplUnloadInstAckReq = False$ + end + + If CurrStage EQ 'POST' then + PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') + If PostSupplID NE False$ then + SupplPostInstAckReq = True$ + end else + SupplPostInstAckReq = False$ + end + end else + SupplPostInstAckReq = False$ + end + + RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') + PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') + FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') + LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') + QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') + LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') + UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') + PostInstAckReq = Xlate('RDS', RDSno, 'POST_INST_ACK_REQ' , 'X') + WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') + // Parse JSON objects + hRDS = SRP_JSON(hScanJSON, 'Get', 'rds') + If (hRDS NE 0) then + + If (SupplVerInstAckReq NE False$) then + SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplVerInstAck') + If (SupplAck EQ True$) then + Supplement_Services('AcknowledgeSupplement', VerSupplID, ScansRow) + end + end + If (SupplLoadInstAckReq NE False$) then + SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplLoadInstAck') + If (SupplAck EQ True$) then + Supplement_Services('AcknowledgeSupplement', LoadSupplID, ScansRow) + end + end + If (SupplUnloadInstAckReq NE False$) then + SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplUnloadInstAck') + If (SupplAck EQ True$) then + Supplement_Services('AcknowledgeSupplement', UnloadSupplID, ScansRow) + end + end + If (SupplPostInstAckReq NE False$) then + SupplAck = SRP_JSON(hRDS, 'GetValue', 'supplPostInstAck') + If (SupplAck EQ True$) then + Supplement_Services('AcknowledgeSupplement', PostSupplID, ScansRow) + end + end + If RDSLayerInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'rdsLayerInstAck') + If PreInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'preInstAck') + If FwiInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'fwiInstAck') + If LwiInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'lwiInstAck') + If QAInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'qaInstAck') + If LoadInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'loadInstAck') + If UnloadInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'unloadInstAck') + If PostInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'postInstAck') + If WaferCountInstAckReq then RDSRec = SRP_JSON(hRDS, 'GetValue', 'waferCountInstAck') + + Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$) + + * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + If CurrStage EQ 'VER' then + VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') + If VerSupplID NE False$ then + SupplVerInstAckReq = True$ + end else + SupplVerInstAckReq = False$ + end + end else + SupplVerInstAckReq = False$ + end + + If CurrStage EQ 'LOAD' OR CurrStage EQ 'VER' then + LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') + If LoadSupplID NE False$ then + SupplLoadInstAckReq = True$ + end else + SupplLoadInstAckReq = False$ + end + end else + SupplLoadInstAckReq = False$ + end + + If CurrStage EQ 'UNLOAD' then + UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') + If UnloadSupplID NE False$ then + SupplUnloadInstAckReq = True$ + end else + SupplUnloadInstAckReq = False$ + end + end else + SupplUnloadInstAckReq = False$ + end + + If CurrStage EQ 'POST' then + PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') + If PostSupplID NE False$ then + SupplPostInstAckReq = True$ + end else + SupplPostInstAckReq = False$ + end + end else + SupplPostInstAckReq = False$ + end + + RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') + PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') + FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') + LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') + QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') + LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') + UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') + PostInstAckReq = Xlate('RDS', RDSNo, 'POST_INST_ACK_REQ' , 'X') + WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') + + SRP_JSON(hRDS, 'Release') + end + + ToolID = ScansRow + Reactor = ToolID[-1, 'BR'] + Username = ScansRow + WaferCountAck = RDSRec + LLSide = ScansRow + WaferQty = '' + If WaferCountAck EQ True$ then + WaferQty = RDSRec + end else + WaferQty = RDSRec + end + // Check signature fields to determine where the lot is in the RDS process. The service should + // use the signatures in the RDS table, not the WO_MAT table, so that we can support both + // EpiPro and non-EpiPro lots. + WONo = RDSRec + CassNo = RDSRec + CurrStatus = obj_WO_Mat('CurrStatus', WONo:'*':CassNo) + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + + Begin Case + + Case CurrStage _EQC 'VER' + Action = 'LOAD' + + // Check if both the PRE and LOAD stages are ready to sign + // If a Pre Clean is required, then the OpenInsight UI must be used for now until support for cleans operations + // is added to the barcode web application. + LotNo = RDSRec + PreCleanReq = False$ + CleanInspKeyID = Xlate('RDS', RDSNo, 'PRE_CI_NO', 'X') + * If CleanInspKeyID NE '' then PreCleanReq = Xlate('CLEAN_INSP', CleanInspKeyID, 'SPEC_CLEAN_REQ', 'X') + PSN = RDSRec + PrePRSStageKey = PSN:'*PRE' + PreCleanReq = Xlate('PRS_STAGE', PrePRSStageKey, 'CLEAN_SIG_REQ', 'X') + + If ( (PreCleanReq EQ False$) or (PreCleanReq EQ '') ) then + // The first run on a reactor requires that RDS Layer parameters be entered manually. This is when Prove-in + // occurs. + RunOrderNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X') + If RunOrderNo GT 1 then + // Wafer is eligible to have recipe parameters automatically applied from the previous cassette. + // Only copy RDS layer parameters if they do not already exist. This way we do not overwrite + // manually entered parameters. + LSParmsComp = Xlate('RDS', RDSNo, 'LS_PARMS_COMP', 'X') + FirstParmsComp = LSParmsComp<1,1> + If (FirstParmsComp EQ False$) then RDS_Services('CopyRDSLayerParameters', RDSNo) + //Test Wafer logging verification + + + // Supplier lot verification + ScannedSuppLot = ScansRow + RDSSuppLot = RDSRec + If (ScannedSuppLot NE '') then + If (ScannedSuppLot _EQC RDSSuppLot) then + IsTWLoggingReqd = RDS_Services('IsTWLoggingReqd', RDSNo) + If IsTWLoggingReqd NE True$ OR TestWaferLotData NE '' then + WaferCountAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ', 'X') + If WaferCountAckReq EQ False$ then + PreStageReady = '' + LoadStageReady = '' + PreStageReady = QA_Services('PreEpiSignatureReady', RDSNo, Username, WaferQty, Reactor) + If PreStageReady EQ True$ then + LoadStageReady = QA_Services('LoadSignatureReady', RDSNo, Username, WaferQty, LLSide, True$, Reactor) + If (LoadStageReady NE True$) then + // Why is it not ready? + ErrorMsg = Error_Services('GetMessage') + Begin Case + Case IndexC(ErrorMsg, 'supplement', 1) + // Clear the error to return a JSON payload and handle the acknowledgements. + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', ErrorMsg) + Case IndexC(ErrorMsg, 'ROTR', 1) + ROTRBlock = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS$, True$, 0, False$) + ROTRBlockReason = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, True$, 0, False$) + ROTREnabled = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ENABLE_ROTR$, True$, 0, False$) + If ( (ROTRBlock NE 'P') AND (ROTREnabled EQ True$) ) then + // Clear the error to return a JSON payload and allow for OVERRIDE scan. + ScansRow = True$ + ScansRow = ROTRBlockReason + ScansRow = 'ROTR' + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', "ROTR Load Block Enabled") + end else + ScansRow = False$ + ScansRow = '' + ScansRow = '' + end + End Case + end + end else + // Why is it not ready? + ErrorMsg = Error_Services('GetMessage') + Begin Case + Case IndexC(ErrorMsg, 'supplement', 1) + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', ErrorMsg) + End Case + end + end else + Scan_Services('AddNotAcceptableReason', 'The cassette wafer count must be verified against the scheduled wafer count to proceed.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafers are required to be logged with this run.') + end + end else + ScansRow = '' + Error_Services('Add', '(':CassetteID:') Supplier lot mismatch.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Supplier lot scan required in order to complete a tool scan.') + end + + end else + Error_Services('Add', '(':CassetteID:') The first run must be completed using the OpenInsight user interface.') + end + end else + Error_Services('Add', '(':CassetteID:') A pre-clean is required for this RDS. The OpenInsight user interface must be used to proceed.') + end + Case CurrStage _EQC 'LOAD' + Action = 'LOAD' + ScannedSuppLot = ScansRow + RDSSuppLot = RDSRec + If (ScannedSuppLot NE '') then + If (ScannedSuppLot _EQC RDSSuppLot) then + IsTWLoggingReqd = RDS_Services('IsTWLoggingReqd', RDSNo) + If IsTWLoggingReqd NE True$ OR TestWaferLotData NE '' then + // Scheduled tool verification (only supports reactors at the moment) + ClearSelect + SchedTool = Xlate('RDS', RDSNo, 'SCHED_REACTOR', 'X') + ClearSelect + SchedTool = 'R':SchedTool + ScanTool = ScansRow + If SchedTool EQ ScanTool then + // Check if LOAD stage is ready to sign + RDSLayerAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ', 'X') + If RDSLayerAckReq EQ False$ then + If LWIInstAckReq EQ False$ then + If LoadInstAckReq EQ False$ then + LoadStageReady = QA_Services('LoadSignatureReady', RDSNo, Username, WaferQty, LLSide) + If (LoadStageReady NE True$) then + // Why is it not ready? + ErrorMsg = Error_Services('GetMessage') + Begin Case + Case IndexC(ErrorMsg, 'supplement', 1) + // Clear the error to return a JSON payload and handle the acknowledgements. + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', ErrorMsg) + Case IndexC(ErrorMsg, 'ROTR', 1) + ROTRBlock = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS$, True$, 0, False$) + ROTRBlockReason = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ROTR_STATUS_REASON$, True$, 0, False$) + ROTREnabled = Database_Services('ReadDataColumn', 'REACTOR', Reactor, REACTOR_ENABLE_ROTR$, True$, 0, False$) + If ( (ROTRBlock NE 'P') AND (ROTREnabled EQ True$) ) then + // Clear the error to return a JSON payload and allow for OVERRIDE scan. + ScansRow = True$ + ScansRow = ROTRBlockReason + ScansRow = 'ROTR' + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', "ROTR Load Block Enabled") + end else + ScansRow = False$ + ScansRow = '' + ScansRow = '' + end + End Case + end + end else + Scan_Services('AddNotAcceptableReason', 'The LOAD stage engineering instructions must be acknowledged before the load operation can be signed.') + end + end else + Scan_Services('AddNotAcceptableReason', 'The LWI stage engineering instructions must be acknowledged before the load operation can be signed.') + end + end else + ErrorMessage = 'RDS layer parameters must be reviewed for accuracy and acknowledged before the load operation can be signed.' + Scan_Services('AddNotAcceptableReason', ErrorMessage) + end + end else + Error_Services('Add', 'Scanned tool ':ScanTool:' does not match the scheduled tool ':SchedTool:'. (':RDSNo:')') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafers are required to be logged with this run.') + end + end else + + ScansRow = '' + Error_Services('Add', '(':CassetteID:') Supplier lot mismatch.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Supplier lot scan required in order to complete a tool scan.') + end + + Case CurrStage _EQC 'UNLOAD' + Action = 'UNLOAD' + // Check if UNLOAD stage is ready to sign + If ( (LWIInstAckReq EQ False$) or (LWIInstAckReq EQ '') ) then + + If ( (UnloadInstAckReq EQ False$) or (UnloadInstAckReq EQ '') ) then + If ( (PostInstAckReq EQ False$) or (PostInstAckReq EQ '') ) then + UnloadStageReady = QA_Services('UnloadSignatureReady', RDSNo, Username, Reactor) + If Not(UnloadStageReady) then + // Why is it not ready? + ErrorMsg = Error_Services('GetMessage') + Begin Case + Case IndexC(ErrorMsg, 'supplement', 1) + Error_Services('Clear') + Scan_Services('AddNotAcceptableReason', ErrorMsg) + Case Otherwise$ + // Keep error on Error_Services stack and return 400 level error. + End Case + end + end else + ScanMsg = 'The POST stage engineering instructions must be acknowledged before the load operation can be signed.' + Scan_Services('AddNotAcceptableReason', ScanMsg) + end + end else + ScanMsg = 'The UNLOAD stage engineering instructions must be acknowledged before the load operation can be signed.' + Scan_Services('AddNotAcceptableReason', ScanMsg) + end + end else + ScanMsg = 'The LWI stage engineering instructions must be acknowledged before the load operation can be signed.' + Scan_Services('AddNotAcceptableReason', ScanMsg) + end + Case CurrStage _EQC 'COMP' + Action = 'COMP' + Error_Services('Add', '(':CassetteID:") Cassette has already been FQA'd.") + Case Otherwise$ + Action = CurrStage + Error_Services('Set', '(':CassetteID:') The ':CurrStage:' is not currently supported by the barcode application.') + End Case + end else + Scan_Services('AddNotAcceptableReason', 'EmployeeID required to complete a tool scan.') + end + end else + Error_Services('Add', '(':CassetteID:') Process Error: cassette is on Hold and may not be signed off.') + end + end + end else + Error_Services('Add', '(':CassetteID:') WMI/WMO cassette are not currently supported for tool scans. The OpenInsight user interface must be used in order to proceed.') + end + end else + // Currently we are only supporting loading one cassette onto a tool at a time. + Error_Services('Add', '(':CassetteID:') Only one cassette can be loaded onto a tool at a time.') + end + end + + end else + If ScansRow NE '' then + ThisTestRunType = ScansRow + ThisUser = ScansRow + If ThisTestRunType NE '' then + If RowExists('LSL_USERS', ThisUser) then + TestWaferLotData = ScansRow + Abort = False$ + for each TWLot in TestWaferLotData using @VM setting twPOS + If ScansRow NE '' OR ScansRow GT 0 then + TWLotCurrQty = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_WAFER_QTY$, True$, 0, False$) + ThisCurrUsageQty = ScansRow + If TWLotCurrQty GT 0 then + If TWLotCurrQty GE ThisCurrUsageQty then + TWLotCurrOperation = Lot_Services('GetLotCurrOperationName', TWLot) + If TWLotCurrOperation NE 'TW_CREATE' AND TWLotCurrOperation NE 'TW_CLOSE' then + TWLotCurrOpen = Database_Services('ReadDataColumn', 'LOT', TWLot, LOT_OPEN$, True$, 0, False$) + If Not(TWLotCurrOpen) then + + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is closed and cannot be used at this time.') + end + end else + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' is currently at ':TWLotCurrOperation:' and cannot be used at this time.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' does not have enough wafers. Please select ' : TWLotCurrQty : ' wafers or less.') + end + end else + Scan_Services('AddNotAcceptableReason', 'Test wafer Lot ':TWLot:' has no wafers and cannot be logged for usage.') + end + end else + Abort = True$ + Scan_Services('AddNotAcceptableReason', 'Lot ':TWLot:' must have a quantity associated with it.') + end + Until Abort + Next TWLot + end else + Scan_Services('AddNotAcceptableReason', 'A User ID Scan is required to log test wafer usage.') + end + end else + Scan_Services('AddNotAcceptableReason', 'A test run type is required to log test wafer usage.') + end + end else + Scan_Services('AddNotAcceptableReason', 'A cassette must be scanned in order to complete a tool scan.') + end + end + + Case Otherwise$ + Scan_Services('AddNotAcceptableReason', 'A location ID or tool ID must be scanned to proceed.') + End Case + end + // If the the scan data is valid, update the scan log before returning to the calling process. + If Error_Services('NoError') then + If Scan_Services('NoNotAcceptableReason') then + ScansRow = True$ + ScansRow = '' + end else + ScansRow = False$ + ScansRow = Scan_Services('GetNotAcceptableReason') + end + end else + ScansRow = False$ + ScansRow = Error_Services('GetMessage') + end + If ScanData NE '' then + ScansRow = Date() + ScansRow = Time() + ScansRow = ScanData + end + ScansRow = Action + // Save error message if present as Database_Services will clear any errors. + ErrorMessage = '' + If Error_Services('HasError') then + ErrorMessage = Error_Services('GetMessage') + end + Database_Services('WriteDataRow', 'SCANS', ScanID, ScansRow, True$, False$, True$) + // Restore pre-existing error message if present. + If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) + end + end else + Error_Services('Add', 'Unable to parse the JSON scan data in the ':Service:' service.') + end + SRP_JSON(hScanJSON, 'Release') + end else + Error_Services('Add', 'ScanID or ScanJSON argument was missing in the ' : Service : ' service.') + end + end service @@ -1214,339 +1223,339 @@ end service // //---------------------------------------------------------------------------------------------------------------------- Service AcceptScan(ScanID, ScanJSON) - If ( (ScanID NE '') and (ScanJSON NE '') ) then - hBody = '' - ParseResponse = SRP_JSON(hBody, 'PARSE', ScanJSON) - If ParseResponse EQ '' then - AcceptedStatus = SRP_JSON(hBody, 'GetValue', 'accepted.status') - If AcceptedStatus NE '' then - ScansRow = Scan_Services('GetScansRow', ScanID, False$) - ScansRow = AcceptedStatus - Result = '' - If AcceptedStatus EQ True$ then - // Scan is acceptable and has been accepted on the web app. Sign stage now if tool scan. - AcceptedDate = Date() - AcceptedTime = Time() - LogDate = OCONV( AcceptedDate, 'D2/' ) - LogTime = OCONV( AcceptedTime, 'MTS' ) - LogDTM = LogDate:' ':LogTime - ScansRow = AcceptedDate - ScansRow = AcceptedTime - CassetteIDs = ScansRow - ScanType = ScansRow - Begin Case - Case ScanType _EQC 'RESET' - Scan_Services('ResetDevData', CassetteIDs) - If Error_Services('NoError') then Result = 'Reset scan complete' - - Case ScanType _EQC 'TENCOR_LOAD' - Tencor= ScansRow - RDSNo= ScansRow - SendStatus = Keyboard_Sim_Services('SendTencor', Tencor, RDSNo) - If Error_Services('NoError') AND SendStatus EQ 'Success' then - Result = 'Tencor Data Sent Successfully' - end else - Error_Services('Add', SendStatus) - end - - Case ScanType _EQC 'LOCATION' - - //DPC - 2/10/20 - need to check for existence of 1K*PTI scan before location scan is allowed - LocID = ScansRow - ErrorCassIDs = '' - WONos = '' - CassNos = '' - For each CassetteID in CassetteIDs using @VM setting vPos - Begin Case - Case Count(CassetteID, '.') EQ 0 - // RDS Format - IsEpiPro = RDS_Services('IsEpiPro', CassetteID) - If IsEpiPro EQ False$ then - // Non-EpiPro RDS - WONo = Xlate('RDS', CassetteID, 'WO', 'X') - CassNo = Xlate('RDS', CassetteID, 'CASS_NO', 'X') - WOMatKey = WONo:'*':CassNo - WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') - If Index(WOMatLocs,'PTI',1) then - WONos<0, -1> = WONo - CassNos<0, -1> = CassNo - end else - // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. - // Add it to the invalid cassette list (error list). - ErrorCassIDs<0, -1> = CassetteID - end - end else - // EpiPro RDS - OutCassNos = Xlate('RDS', CassetteID, 'OUT_CASS_NO', 'X') - OutCassNos = SRP_Array('Clean', OutCassNos, 'TrimAndMakeUnique', @VM) - For each OutCassNo in OutCassNos using @VM setting oPos - WONo = Xlate('RDS', CassetteID, 'WO', 'X') - CassNo = OutCassNo - WOMatKey = WONo:'*':CassNo - WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') - If Index(WOMatLocs,'PTI',1) then - WONos<0, -1> = WONo - CassNos<0, -1> = CassNo - end else - // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. - // Add it to the invalid cassette list (error list). - ErrorCassIDs<0, -1> = CassetteID - end - Next OutCassNo - end - Case DCount(CassetteID, '.') EQ 3 - // WM_IN / WM_OUT Format - WONo = Field(CassetteID, '.', 1, 1) - CassNo = Field(CassetteID, '.', 3, 1) - WOMatKey = WONo:'*':CassNo - WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') - If Index(WOMatLocs,'PTI',1) then - WONos<0, -1> = WONo - CassNos<0, -1> = CassNo - end else - // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. - // Add it to the invalid cassette list (error list). - ErrorCassIDs<0, -1> = CassetteID - end - Case Otherwise$ - // Unsupported format - Null - End Case - - Next CassetteID - - For each CassetteID in ErrorCassIDs using @VM - // Remove erroneous cassettes from the valid cassette list - Locate CassetteID in CassetteIDs using @VM setting vPos then - CassetteIDs = Delete(CassetteIDS, 0, vPos, 0) - end - Next CassetteID - - If ( (WONos NE '') and (CassNos NE '') ) then - // Move the cassettes (i.e. log their movement in the material log) - LogFile = 'WO_MAT' - LogDTM = LogDate:' ':LogTime - Action = 'PLACE' - WhCd = Field(LocID, '.', 1, 1) - LocCd = Field(LocID, '.', 2, 1) - UserID = ScansRow - Tags = '' - ToolID = '' - ScanEntry = 1 - - WOMLParms = LogFile:@RM - WOMLParms := LogDTM:@RM - WOMLParms := Action:@RM - WOMLParms := WhCd:@RM - WOMLParms := LocCd:@RM - WOMLParms := WONos:@RM - WOMLParms := CassNos:@RM - WOMLParms := UserID:@RM - WOMLParms := Tags:@RM - WOMLParms := ToolID:@RM - WOMLParms := ScanEntry - - obj_WO_Mat_Log('Create',WOMLParms) - errCode = '' - end - - IF Get_Status(errCode) THEN - ErrorMsg = 'Error calling obj_WO_Mat_Log("Create"). Error code: ':errCode - Error_Services('Add', ErrorMsg) - END else - NumCass = DCount(CassetteIDs, @VM) - If NumCass EQ 1 then - CassetteID = CassetteIDs<0, 1> - Result = '(':CassetteID:') Location scan complete. ' - end else - Result = '(Multi) Location scan complete. ' - end - If ErrorCassIDs NE '' then - Convert @VM to ',' in ErrorCassIDs - Result := 'Cassette(s) ':ErrorCassIDs:' failed due to missing PTI.' - end - end - - - Case ScanType _EQC 'TOOL' - // Check if cassette field is populated. If so, then check the cassette's current status to - // determine what the next action will be (i.e. Pre-Epi+Load, Unload, etc.) - CassetteID = CassetteIDs<0, 1> - TestWaferLots = ScansRow - Begin Case - Case CassetteID NE '' - //Tool Cassette scan, check for test wafers after everything is signed. - RDSNo = CassetteID - RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) - ToolID = ScansRow - Reactor = ToolID[-1, 'BR'] - Username = ScansRow - LLSide = ScansRow - WaferQty = RDSRec - // Check signature fields to determine where the lot is in the RDS process. The service should - // use the signatures in the RDS table, not the WO_MAT table, so that we can support both - // EpiPro and non-EpiPro lots. - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - CurrDTM = Datetime() - LogData = '' - LogData<1> = OConv(CurrDTM, 'DT') - LogData<2> = RDSNo - LogData<3> = Username - LogData<4> = CurrStage - LogData<5> = ScanID - Begin Case - Case CurrStage _EQC 'VER' - Action = 'LOAD' - // Check if both the PRE and LOAD stages are ready to sign - PreStageSigned = False$ - LoadStageSigned = False$ - //Log test wafer usage here - If TestWaferLots NE '' then - Continue = False$ - ToolID = ScansRow - Reactor = ToolID[-1, 'BR'] - Username = ScansRow - TestWaferLotQtys = ScansRow - PSNo = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_PROD_SPEC_ID$, True$, 0, False$) - NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, PSNo, RDSNo,Username , TestWaferLots, TestWaferLotQtys) - If Error_Services('NoError') then - Continue = True$ - end else - ErrorMessage = Error_Services('GetMessage') - Error_Services('Set', ErrorMessage) - Continue = False$ - end - If Continue then - PreStageSigned = QA_Services('SignPreEpiStage', RDSNo, Username, WaferQty, Reactor, 1) - If PreStageSigned EQ True$ then - LoadStageSigned = QA_Services('SignLoadStage', RDSNo, USername, WaferQty, LLSide, 1) - end - If ( (PreStageSigned EQ True$) and (LoadStageSigned EQ True$) ) then - Result = '(':CassetteID:') Load stage signed.' - end - LogData<6> = Action - LogData<7> = Result - Logging_Services('AppendLog', objLog, LogData, @RM, @FM) - end - - end else - PreStageSigned = QA_Services('SignPreEpiStage', RDSNo, Username, WaferQty, Reactor, 1) - If PreStageSigned EQ True$ then - LoadStageSigned = QA_Services('SignLoadStage', RDSNo, USername, WaferQty, LLSide, 1) - end - If ( (PreStageSigned EQ True$) and (LoadStageSigned EQ True$) ) then - Result = '(':CassetteID:') Load stage signed.' - end - LogData<6> = Action - LogData<7> = Result - Logging_Services('AppendLog', objLog, LogData, @RM, @FM) - end - - Case CurrStage _EQC 'LOAD' - Action = 'LOAD' - If TestWaferLots NE '' then - Continue = False$ - ToolID = ScansRow - Reactor = ToolID[-1, 'BR'] - Username = ScansRow - TestWaferLotQtys = ScansRow - PSNo = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_PROD_SPEC_ID$, True$, 0, False$) - NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, PSNo, RDSNo,Username , TestWaferLots, TestWaferLotQtys) - If Error_Services('NoError') then - Continue = True$ - end else - ErrorMessage = Error_Services('GetMessage') - Error_Services('Set', ErrorMessage) - Continue = False$ - end - If Continue then - LoadStageSigned = QA_Services('SignLoadStage', RDSNo, Username, WaferQty, LLSide, 1) - If LoadStageSigned EQ True$ then - Result = '(':CassetteID:') Load stage signed.' - end - LogData<6> = Action - LogData<7> = Result - Logging_Services('AppendLog', objLog, LogData, @RM, @FM) - end - end else - LoadStageSigned = QA_Services('SignLoadStage', RDSNo, Username, WaferQty, LLSide, 1) - If LoadStageSigned EQ True$ then - Result = '(':CassetteID:') Load stage signed.' - end - LogData<6> = Action - LogData<7> = Result - Logging_Services('AppendLog', objLog, LogData, @RM, @FM) - end - - // Check if LOAD stage is ready to sign - - Case CurrStage _EQC 'UNLOAD' - Action = 'UNLOAD' - // Check if UNLOAD stage is ready to sign - UnloadStageSigned = QA_Services('SignUnloadStage', RDSNo, Username, 1) - If UnloadStageSigned EQ True$ then - Result = '(':CassetteID:') Unload stage signed.' - end - LogData<6> = Action - LogData<7> = Result - Logging_Services('AppendLog', objLog, LogData, @RM, @FM) - Case CurrStage _EQC 'COMP' - Action = 'COMP' - Error_Services('Set', '(':CassetteID:") Cassette has already been FQA'd.") - Case Otherwise$ - Action = CurrStage - Error_Services('Set', '(':CassetteID:') The ':CurrStage:' is not currently supported by the barcode application.') - End Case - Case CassetteID EQ '' AND TestWaferLots NE '' - //Tool scan with ONLY test wafers being logged. - ToolID = ScansRow - Reactor = ToolID[-1, 'BR'] - Username = ScansRow - TestWaferLotQtys = ScansRow - NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, '', '',Username , TestWaferLots, TestWaferLotQtys) - If Error_Services('NoError') then - If NewTestRunId NE '' then - Result = 'Test run logged successfully' - end else - ErrorMessage = 'Error while logging creating test run.' - Error_Services('Set', ErrorMessage) - end - end else - ErrorMessage = Error_Services('GetMessage') - Error_Services('Set', ErrorMessage) - end - Case Otherwise$ - //null - End Case - End Case - end - - If Error_Services('NoError') then - ScansRow = 'This scan has already been accepted.' - end else - ScansRow = Error_Services('GetMessage') - end - ScansRow = False$ - If Assigned(Result) then ScansRow = Result - // Save error message if present as Database_Services will clear any errors. - ErrorMessage = '' - If Error_Services('HasError') then - ErrorMessage = Error_Services('GetMessage') - end - Scan_Services('SetScansRow', ScanID, ScansRow) - // Restore pre-existing error message if present. - If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) - end else - Error_Services('Add', 'The accepted.status field is missing from the JSON object in the ':Service:' service.') - end - SRP_JSON(hBody, 'Release') - end else - Error_Services('Add', 'Unable to parse the JSON scan resource in the ':Service:' service.') - end - end else - Error_Services('Add', 'ScanID or ScanJSON argument was missing in the ' : Service : ' service.') - end - + If ( (ScanID NE '') and (ScanJSON NE '') ) then + hBody = '' + ParseResponse = SRP_JSON(hBody, 'PARSE', ScanJSON) + If ParseResponse EQ '' then + AcceptedStatus = SRP_JSON(hBody, 'GetValue', 'accepted.status') + If AcceptedStatus NE '' then + ScansRow = Scan_Services('GetScansRow', ScanID, False$) + ScansRow = AcceptedStatus + Result = '' + If AcceptedStatus EQ True$ then + // Scan is acceptable and has been accepted on the web app. Sign stage now if tool scan. + AcceptedDate = Date() + AcceptedTime = Time() + LogDate = OCONV( AcceptedDate, 'D2/' ) + LogTime = OCONV( AcceptedTime, 'MTS' ) + LogDTM = LogDate:' ':LogTime + ScansRow = AcceptedDate + ScansRow = AcceptedTime + CassetteIDs = ScansRow + ScanType = ScansRow + Begin Case + Case ScanType _EQC 'RESET' + Scan_Services('ResetDevData', CassetteIDs) + If Error_Services('NoError') then Result = 'Reset scan complete' + + Case ScanType _EQC 'TENCOR_LOAD' + Tencor= ScansRow + RDSNo= ScansRow + SendStatus = Keyboard_Sim_Services('SendTencor', Tencor, RDSNo) + If Error_Services('NoError') AND SendStatus EQ 'Success' then + Result = 'Tencor Data Sent Successfully' + end else + Error_Services('Add', SendStatus) + end + + Case ScanType _EQC 'LOCATION' + + //DPC - 2/10/20 - need to check for existence of 1K*PTI scan before location scan is allowed + LocID = ScansRow + ErrorCassIDs = '' + WONos = '' + CassNos = '' + For each CassetteID in CassetteIDs using @VM setting vPos + Begin Case + Case Count(CassetteID, '.') EQ 0 + // RDS Format + IsEpiPro = RDS_Services('IsEpiPro', CassetteID) + If IsEpiPro EQ False$ then + // Non-EpiPro RDS + WONo = Xlate('RDS', CassetteID, 'WO', 'X') + CassNo = Xlate('RDS', CassetteID, 'CASS_NO', 'X') + WOMatKey = WONo:'*':CassNo + WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') + If Index(WOMatLocs,'PTI',1) then + WONos<0, -1> = WONo + CassNos<0, -1> = CassNo + end else + // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. + // Add it to the invalid cassette list (error list). + ErrorCassIDs<0, -1> = CassetteID + end + end else + // EpiPro RDS + OutCassNos = Xlate('RDS', CassetteID, 'OUT_CASS_NO', 'X') + OutCassNos = SRP_Array('Clean', OutCassNos, 'TrimAndMakeUnique', @VM) + For each OutCassNo in OutCassNos using @VM setting oPos + WONo = Xlate('RDS', CassetteID, 'WO', 'X') + CassNo = OutCassNo + WOMatKey = WONo:'*':CassNo + WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') + If Index(WOMatLocs,'PTI',1) then + WONos<0, -1> = WONo + CassNos<0, -1> = CassNo + end else + // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. + // Add it to the invalid cassette list (error list). + ErrorCassIDs<0, -1> = CassetteID + end + Next OutCassNo + end + Case DCount(CassetteID, '.') EQ 3 + // WM_IN / WM_OUT Format + WONo = Field(CassetteID, '.', 1, 1) + CassNo = Field(CassetteID, '.', 3, 1) + WOMatKey = WONo:'*':CassNo + WOMatLocs = Xlate('WO_MAT', WOMatKey, WO_MAT_INV_LOCATION$, 'X') + If Index(WOMatLocs,'PTI',1) then + WONos<0, -1> = WONo + CassNos<0, -1> = CassNo + end else + // Cassette has not yet been through passthrough (PTI), so it is not eligible for location scanning. + // Add it to the invalid cassette list (error list). + ErrorCassIDs<0, -1> = CassetteID + end + Case Otherwise$ + // Unsupported format + Null + End Case + + Next CassetteID + + For each CassetteID in ErrorCassIDs using @VM + // Remove erroneous cassettes from the valid cassette list + Locate CassetteID in CassetteIDs using @VM setting vPos then + CassetteIDs = Delete(CassetteIDS, 0, vPos, 0) + end + Next CassetteID + + If ( (WONos NE '') and (CassNos NE '') ) then + // Move the cassettes (i.e. log their movement in the material log) + LogFile = 'WO_MAT' + LogDTM = LogDate:' ':LogTime + Action = 'PLACE' + WhCd = Field(LocID, '.', 1, 1) + LocCd = Field(LocID, '.', 2, 1) + UserID = ScansRow + Tags = '' + ToolID = '' + ScanEntry = 1 + + WOMLParms = LogFile:@RM + WOMLParms := LogDTM:@RM + WOMLParms := Action:@RM + WOMLParms := WhCd:@RM + WOMLParms := LocCd:@RM + WOMLParms := WONos:@RM + WOMLParms := CassNos:@RM + WOMLParms := UserID:@RM + WOMLParms := Tags:@RM + WOMLParms := ToolID:@RM + WOMLParms := ScanEntry + + obj_WO_Mat_Log('Create',WOMLParms) + errCode = '' + end + + IF Get_Status(errCode) THEN + ErrorMsg = 'Error calling obj_WO_Mat_Log("Create"). Error code: ':errCode + Error_Services('Add', ErrorMsg) + END else + NumCass = DCount(CassetteIDs, @VM) + If NumCass EQ 1 then + CassetteID = CassetteIDs<0, 1> + Result = '(':CassetteID:') Location scan complete. ' + end else + Result = '(Multi) Location scan complete. ' + end + If ErrorCassIDs NE '' then + Convert @VM to ',' in ErrorCassIDs + Result := 'Cassette(s) ':ErrorCassIDs:' failed due to missing PTI.' + end + end + + + Case ScanType _EQC 'TOOL' + // Check if cassette field is populated. If so, then check the cassette's current status to + // determine what the next action will be (i.e. Pre-Epi+Load, Unload, etc.) + CassetteID = CassetteIDs<0, 1> + TestWaferLots = ScansRow + Begin Case + Case CassetteID NE '' + //Tool Cassette scan, check for test wafers after everything is signed. + RDSNo = CassetteID + RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) + ToolID = ScansRow + Reactor = ToolID[-1, 'BR'] + Username = ScansRow + LLSide = ScansRow + WaferQty = RDSRec + // Check signature fields to determine where the lot is in the RDS process. The service should + // use the signatures in the RDS table, not the WO_MAT table, so that we can support both + // EpiPro and non-EpiPro lots. + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + CurrDTM = Datetime() + LogData = '' + LogData<1> = OConv(CurrDTM, 'DT') + LogData<2> = RDSNo + LogData<3> = Username + LogData<4> = CurrStage + LogData<5> = ScanID + Begin Case + Case CurrStage _EQC 'VER' + Action = 'LOAD' + // Check if both the PRE and LOAD stages are ready to sign + PreStageSigned = False$ + LoadStageSigned = False$ + //Log test wafer usage here + If TestWaferLots NE '' then + Continue = False$ + ToolID = ScansRow + Reactor = ToolID[-1, 'BR'] + Username = ScansRow + TestWaferLotQtys = ScansRow + PSNo = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_PROD_SPEC_ID$, True$, 0, False$) + NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, PSNo, RDSNo,Username , TestWaferLots, TestWaferLotQtys) + If Error_Services('NoError') then + Continue = True$ + end else + ErrorMessage = Error_Services('GetMessage') + Error_Services('Set', ErrorMessage) + Continue = False$ + end + If Continue then + PreStageSigned = QA_Services('SignPreEpiStage', RDSNo, Username, WaferQty, Reactor, 1) + If PreStageSigned EQ True$ then + LoadStageSigned = QA_Services('SignLoadStage', RDSNo, USername, WaferQty, LLSide, 1) + end + If ( (PreStageSigned EQ True$) and (LoadStageSigned EQ True$) ) then + Result = '(':CassetteID:') Load stage signed.' + end + LogData<6> = Action + LogData<7> = Result + Logging_Services('AppendLog', objLog, LogData, @RM, @FM) + end + + end else + PreStageSigned = QA_Services('SignPreEpiStage', RDSNo, Username, WaferQty, Reactor, 1) + If PreStageSigned EQ True$ then + LoadStageSigned = QA_Services('SignLoadStage', RDSNo, USername, WaferQty, LLSide, 1) + end + If ( (PreStageSigned EQ True$) and (LoadStageSigned EQ True$) ) then + Result = '(':CassetteID:') Load stage signed.' + end + LogData<6> = Action + LogData<7> = Result + Logging_Services('AppendLog', objLog, LogData, @RM, @FM) + end + + Case CurrStage _EQC 'LOAD' + Action = 'LOAD' + If TestWaferLots NE '' then + Continue = False$ + ToolID = ScansRow + Reactor = ToolID[-1, 'BR'] + Username = ScansRow + TestWaferLotQtys = ScansRow + PSNo = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_PROD_SPEC_ID$, True$, 0, False$) + NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, PSNo, RDSNo,Username , TestWaferLots, TestWaferLotQtys) + If Error_Services('NoError') then + Continue = True$ + end else + ErrorMessage = Error_Services('GetMessage') + Error_Services('Set', ErrorMessage) + Continue = False$ + end + If Continue then + LoadStageSigned = QA_Services('SignLoadStage', RDSNo, Username, WaferQty, LLSide, 1) + If LoadStageSigned EQ True$ then + Result = '(':CassetteID:') Load stage signed.' + end + LogData<6> = Action + LogData<7> = Result + Logging_Services('AppendLog', objLog, LogData, @RM, @FM) + end + end else + LoadStageSigned = QA_Services('SignLoadStage', RDSNo, Username, WaferQty, LLSide, 1) + If LoadStageSigned EQ True$ then + Result = '(':CassetteID:') Load stage signed.' + end + LogData<6> = Action + LogData<7> = Result + Logging_Services('AppendLog', objLog, LogData, @RM, @FM) + end + + // Check if LOAD stage is ready to sign + + Case CurrStage _EQC 'UNLOAD' + Action = 'UNLOAD' + // Check if UNLOAD stage is ready to sign + UnloadStageSigned = QA_Services('SignUnloadStage', RDSNo, Username, 1) + If UnloadStageSigned EQ True$ then + Result = '(':CassetteID:') Unload stage signed.' + end + LogData<6> = Action + LogData<7> = Result + Logging_Services('AppendLog', objLog, LogData, @RM, @FM) + Case CurrStage _EQC 'COMP' + Action = 'COMP' + Error_Services('Set', '(':CassetteID:") Cassette has already been FQA'd.") + Case Otherwise$ + Action = CurrStage + Error_Services('Set', '(':CassetteID:') The ':CurrStage:' is not currently supported by the barcode application.') + End Case + Case CassetteID EQ '' AND TestWaferLots NE '' + //Tool scan with ONLY test wafers being logged. + ToolID = ScansRow + Reactor = ToolID[-1, 'BR'] + Username = ScansRow + TestWaferLotQtys = ScansRow + NewTestRunId = Test_Run_Services('CreateTestRunRecord', 3, 'R', Reactor, '', '',Username , TestWaferLots, TestWaferLotQtys) + If Error_Services('NoError') then + If NewTestRunId NE '' then + Result = 'Test run logged successfully' + end else + ErrorMessage = 'Error while logging creating test run.' + Error_Services('Set', ErrorMessage) + end + end else + ErrorMessage = Error_Services('GetMessage') + Error_Services('Set', ErrorMessage) + end + Case Otherwise$ + //null + End Case + End Case + end + + If Error_Services('NoError') then + ScansRow = 'This scan has already been accepted.' + end else + ScansRow = Error_Services('GetMessage') + end + ScansRow = False$ + If Assigned(Result) then ScansRow = Result + // Save error message if present as Database_Services will clear any errors. + ErrorMessage = '' + If Error_Services('HasError') then + ErrorMessage = Error_Services('GetMessage') + end + Scan_Services('SetScansRow', ScanID, ScansRow) + // Restore pre-existing error message if present. + If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) + end else + Error_Services('Add', 'The accepted.status field is missing from the JSON object in the ':Service:' service.') + end + SRP_JSON(hBody, 'Release') + end else + Error_Services('Add', 'Unable to parse the JSON scan resource in the ':Service:' service.') + end + end else + Error_Services('Add', 'ScanID or ScanJSON argument was missing in the ' : Service : ' service.') + end + end service //---------------------------------------------------------------------------------------------------------------------- @@ -1557,227 +1566,227 @@ end service // HAL+JSON properties will be added to the JSON object. //---------------------------------------------------------------------------------------------------------------------- Service ConvertMVScanToJSON(ScanID, mvScan, itemURL) - - jsonScan = '' - - If ScanID NE '' then - - If mvScan EQ '' then mvScan = Database_Services('ReadDataRow', 'SCANS', ScanID) - If Error_Services('NoError') then - @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') - @ID = ScanID - @RECORD = mvScan - objJSONScan = '' - If SRP_JSON(objJSONScan, 'New', 'Object') then - // Scan object. - If SRP_JSON(objScan, 'New', 'Object') then - SRP_JSON(objScan, 'SetValue', 'ID', @ID, 'String') - SRP_JSON(objScan, 'SetValue', 'type', {SCAN_TYPE}, 'String') - SRP_JSON(objScan, 'SetValue', 'action', {ACTION}, 'String') - SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') - - SRP_JSON(objScan, 'SetValue', 'acceptable', {ACCEPTABLE}, 'Boolean') - SRP_JSON(objScan, 'SetValue', 'notAcceptableReason', {NOT_ACCEPTABLE_REASON}, 'String') - SRP_JSON(objScan, 'SetValue', 'result', {RESULT}, 'String') - SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') - SRP_JSON(objScan, 'SetValue', 'testRunTypeName', XLate('TEST_RUN_TYPE', {TEST_RUN_TYPE_ID}, TEST_RUN_TYPE_RUN_TYPE$, 'X'), 'String') - If SRP_JSON(arrayScanLog, 'New', 'Array') then - If {SCANNED_DATES} NE '' then - ScannedDates = {SCANNED_DATES} - For Each ScannedDate in scannedDates using @VM setting vPos - objScanSession = '' - If SRP_JSON(objScanSession, 'New', 'Object') then - SRP_JSON(objScanSession, 'SetValue', 'date', Oconv({SCANNED_DATES}<0, vPos>, 'D4/'), 'String') - SRP_JSON(objScanSession, 'SetValue', 'time', Oconv({SCANNED_TIMES}<0, vPos>, 'MTH'), 'String') - SRP_JSON(objScanSession, 'SetValue', 'data', {SCANNED_DATA}<0, vPos>, 'String') - SRP_JSON(arrayScanLog, 'Add', objScanSession) - SRP_JSON(objScanSession, 'Release') - end - Next ScannedDate - end - SRP_JSON(objScan, 'Set', 'scanLog', arrayScanLog) - SRP_JSON(arrayScanLog, 'Release') - end - - SRP_JSON(objJSONScan, 'Set', 'scan', objScan) - SRP_JSON(objScan, 'Release') - end - // Supplier Lot object. - objSupplierLot = '' - If SRP_JSON(objSupplierLot, 'New', 'Object') then - SRP_JSON(objSupplierLot, 'SetValue', 'ID', {SUPPLIER_LOT}, 'String') - SRP_JSON(objJSONScan, 'Set', 'supplierLot', objSupplierLot) - SRP_JSON(objSupplierLot, 'Release') - end - // TestWafer Lot Object. - If SRP_JSON(hTWLotArray, 'New', 'Array') then - Abort = False$ - TestWaferLots = {TW_LOT_ID} - for each TestWaferLotId in TestWaferLots using @VM setting twPos - thisTWLotJson = '' - If SRP_JSON(thisTWLotJson, 'New', 'Object') then - SRP_JSON(thisTWLotJson, 'SetValue', 'testWaferLotId', {TW_LOT_ID}<1, twPos>) - SRP_JSON(thisTWLotJson, 'SetValue', 'quantity', {TW_LOT_QTY}<1, twPos>, 'Integer') - SRP_JSON(hTWLotArray, 'Add', thisTWLotJson) - SRP_JSON(thisTWLotJson, 'Release') - end - Next TestWaferLotId - SRP_JSON(objJSONScan, 'Set', 'testWaferLots', hTWLotArray) - SRP_JSON(hTWLotArray, 'Release') - end - SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') - // TestRun Type Option Array - TestRunTypeList = Test_Run_Services('GetAllTestRunTypes') - If SRP_JSON(hTestRunTypeArray, 'New', 'Array') then - For each TestRunTypeId in TestRunTypeList<1> using @VM setting fPos - hTestRunTypeObj = '' - If SRP_JSON(hTestRunTypeObj, 'New', 'Object') then - SRP_JSON(hTestRunTypeObj, 'SetValue', 'testRunTypeId', TestRunTypeId, 'Number') - SRP_JSON(hTestRunTypeObj, 'SetValue', 'testRunTypeName', TestRunTypeList<2, fPos>, 'String') - SRP_JSON(hTestRunTypeArray, 'Add', hTestRunTypeObj) - SRP_JSON(hTestRunTypeObj, 'Release') - end else - Abort = True$ - end - Until Abort - Next TestRunTypeId - If Abort EQ False$ then - SRP_JSON(objJSONScan, 'Set', 'testRunTypeOptions', hTestRunTypeArray) - end - SRP_JSON(hTestRunTypeArray, 'Release') - end - // Created object. - objCreated = '' - If SRP_JSON(objCreated, 'New', 'Object') then - SRP_JSON(objCreated, 'SetValue', 'date', Oconv({CREATED_DATE}, 'D4/'), 'String') - SRP_JSON(objCreated, 'SetValue', 'time', Oconv({CREATED_TIME}, 'MTH'), 'String') - SRP_JSON(objJSONScan, 'Set', 'created', objCreated) - SRP_JSON(objCreated, 'Release') - end - // Employee object - objEmployee = '' - If SRP_JSON(objEmployee, 'New', 'Object') then - - SRP_JSON(objEmployee, 'SetValue', 'ID', {EMPLOYEE_ID}, 'String') - SRP_JSON(objEmployee, 'SetValue', 'name', {EMPLOYEE_NAME}, 'String') - SRP_JSON(objEmployee, 'SetValue', 'authorized', {EMPLOYEE_AUTHORIZED}, 'Boolean') - SRP_JSON(objEmployee, 'SetValue', 'notAuthorizedReason', {EMPLOYEE_NOT_AUTHORIZED_REASON}, 'String') - SRP_JSON(objEmployee, 'SetValue', 'authenticated' , @Record , 'Boolean');//JRO Change - SRP_JSON(objJSONScan, 'Set', 'employee', objEmployee) - SRP_JSON(objEmployee, 'Release') - - end - // Cassettes object. - arrayCassetteIDs = '' - If SRP_JSON(arrayCassetteIDs, 'New', 'Array') then - If {CASSETTE_IDS} NE '' then - CassetteIDs = {CASSETTE_IDS} - For Each CassetteID in CassetteIDs using @VM - SRP_JSON(arrayCassetteIDs, 'AddValue', CassetteID, 'String') - Next CassetteID - end - SRP_JSON(objJSONScan, 'Set', 'cassetteIDs', arrayCassetteIDs) - SRP_JSON(arrayCassetteIDs, 'Release') - end - // Location object. - objLocation = '' - If SRP_JSON(objLocation, 'New', 'Object') then - SRP_JSON(objLocation, 'SetValue', 'ID', {LOCATION_ID}, 'String') - SRP_JSON(objLocation, 'SetValue', 'name', {LOCATION_NAME}, 'String') - SRP_JSON(objJSONScan, 'Set', 'location', objLocation) - SRP_JSON(objLocation, 'Release') - end - // Tool object. - objTool = '' - If SRP_JSON(objTool, 'New', 'Object') then - SRP_JSON(objTool, 'SetValue', 'ID', {TOOL_ID}, 'String') - SRP_JSON(objTool, 'SetValue', 'name', {TOOL_NAME}, 'String') - SRP_JSON(objTool, 'SetValue', 'loadLock', {LOAD_LOCK}, 'String') - SRP_JSON(objJSONScan, 'Set', 'tool', objTool) - SRP_JSON(objTool, 'Release') - end - // Accepted object. - objAccepted = '' - If SRP_JSON(objAccepted, 'New', 'Object') then - SRP_JSON(objAccepted, 'SetValue', 'status', {ACCEPTED}, 'Boolean') - SRP_JSON(objAccepted, 'SetValue', 'date', Oconv({ACCEPTED_DATE}, 'D4/'), 'String') - SRP_JSON(objAccepted, 'SetValue', 'time', Oconv({ACCEPTED_TIME}, 'MTH'), 'String') - SRP_JSON(objEmployee, 'SetValue', 'notAcceptedReason', {NOT_ACCEPTABLE_REASON}, 'String') - SRP_JSON(objJSONScan, 'Set', 'accepted', objAccepted) - SRP_JSON(objAccepted, 'Release') - end - // Wafer Count object. - objWaferCount = '' - If SRP_JSON(objWaferCount, 'New', 'Object') then - SRP_JSON(objWaferCount, 'SetValue', 'scheduler', {SCHEDULER_WAFER_COUNT}, 'Number') - SRP_JSON(objWaferCount, 'SetValue', 'confirmed', {WAFER_COUNT_CONFIRMED}, 'Boolean') - SRP_JSON(objJSONScan, 'Set', 'waferCount', objWaferCount) - SRP_JSON(objWaferCount, 'Release') - end - // Transfer object. - objTransfer = '' - If SRP_JSON(objTransfer, 'New', 'Object') then - // Transfer Tool sub-object. - objTool = '' - If SRP_JSON(objTool, 'New', 'Object') then - SRP_JSON(objTool, 'SetValue', 'ID', {TRANSFER_TOOL_ID}, 'String') - SRP_JSON(objTool, 'SetValue', 'name', {TRANSFER_TOOL_NAME}, 'String') - SRP_JSON(objTransfer, 'Set', 'tool', objTool) - SRP_JSON(objTool, 'Release') - end - SRP_JSON(objTransfer, 'SetValue', 'boatID', {BOAT_ID}, 'String') - SRP_JSON(objTransfer, 'SetValue', 'plNumber', {PL_NUMBER}, 'String') - SRP_JSON(objTransfer, 'SetValue', 'unloadplConfirmed', {UNLOAD_PL_CONFIRMED}, 'Boolean') - SRP_JSON(objJSONScan, 'Set', 'transfer', objTransfer) - SRP_JSON(objTransfer, 'Release') - end - SRP_JSON(objJSONScan, 'SetValue', 'lastModified', {LAST_MODIFIED}, 'String') - - If {SCAN_TYPE} EQ 'TOOL' then - CassIDs = {CASSETTE_IDS} - RDSNo = CassIDs<0, 1> - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - If ( ({EMPLOYEE_ID} NE '') and ({TOOL_ID} NE '') and ({SUPPLIER_LOT} NE '') and ({CASSETTE_IDS} NE '') and ( (CurrStage EQ 'LOAD') or (CurrStage EQ 'VER') ) ) | - or ( ({EMPLOYEE_ID} NE '') and ({TOOL_ID} NE '') and ({CASSETTE_IDS} NE '') and (CurrStage EQ 'UNLOAD') ) then - // RDS object - objRDS = '' - - If SRP_JSON(objRDS, 'New', 'Object') then - - RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) - * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') - CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') - If CurrStage EQ 'VER' then - VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') - If VerSupplID NE False$ then - SupplVerInstAckReq = True$ - end else - SupplVerInstAckReq = False$ - end - end else - SupplVerInstAckReq = False$ - end - - If CurrStage EQ 'VER' or CurrStage EQ 'LOAD' then - LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') - If LoadSupplID NE False$ then - SupplLoadInstAckReq = True$ - end else - SupplLoadInstAckReq = False$ - end - end else - SupplLoadInstAckReq = False$ - end - - If CurrStage EQ 'UNLOAD' then - UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') - If UnloadSupplID NE False$ then - SupplUnloadInstAckReq = True$ - end else - SupplUnloadInstAckReq = False$ - end - - ReactorNo = Xlate('RDS', RDSNo, RDS_REACTOR$, 'X') + + jsonScan = '' + + If ScanID NE '' then + + If mvScan EQ '' then mvScan = Database_Services('ReadDataRow', 'SCANS', ScanID) + If Error_Services('NoError') then + @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') + @ID = ScanID + @RECORD = mvScan + objJSONScan = '' + If SRP_JSON(objJSONScan, 'New', 'Object') then + // Scan object. + If SRP_JSON(objScan, 'New', 'Object') then + SRP_JSON(objScan, 'SetValue', 'ID', @ID, 'String') + SRP_JSON(objScan, 'SetValue', 'type', {SCAN_TYPE}, 'String') + SRP_JSON(objScan, 'SetValue', 'action', {ACTION}, 'String') + SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') + + SRP_JSON(objScan, 'SetValue', 'acceptable', {ACCEPTABLE}, 'Boolean') + SRP_JSON(objScan, 'SetValue', 'notAcceptableReason', {NOT_ACCEPTABLE_REASON}, 'String') + SRP_JSON(objScan, 'SetValue', 'result', {RESULT}, 'String') + SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') + SRP_JSON(objScan, 'SetValue', 'testRunTypeName', XLate('TEST_RUN_TYPE', {TEST_RUN_TYPE_ID}, TEST_RUN_TYPE_RUN_TYPE$, 'X'), 'String') + If SRP_JSON(arrayScanLog, 'New', 'Array') then + If {SCANNED_DATES} NE '' then + ScannedDates = {SCANNED_DATES} + For Each ScannedDate in scannedDates using @VM setting vPos + objScanSession = '' + If SRP_JSON(objScanSession, 'New', 'Object') then + SRP_JSON(objScanSession, 'SetValue', 'date', Oconv({SCANNED_DATES}<0, vPos>, 'D4/'), 'String') + SRP_JSON(objScanSession, 'SetValue', 'time', Oconv({SCANNED_TIMES}<0, vPos>, 'MTH'), 'String') + SRP_JSON(objScanSession, 'SetValue', 'data', {SCANNED_DATA}<0, vPos>, 'String') + SRP_JSON(arrayScanLog, 'Add', objScanSession) + SRP_JSON(objScanSession, 'Release') + end + Next ScannedDate + end + SRP_JSON(objScan, 'Set', 'scanLog', arrayScanLog) + SRP_JSON(arrayScanLog, 'Release') + end + + SRP_JSON(objJSONScan, 'Set', 'scan', objScan) + SRP_JSON(objScan, 'Release') + end + // Supplier Lot object. + objSupplierLot = '' + If SRP_JSON(objSupplierLot, 'New', 'Object') then + SRP_JSON(objSupplierLot, 'SetValue', 'ID', {SUPPLIER_LOT}, 'String') + SRP_JSON(objJSONScan, 'Set', 'supplierLot', objSupplierLot) + SRP_JSON(objSupplierLot, 'Release') + end + // TestWafer Lot Object. + If SRP_JSON(hTWLotArray, 'New', 'Array') then + Abort = False$ + TestWaferLots = {TW_LOT_ID} + for each TestWaferLotId in TestWaferLots using @VM setting twPos + thisTWLotJson = '' + If SRP_JSON(thisTWLotJson, 'New', 'Object') then + SRP_JSON(thisTWLotJson, 'SetValue', 'testWaferLotId', {TW_LOT_ID}<1, twPos>) + SRP_JSON(thisTWLotJson, 'SetValue', 'quantity', {TW_LOT_QTY}<1, twPos>, 'Integer') + SRP_JSON(hTWLotArray, 'Add', thisTWLotJson) + SRP_JSON(thisTWLotJson, 'Release') + end + Next TestWaferLotId + SRP_JSON(objJSONScan, 'Set', 'testWaferLots', hTWLotArray) + SRP_JSON(hTWLotArray, 'Release') + end + SRP_JSON(objScan, 'SetValue', 'testRunTypeId', {TEST_RUN_TYPE_ID}, 'Integer') + // TestRun Type Option Array + TestRunTypeList = Test_Run_Services('GetAllTestRunTypes') + If SRP_JSON(hTestRunTypeArray, 'New', 'Array') then + For each TestRunTypeId in TestRunTypeList<1> using @VM setting fPos + hTestRunTypeObj = '' + If SRP_JSON(hTestRunTypeObj, 'New', 'Object') then + SRP_JSON(hTestRunTypeObj, 'SetValue', 'testRunTypeId', TestRunTypeId, 'Number') + SRP_JSON(hTestRunTypeObj, 'SetValue', 'testRunTypeName', TestRunTypeList<2, fPos>, 'String') + SRP_JSON(hTestRunTypeArray, 'Add', hTestRunTypeObj) + SRP_JSON(hTestRunTypeObj, 'Release') + end else + Abort = True$ + end + Until Abort + Next TestRunTypeId + If Abort EQ False$ then + SRP_JSON(objJSONScan, 'Set', 'testRunTypeOptions', hTestRunTypeArray) + end + SRP_JSON(hTestRunTypeArray, 'Release') + end + // Created object. + objCreated = '' + If SRP_JSON(objCreated, 'New', 'Object') then + SRP_JSON(objCreated, 'SetValue', 'date', Oconv({CREATED_DATE}, 'D4/'), 'String') + SRP_JSON(objCreated, 'SetValue', 'time', Oconv({CREATED_TIME}, 'MTH'), 'String') + SRP_JSON(objJSONScan, 'Set', 'created', objCreated) + SRP_JSON(objCreated, 'Release') + end + // Employee object + objEmployee = '' + If SRP_JSON(objEmployee, 'New', 'Object') then + + SRP_JSON(objEmployee, 'SetValue', 'ID', {EMPLOYEE_ID}, 'String') + SRP_JSON(objEmployee, 'SetValue', 'name', {EMPLOYEE_NAME}, 'String') + SRP_JSON(objEmployee, 'SetValue', 'authorized', {EMPLOYEE_AUTHORIZED}, 'Boolean') + SRP_JSON(objEmployee, 'SetValue', 'notAuthorizedReason', {EMPLOYEE_NOT_AUTHORIZED_REASON}, 'String') + SRP_JSON(objEmployee, 'SetValue', 'authenticated' , @Record , 'Boolean');//JRO Change + SRP_JSON(objJSONScan, 'Set', 'employee', objEmployee) + SRP_JSON(objEmployee, 'Release') + + end + // Cassettes object. + arrayCassetteIDs = '' + If SRP_JSON(arrayCassetteIDs, 'New', 'Array') then + If {CASSETTE_IDS} NE '' then + CassetteIDs = {CASSETTE_IDS} + For Each CassetteID in CassetteIDs using @VM + SRP_JSON(arrayCassetteIDs, 'AddValue', CassetteID, 'String') + Next CassetteID + end + SRP_JSON(objJSONScan, 'Set', 'cassetteIDs', arrayCassetteIDs) + SRP_JSON(arrayCassetteIDs, 'Release') + end + // Location object. + objLocation = '' + If SRP_JSON(objLocation, 'New', 'Object') then + SRP_JSON(objLocation, 'SetValue', 'ID', {LOCATION_ID}, 'String') + SRP_JSON(objLocation, 'SetValue', 'name', {LOCATION_NAME}, 'String') + SRP_JSON(objJSONScan, 'Set', 'location', objLocation) + SRP_JSON(objLocation, 'Release') + end + // Tool object. + objTool = '' + If SRP_JSON(objTool, 'New', 'Object') then + SRP_JSON(objTool, 'SetValue', 'ID', {TOOL_ID}, 'String') + SRP_JSON(objTool, 'SetValue', 'name', {TOOL_NAME}, 'String') + SRP_JSON(objTool, 'SetValue', 'loadLock', {LOAD_LOCK}, 'String') + SRP_JSON(objJSONScan, 'Set', 'tool', objTool) + SRP_JSON(objTool, 'Release') + end + // Accepted object. + objAccepted = '' + If SRP_JSON(objAccepted, 'New', 'Object') then + SRP_JSON(objAccepted, 'SetValue', 'status', {ACCEPTED}, 'Boolean') + SRP_JSON(objAccepted, 'SetValue', 'date', Oconv({ACCEPTED_DATE}, 'D4/'), 'String') + SRP_JSON(objAccepted, 'SetValue', 'time', Oconv({ACCEPTED_TIME}, 'MTH'), 'String') + SRP_JSON(objEmployee, 'SetValue', 'notAcceptedReason', {NOT_ACCEPTABLE_REASON}, 'String') + SRP_JSON(objJSONScan, 'Set', 'accepted', objAccepted) + SRP_JSON(objAccepted, 'Release') + end + // Wafer Count object. + objWaferCount = '' + If SRP_JSON(objWaferCount, 'New', 'Object') then + SRP_JSON(objWaferCount, 'SetValue', 'scheduler', {SCHEDULER_WAFER_COUNT}, 'Number') + SRP_JSON(objWaferCount, 'SetValue', 'confirmed', {WAFER_COUNT_CONFIRMED}, 'Boolean') + SRP_JSON(objJSONScan, 'Set', 'waferCount', objWaferCount) + SRP_JSON(objWaferCount, 'Release') + end + // Transfer object. + objTransfer = '' + If SRP_JSON(objTransfer, 'New', 'Object') then + // Transfer Tool sub-object. + objTool = '' + If SRP_JSON(objTool, 'New', 'Object') then + SRP_JSON(objTool, 'SetValue', 'ID', {TRANSFER_TOOL_ID}, 'String') + SRP_JSON(objTool, 'SetValue', 'name', {TRANSFER_TOOL_NAME}, 'String') + SRP_JSON(objTransfer, 'Set', 'tool', objTool) + SRP_JSON(objTool, 'Release') + end + SRP_JSON(objTransfer, 'SetValue', 'boatID', {BOAT_ID}, 'String') + SRP_JSON(objTransfer, 'SetValue', 'plNumber', {PL_NUMBER}, 'String') + SRP_JSON(objTransfer, 'SetValue', 'unloadplConfirmed', {UNLOAD_PL_CONFIRMED}, 'Boolean') + SRP_JSON(objJSONScan, 'Set', 'transfer', objTransfer) + SRP_JSON(objTransfer, 'Release') + end + SRP_JSON(objJSONScan, 'SetValue', 'lastModified', {LAST_MODIFIED}, 'String') + + If {SCAN_TYPE} EQ 'TOOL' then + CassIDs = {CASSETTE_IDS} + RDSNo = CassIDs<0, 1> + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + If ( ({EMPLOYEE_ID} NE '') and ({TOOL_ID} NE '') and ({SUPPLIER_LOT} NE '') and ({CASSETTE_IDS} NE '') and ( (CurrStage EQ 'LOAD') or (CurrStage EQ 'VER') ) ) | + or ( ({EMPLOYEE_ID} NE '') and ({TOOL_ID} NE '') and ({CASSETTE_IDS} NE '') and (CurrStage EQ 'UNLOAD') ) then + // RDS object + objRDS = '' + + If SRP_JSON(objRDS, 'New', 'Object') then + + RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) + * SupplInstAckReq = Xlate('RDS', RDSNo, 'SUPPL_ACK_REQ' , 'X') + CurrStage = Xlate('RDS', RDSNo, 'CURR_STAGE', 'X') + If CurrStage EQ 'VER' then + VerSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'VER') + If VerSupplID NE False$ then + SupplVerInstAckReq = True$ + end else + SupplVerInstAckReq = False$ + end + end else + SupplVerInstAckReq = False$ + end + + If CurrStage EQ 'VER' or CurrStage EQ 'LOAD' then + LoadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'LOAD') + If LoadSupplID NE False$ then + SupplLoadInstAckReq = True$ + end else + SupplLoadInstAckReq = False$ + end + end else + SupplLoadInstAckReq = False$ + end + + If CurrStage EQ 'UNLOAD' then + UnloadSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'UNLOAD') + If UnloadSupplID NE False$ then + SupplUnloadInstAckReq = True$ + end else + SupplUnloadInstAckReq = False$ + end + + ReactorNo = Xlate('RDS', RDSNo, RDS_REACTOR$, 'X') ReactorType = Xlate('REACTOR', ReactorNo, REACTOR_REACT_TYPE$, 'X') If Len(ReactorType) GE 3 and ReactorType[1, 3] _EQC 'HTR' then WO = Xlate('RDS', RDSNo, RDS_WO$, 'X') @@ -1789,7 +1798,7 @@ Service ConvertMVScanToJSON(ScanID, mvScan, itemURL) LastCassInWoTestWaferReqMsg = '' If LastCassInWoTestWaferAcked EQ False$ or LastCassInWoTestWaferAcked EQ '' then LastCassInWo = WO_MAT_Services('CassetteIsLastInWo', WoMatKey) - + If LastCassInWo then NextEventScheduled = False$ NextEventHasSamePsn = True$ @@ -1822,287 +1831,287 @@ Service ConvertMVScanToJSON(ScanID, mvScan, itemURL) SRP_JSON(objRDS, 'SetValue', 'lastCassInWoTestWaferAcked', LastCassInWoTestWaferAcked, 'Boolean') SRP_JSON(objRDS, 'SetValue', 'lastCassInWoTestWaferAckReqMsg', LastCassInWoTestWaferReqMsg, 'String') end - end else - SupplUnloadInstAckReq = False$ - end - - If CurrStage EQ 'POST' then - PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') - If PostSupplID NE False$ then - SupplPostInstAckReq = True$ - end else - SupplPostInstAckReq = False$ - end - end else - SupplPostInstAckReq = False$ - end - - @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') - @ID = ScanID - @RECORD = mvScan - - RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') - RDSLayerIDs = Xlate('RDS', RDSNo, 'RDS_LS_ID' , 'X') - PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') - PreInst = Xlate('RDS', RDSNo, 'PRE_INST' , 'X') - FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') - FwiInst = Xlate('RDS', RDSNo, 'FWI_INST' , 'X') - LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') - LwiInst = Xlate('RDS', RDSNo, 'LWI_INST' , 'X') - QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') - QAInst = Xlate('RDS', RDSNo, 'QA_INST' , 'X') - LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') - LoadInst = Xlate('RDS', RDSNo, 'LOAD_INST' , 'X') - UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') - UnloadInst = Xlate('RDS', RDSNo, 'UNLOAD_INST' , 'X') - PostInstAckReq = Xlate('RDS', RDSNo, 'POST_INST_ACK_REQ' , 'X') - PostInst = Xlate('RDS', RDSNo, 'POST_INST' , 'X') - WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') - - * SchedWfrCnt = Xlate('SCANS', ScanID, 'SCHEDULER_WAFER_COUNT', 'X') - WaferCountInst = 'Please verify the wafer quantity in the cassette matches the ' | - : 'scheduled wafer quantity, ':{SCHEDULER_WAFER_COUNT}:'.' - - * SRP_JSON(objRDS, 'SetValue', 'supplInstAckReq' , SupplInstAckReq , 'Boolean') - * SRP_JSON(objRDS, 'SetValue', 'supplInstAck' , RDSRec , 'Boolean') - * SRP_JSON(objRDS, 'SetValue', 'supplInst' , RDSRec , 'String') - - - If supplLoadInstAckReq EQ TRUE$ then - supplLoadInstAck = Xlate('SUPPLEMENTS', LoadSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') - supplLoadInst = Xlate('SUPPLEMENTS', LoadSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') - end else - supplLoadInstAck = '' - supplLoadInst = '' - end - SRP_JSON(objRDS, 'SetValue', 'supplLoadInstAckReq' , supplLoadInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplLoadInstAck' , supplLoadInstAck , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplLoadInst' , supplLoadInst , 'String') - - If supplVerInstAckReq EQ TRUE$ then - supplVerInstAck = Xlate('SUPPLEMENTS', VerSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') - supplVerInst = Xlate('SUPPLEMENTS', VerSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') - end else - supplVerInstAck = '' - supplVerInst = '' - end - SRP_JSON(objRDS, 'SetValue', 'supplVerInstAckReq' , supplVerInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplVerInstAck' , supplVerInstAck , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplVerInst' , supplVerInst , 'String') - - - If supplUnloadInstAckReq EQ TRUE$ then - supplUnloadInstAck = Xlate('SUPPLEMENTS', UnloadSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') - supplUnloadInst = Xlate('SUPPLEMENTS', UnloadSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') - end else - supplUnloadInstAck = '' - supplUnloadInst = '' - end - SRP_JSON(objRDS, 'SetValue', 'supplUnloadInstAckReq' , supplUnloadInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplUnloadInstAck' , supplUnloadInstAck , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplUnloadInst' , supplUnloadInst , 'String') - - If supplPostInstAckReq EQ TRUE$ then - supplPostInstAck = Xlate('SUPPLEMENTS', PostSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') - supplPostInst = Xlate('SUPPLEMENTS', PostSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') - end else - supplPostInstAck = '' - supplPostInst = '' - end - SRP_JSON(objRDS, 'SetValue', 'supplPostInstAckReq' , supplPostInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplPostInstAck' , supplPostInstAck , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'supplPostInst' , supplPostInst , 'String') - - SRP_JSON(objRDS, 'SetValue', 'preInstAckReq' , PreInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'preInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'preInst' , PreInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'fwiInstAckReq' , FwiInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'fwiInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'fwiInst' , FwiInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'lwiInstAckReq' , LwiInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'lwiInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'lwiInst' , LwiInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'qaInstAckReq' , QAInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'qaInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'qaInst' , QAInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'loadInstAckReq' , LoadInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'loadInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'loadInst' , LoadInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'unloadInstAckReq' , UnloadInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'unloadInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'unloadInst' , UnloadInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'postInstAckReq' , PostInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'postInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'postInst' , PostInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'waferCountInstAckReq' , WaferCountInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'waferCountInstAck' , RDSRec , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'waferCountInst' , WaferCountInst , 'String') - SRP_JSON(objRDS, 'SetValue', 'rdsLayerInstAckReq' , RDSLayerInstAckReq , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'rdsLayerInstAck' , RDSRec , 'Boolean') - - OverrideRequired = @Record - OverrideType = @Record - OverrideReason = @Record - SRP_JSON(objRDS, 'SetValue', 'overRideAckReq' , OverrideRequired , 'Boolean') - SRP_JSON(objRDS, 'SetValue', 'overRideType' , OverrideType , 'string') - SRP_JSON(objRDS, 'SetValue', 'overRideReason', @Record, 'string') - - If ((OverrideRequired EQ True$) and (OverrideType EQ 'ROTR')) then - Swap " " with "" in OverrideReason - OverrideComments = Xlate("ROTR_OVERRIDE_COMMENT_OPTIONS", OverrideReason, ROTR_OVERRIDE_COMMENT_OPTIONS_COMMENT_OPTIONS$, 'X') - SRP_JSON(objRds, "SetValueArray", "overRideComments", OverrideComments, @VM) - - Reactor = {TOOL_ID}[2,999] - rotrOverrideCount = Xlate('REACTOR', Reactor, REACTOR_ROTR_OVERRIDE_COUNT$, 'X') - if rotrOverrideCount EQ '' then rotrOverrideCount = 0 - SRP_JSON(objRds, "SetValue", "rotrOverrideCount", rotrOverrideCount, 'Number') - end - arrayRDSLayers = '' - // Add RDSLayers (recipe parameters) array - If SRP_JSON(arrayRDSLayers, 'New', 'Array') then - For each RDSLayerID in RDSLayerIDs using @VM setting vPos - arrayParameters = '' - If SRP_JSON(arrayParameters, 'New', 'Array') then - RDSLayerKey = RDSNo:'*':RDSLayerID - ColNames = 'LS_ID,RECIPE_NO,RECIPE_NAME,DOPANT,EPI_DILUENT,EPI_TIME,' | - : 'DILUENT_ADJ_PARAM,DOPANT_FLOW,HCL_FLOW,BAKE_TIME,EPI_H2_FLOW,' | - : 'TCS_FLOW,DCS_FLOW,AUX1,AUX2,F_OFFSET,S_OFFSET,R_OFFSET,' | - : 'SUSC_ETCH,ETCH1,ETCH2,ETCH3,UL_TEMP' - ParamList = 'Layer ID,Recipe,Recipe Name,Dopant,Epi Diluent,Deposit,' | - : 'Diluent,Dopant Flow,HCL Flow,Bake Time,H2 Flow,TCS Flow,' | - : 'DCS Flow,Aux 1 Flow,Aux 2 flow,F Offset,S Offset,R Offset,' | - : 'Susc Etch,Etch 1,Etch 2,Etch 3,Unload Temp' - pos = '' - For each Parameter in ParamList using ',' setting pos - ColName = Field(ColNames, ',', pos) - ParamData = Xlate('RDS_LAYER', RDSLayerKey, ColName, 'X') - Conversion = Xlate('DICT.RDS_LAYER', ColName, DICT_CONV$, 'X') - If ParamData NE '' then - If Conversion NE '' then ParamData = OConv(ParamData, Conversion) - objParameter = '' - If SRP_JSON(objParameter, 'New', 'Object') then - Success = SRP_JSON(objParameter, 'SetValue', 'Parameter', Parameter) - Success = SRP_JSON(objParameter, 'SetValue', 'Value', ParamData) - // Add parameter object to parameter array - Success = SRP_JSON(arrayParameters, 'Add', objParameter) - SRP_JSON(objParameter, 'Release') - end - end - Next Value - end - // Add parameter array to RDS Layer array - Success = SRP_JSON(arrayRDSLayers, 'Add', arrayParameters) - SRP_JSON(arrayParameters, 'Release') - Next RDSLayerID - Success = SRP_JSON(objRDS, 'Set', 'rdsLayers', arrayRDSLayers) - SRP_JSON(arrayRDSLayers, 'Release') - end - - SRP_JSON(objJSONScan, 'Set', 'rds', objRDS) - SRP_JSON(objRDS, 'Release') - end - end - end - - If itemURL NE '' then - // The itemURL was passed in so add HAL+JSON properties. - objLinks = '' - // Create the _links property and then all link objects needed for this resource. - If SRP_JSON(objLinks, 'New', 'Object') then - // Create a self link. - objLink = '' - If SRP_JSON(objLink, 'New', 'Object') then - SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String') - SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String') - SRP_JSON(objLinks, 'Set', 'self', objLink) - SRP_JSON(objLink, 'Release') - end - SRP_JSON(objJSONScan, 'Set', '_links', objLinks) - SRP_JSON(objLinks, 'Release') - end - objForm = '' - // Create the _form property to help UIs determine what to display. - If SRP_JSON(objForm, 'New', 'Object') then - arrayFields = '' - If SRP_JSON(arrayFields, 'New', 'Array') then - If {EMPLOYEE_ID} NE '' then - objField = '' - If SRP_JSON(objField, 'New', 'Object') then - SRP_JSON(objField, 'SetValue', 'label', 'Employee', 'String') - SRP_JSON(objField, 'SetValue', 'value', {EMPLOYEE_NAME}, 'String') - SRP_JSON(arrayFields, 'Add', objField) - SRP_JSON(objField, 'Release') - end - end - If {LOCATION_ID} NE '' then - If SRP_JSON(objField, 'New', 'Object') then - SRP_JSON(objField, 'SetValue', 'label', 'Location', 'String') - SRP_JSON(objField, 'SetValue', 'value', {LOCATION_NAME}, 'String') - SRP_JSON(arrayFields, 'Add', objField) - SRP_JSON(objField, 'Release') - end - end - If {TOOL_ID} NE '' then - If SRP_JSON(objField, 'New', 'Object') then - SRP_JSON(objField, 'SetValue', 'label', 'Tool', 'String') - ToolName = {TOOL_NAME} - If {LOAD_LOCK} NE '' then ToolName := ' ( ' : {LOAD_LOCK} : ' )' - SRP_JSON(objField, 'SetValue', 'value', ToolName, 'String') - SRP_JSON(arrayFields, 'Add', objField) - SRP_JSON(objField, 'Release') - end - * If {LOAD_LOCK} NE '' then - * If SRP_JSON(objField, 'New', 'Object') then - * SRP_JSON(objField, 'SetValue', 'label', 'Load Lock', 'String') - * SRP_JSON(objField, 'SetValue', 'value', {LOAD_LOCK}, 'String') - * SRP_JSON(arrayFields, 'Add', objField) - * SRP_JSON(objField, 'Release') - * end - * end - end - If {TRANSFER_TOOL_ID} NE '' then - If SRP_JSON(objField, 'New', 'Object') then - SRP_JSON(objField, 'SetValue', 'label', 'Transfer', 'String') - SRP_JSON(objField, 'SetValue', 'value', {TRANSFER_TOOL_NAME}, 'String') - SRP_JSON(arrayFields, 'Add', objField) - SRP_JSON(objField, 'Release') - end - end - If {CASSETTE_IDS} NE '' then - If SRP_JSON(objField, 'New', 'Object') then - SRP_JSON(objField, 'SetValue', 'label', 'Cassette ID', 'String') - If SRP_JSON(arrayCassetteIDs, 'New', 'Array') then - For Each CassetteID in CassetteIDs using @VM - SRP_JSON(arrayCassetteIDs, 'AddValue', CassetteID, 'String') - Next CassetteID - SRP_JSON(objField, 'Set', 'values', arrayCassetteIDs) - SRP_JSON(arrayCassetteIDs, 'Release') - end - SRP_JSON(arrayFields, 'Add', objField) - SRP_JSON(objField, 'Release') - end - end - SRP_JSON(objForm, 'Set', 'fields', arrayFields) - SRP_JSON(arrayFields, 'Release') - end - SRP_JSON(objJSONScan, 'Set', '_form', objForm) - SRP_JSON(objForm, 'Release') - end - // Create the _class property for this resource. - SRP_JSON(objJSONScan, 'SetValue', '_class', 'resource') - end - jsonScan = SRP_JSON(objJSONScan, 'Stringify', 'Styled') - SRP_JSON(objJSONScan, 'Release') - end else - Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.') - end - end - end else - Error_Services('Add', 'ScanID argument was missing in the ' : Service : ' service.') - end - - Response = jsonScan - + end else + SupplUnloadInstAckReq = False$ + end + + If CurrStage EQ 'POST' then + PostSupplID = Supplement_Services('UnacknowledgedSupplementCheck', 'RDS', RDSNo, 'POST') + If PostSupplID NE False$ then + SupplPostInstAckReq = True$ + end else + SupplPostInstAckReq = False$ + end + end else + SupplPostInstAckReq = False$ + end + + @DICT = Database_Services('GetTableHandle', 'DICT.SCANS') + @ID = ScanID + @RECORD = mvScan + + RDSLayerInstAckReq = Xlate('RDS', RDSNo, 'RDS_LAYER_ACK_REQ' , 'X') + RDSLayerIDs = Xlate('RDS', RDSNo, 'RDS_LS_ID' , 'X') + PreInstAckReq = Xlate('RDS', RDSNo, 'PRE_INST_ACK_REQ' , 'X') + PreInst = Xlate('RDS', RDSNo, 'PRE_INST' , 'X') + FwiInstAckReq = Xlate('RDS', RDSNo, 'FWI_INST_ACK_REQ' , 'X') + FwiInst = Xlate('RDS', RDSNo, 'FWI_INST' , 'X') + LwiInstAckReq = Xlate('RDS', RDSNo, 'LWI_INST_ACK_REQ' , 'X') + LwiInst = Xlate('RDS', RDSNo, 'LWI_INST' , 'X') + QAInstAckReq = Xlate('RDS', RDSNo, 'QA_INST_ACK_REQ' , 'X') + QAInst = Xlate('RDS', RDSNo, 'QA_INST' , 'X') + LoadInstAckReq = Xlate('RDS', RDSNo, 'LOAD_INST_ACK_REQ' , 'X') + LoadInst = Xlate('RDS', RDSNo, 'LOAD_INST' , 'X') + UnloadInstAckReq = Xlate('RDS', RDSNo, 'UNLOAD_INST_ACK_REQ' , 'X') + UnloadInst = Xlate('RDS', RDSNo, 'UNLOAD_INST' , 'X') + PostInstAckReq = Xlate('RDS', RDSNo, 'POST_INST_ACK_REQ' , 'X') + PostInst = Xlate('RDS', RDSNo, 'POST_INST' , 'X') + WaferCountInstAckReq = Xlate('RDS', RDSNo, 'WAFER_COUNT_ACK_REQ' , 'X') + + * SchedWfrCnt = Xlate('SCANS', ScanID, 'SCHEDULER_WAFER_COUNT', 'X') + WaferCountInst = 'Please verify the wafer quantity in the cassette matches the ' | + : 'scheduled wafer quantity, ':{SCHEDULER_WAFER_COUNT}:'.' + + * SRP_JSON(objRDS, 'SetValue', 'supplInstAckReq' , SupplInstAckReq , 'Boolean') + * SRP_JSON(objRDS, 'SetValue', 'supplInstAck' , RDSRec , 'Boolean') + * SRP_JSON(objRDS, 'SetValue', 'supplInst' , RDSRec , 'String') + + + If supplLoadInstAckReq EQ TRUE$ then + supplLoadInstAck = Xlate('SUPPLEMENTS', LoadSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') + supplLoadInst = Xlate('SUPPLEMENTS', LoadSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') + end else + supplLoadInstAck = '' + supplLoadInst = '' + end + SRP_JSON(objRDS, 'SetValue', 'supplLoadInstAckReq' , supplLoadInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplLoadInstAck' , supplLoadInstAck , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplLoadInst' , supplLoadInst , 'String') + + If supplVerInstAckReq EQ TRUE$ then + supplVerInstAck = Xlate('SUPPLEMENTS', VerSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') + supplVerInst = Xlate('SUPPLEMENTS', VerSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') + end else + supplVerInstAck = '' + supplVerInst = '' + end + SRP_JSON(objRDS, 'SetValue', 'supplVerInstAckReq' , supplVerInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplVerInstAck' , supplVerInstAck , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplVerInst' , supplVerInst , 'String') + + + If supplUnloadInstAckReq EQ TRUE$ then + supplUnloadInstAck = Xlate('SUPPLEMENTS', UnloadSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') + supplUnloadInst = Xlate('SUPPLEMENTS', UnloadSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') + end else + supplUnloadInstAck = '' + supplUnloadInst = '' + end + SRP_JSON(objRDS, 'SetValue', 'supplUnloadInstAckReq' , supplUnloadInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplUnloadInstAck' , supplUnloadInstAck , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplUnloadInst' , supplUnloadInst , 'String') + + If supplPostInstAckReq EQ TRUE$ then + supplPostInstAck = Xlate('SUPPLEMENTS', PostSupplID, SUPPLEMENTS_SUPPL_ACK$, 'X', '') + supplPostInst = Xlate('SUPPLEMENTS', PostSupplID, SUPPLEMENTS_SUPPL_TEXT$, 'X', '') + end else + supplPostInstAck = '' + supplPostInst = '' + end + SRP_JSON(objRDS, 'SetValue', 'supplPostInstAckReq' , supplPostInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplPostInstAck' , supplPostInstAck , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'supplPostInst' , supplPostInst , 'String') + + SRP_JSON(objRDS, 'SetValue', 'preInstAckReq' , PreInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'preInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'preInst' , PreInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'fwiInstAckReq' , FwiInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'fwiInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'fwiInst' , FwiInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'lwiInstAckReq' , LwiInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'lwiInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'lwiInst' , LwiInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'qaInstAckReq' , QAInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'qaInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'qaInst' , QAInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'loadInstAckReq' , LoadInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'loadInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'loadInst' , LoadInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'unloadInstAckReq' , UnloadInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'unloadInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'unloadInst' , UnloadInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'postInstAckReq' , PostInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'postInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'postInst' , PostInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'waferCountInstAckReq' , WaferCountInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'waferCountInstAck' , RDSRec , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'waferCountInst' , WaferCountInst , 'String') + SRP_JSON(objRDS, 'SetValue', 'rdsLayerInstAckReq' , RDSLayerInstAckReq , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'rdsLayerInstAck' , RDSRec , 'Boolean') + + OverrideRequired = @Record + OverrideType = @Record + OverrideReason = @Record + SRP_JSON(objRDS, 'SetValue', 'overRideAckReq' , OverrideRequired , 'Boolean') + SRP_JSON(objRDS, 'SetValue', 'overRideType' , OverrideType , 'string') + SRP_JSON(objRDS, 'SetValue', 'overRideReason', @Record, 'string') + + If ((OverrideRequired EQ True$) and (OverrideType EQ 'ROTR')) then + Swap " " with "" in OverrideReason + OverrideComments = Xlate("ROTR_OVERRIDE_COMMENT_OPTIONS", OverrideReason, ROTR_OVERRIDE_COMMENT_OPTIONS_COMMENT_OPTIONS$, 'X') + SRP_JSON(objRds, "SetValueArray", "overRideComments", OverrideComments, @VM) + + Reactor = {TOOL_ID}[2,999] + rotrOverrideCount = Xlate('REACTOR', Reactor, REACTOR_ROTR_OVERRIDE_COUNT$, 'X') + if rotrOverrideCount EQ '' then rotrOverrideCount = 0 + SRP_JSON(objRds, "SetValue", "rotrOverrideCount", rotrOverrideCount, 'Number') + end + arrayRDSLayers = '' + // Add RDSLayers (recipe parameters) array + If SRP_JSON(arrayRDSLayers, 'New', 'Array') then + For each RDSLayerID in RDSLayerIDs using @VM setting vPos + arrayParameters = '' + If SRP_JSON(arrayParameters, 'New', 'Array') then + RDSLayerKey = RDSNo:'*':RDSLayerID + ColNames = 'LS_ID,RECIPE_NO,RECIPE_NAME,DOPANT,EPI_DILUENT,EPI_TIME,' | + : 'DILUENT_ADJ_PARAM,DOPANT_FLOW,HCL_FLOW,BAKE_TIME,EPI_H2_FLOW,' | + : 'TCS_FLOW,DCS_FLOW,AUX1,AUX2,F_OFFSET,S_OFFSET,R_OFFSET,' | + : 'SUSC_ETCH,ETCH1,ETCH2,ETCH3,UL_TEMP' + ParamList = 'Layer ID,Recipe,Recipe Name,Dopant,Epi Diluent,Deposit,' | + : 'Diluent,Dopant Flow,HCL Flow,Bake Time,H2 Flow,TCS Flow,' | + : 'DCS Flow,Aux 1 Flow,Aux 2 flow,F Offset,S Offset,R Offset,' | + : 'Susc Etch,Etch 1,Etch 2,Etch 3,Unload Temp' + pos = '' + For each Parameter in ParamList using ',' setting pos + ColName = Field(ColNames, ',', pos) + ParamData = Xlate('RDS_LAYER', RDSLayerKey, ColName, 'X') + Conversion = Xlate('DICT.RDS_LAYER', ColName, DICT_CONV$, 'X') + If ParamData NE '' then + If Conversion NE '' then ParamData = OConv(ParamData, Conversion) + objParameter = '' + If SRP_JSON(objParameter, 'New', 'Object') then + Success = SRP_JSON(objParameter, 'SetValue', 'Parameter', Parameter) + Success = SRP_JSON(objParameter, 'SetValue', 'Value', ParamData) + // Add parameter object to parameter array + Success = SRP_JSON(arrayParameters, 'Add', objParameter) + SRP_JSON(objParameter, 'Release') + end + end + Next Value + end + // Add parameter array to RDS Layer array + Success = SRP_JSON(arrayRDSLayers, 'Add', arrayParameters) + SRP_JSON(arrayParameters, 'Release') + Next RDSLayerID + Success = SRP_JSON(objRDS, 'Set', 'rdsLayers', arrayRDSLayers) + SRP_JSON(arrayRDSLayers, 'Release') + end + + SRP_JSON(objJSONScan, 'Set', 'rds', objRDS) + SRP_JSON(objRDS, 'Release') + end + end + end + + If itemURL NE '' then + // The itemURL was passed in so add HAL+JSON properties. + objLinks = '' + // Create the _links property and then all link objects needed for this resource. + If SRP_JSON(objLinks, 'New', 'Object') then + // Create a self link. + objLink = '' + If SRP_JSON(objLink, 'New', 'Object') then + SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String') + SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String') + SRP_JSON(objLinks, 'Set', 'self', objLink) + SRP_JSON(objLink, 'Release') + end + SRP_JSON(objJSONScan, 'Set', '_links', objLinks) + SRP_JSON(objLinks, 'Release') + end + objForm = '' + // Create the _form property to help UIs determine what to display. + If SRP_JSON(objForm, 'New', 'Object') then + arrayFields = '' + If SRP_JSON(arrayFields, 'New', 'Array') then + If {EMPLOYEE_ID} NE '' then + objField = '' + If SRP_JSON(objField, 'New', 'Object') then + SRP_JSON(objField, 'SetValue', 'label', 'Employee', 'String') + SRP_JSON(objField, 'SetValue', 'value', {EMPLOYEE_NAME}, 'String') + SRP_JSON(arrayFields, 'Add', objField) + SRP_JSON(objField, 'Release') + end + end + If {LOCATION_ID} NE '' then + If SRP_JSON(objField, 'New', 'Object') then + SRP_JSON(objField, 'SetValue', 'label', 'Location', 'String') + SRP_JSON(objField, 'SetValue', 'value', {LOCATION_NAME}, 'String') + SRP_JSON(arrayFields, 'Add', objField) + SRP_JSON(objField, 'Release') + end + end + If {TOOL_ID} NE '' then + If SRP_JSON(objField, 'New', 'Object') then + SRP_JSON(objField, 'SetValue', 'label', 'Tool', 'String') + ToolName = {TOOL_NAME} + If {LOAD_LOCK} NE '' then ToolName := ' ( ' : {LOAD_LOCK} : ' )' + SRP_JSON(objField, 'SetValue', 'value', ToolName, 'String') + SRP_JSON(arrayFields, 'Add', objField) + SRP_JSON(objField, 'Release') + end + * If {LOAD_LOCK} NE '' then + * If SRP_JSON(objField, 'New', 'Object') then + * SRP_JSON(objField, 'SetValue', 'label', 'Load Lock', 'String') + * SRP_JSON(objField, 'SetValue', 'value', {LOAD_LOCK}, 'String') + * SRP_JSON(arrayFields, 'Add', objField) + * SRP_JSON(objField, 'Release') + * end + * end + end + If {TRANSFER_TOOL_ID} NE '' then + If SRP_JSON(objField, 'New', 'Object') then + SRP_JSON(objField, 'SetValue', 'label', 'Transfer', 'String') + SRP_JSON(objField, 'SetValue', 'value', {TRANSFER_TOOL_NAME}, 'String') + SRP_JSON(arrayFields, 'Add', objField) + SRP_JSON(objField, 'Release') + end + end + If {CASSETTE_IDS} NE '' then + If SRP_JSON(objField, 'New', 'Object') then + SRP_JSON(objField, 'SetValue', 'label', 'Cassette ID', 'String') + If SRP_JSON(arrayCassetteIDs, 'New', 'Array') then + For Each CassetteID in CassetteIDs using @VM + SRP_JSON(arrayCassetteIDs, 'AddValue', CassetteID, 'String') + Next CassetteID + SRP_JSON(objField, 'Set', 'values', arrayCassetteIDs) + SRP_JSON(arrayCassetteIDs, 'Release') + end + SRP_JSON(arrayFields, 'Add', objField) + SRP_JSON(objField, 'Release') + end + end + SRP_JSON(objForm, 'Set', 'fields', arrayFields) + SRP_JSON(arrayFields, 'Release') + end + SRP_JSON(objJSONScan, 'Set', '_form', objForm) + SRP_JSON(objForm, 'Release') + end + // Create the _class property for this resource. + SRP_JSON(objJSONScan, 'SetValue', '_class', 'resource') + end + jsonScan = SRP_JSON(objJSONScan, 'Stringify', 'Styled') + SRP_JSON(objJSONScan, 'Release') + end else + Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.') + end + end + end else + Error_Services('Add', 'ScanID argument was missing in the ' : Service : ' service.') + end + + Response = jsonScan + end service //---------------------------------------------------------------------------------------------------------------------- @@ -2111,60 +2120,60 @@ end service // Converts a serialized JSON scan object into a MultiValue formatted SCANS row and returns the result. //---------------------------------------------------------------------------------------------------------------------- Service ConvertJSONScanToMV(jsonScan) - - mvScan = '' - - If jsonScan NE '' then - If SRP_JSON(objJSONScan, 'Parse', jsonScan) EQ '' then - - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'created.date') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'created.time') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.type') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'employee.ID') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'location.ID') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'tool.ID') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'tool.loadLock') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.status', False$) - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.date') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.time') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'action') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'waferCount.confirmed', False$) - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.boatID') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.plNumber') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.unloadplConfirmed', False$) - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.tool.ID') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.testRunTypId') - mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.testRunTypeName') - - arrayCassettes = SRP_JSON(objJSONScan, 'Get', 'cassetteIDs') - NumCassettes = SRP_JSON(arrayCassettes, 'GetCount') - For CassetteCnt = 1 to NumCassettes - mvScan = SRP_JSON(arrayCassettes, 'GetValue', CassetteCnt) - Next CassetteCnt - SRP_JSON(arrayCassettes, 'Release') - - arrayScanLog = SRP_JSON(objJSONScan, 'Get', 'scan.scanLog') - NumScanSessions = SRP_JSON(arrayScanLog, 'GetCount') - For ScanSessionCnt = 1 to NumScanSessions - objScan = SRP_JSON(arrayScanLog, 'Get', ScanSessionCnt) - mvScan = SRP_JSON(objScan, 'GetValue', 'date') - mvScan = SRP_JSON(objScan, 'GetValue', 'time') - mvScan = SRP_JSON(objScan, 'GetValue', 'data') - SRP_JSON(objScan, 'Release') - Next ScanSessionCnt - SRP_JSON(arrayScanLog, 'Release') - - SRP_JSON(objJSONScan, 'Release') - - end else - Error_Services('Add', 'Error parsing jsonScan in the ' : Service : ' service.') - end - end else - Error_Services('Add', 'jsonScan argument was missing in the ' : Service : ' service.') - end - - Response = mvScan - + + mvScan = '' + + If jsonScan NE '' then + If SRP_JSON(objJSONScan, 'Parse', jsonScan) EQ '' then + + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'created.date') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'created.time') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.type') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'employee.ID') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'location.ID') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'tool.ID') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'tool.loadLock') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.status', False$) + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.date') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'accepted.time') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'action') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'waferCount.confirmed', False$) + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.boatID') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.plNumber') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.unloadplConfirmed', False$) + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'transfer.tool.ID') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.testRunTypId') + mvScan = SRP_JSON(objJSONScan, 'GetValue', 'scan.testRunTypeName') + + arrayCassettes = SRP_JSON(objJSONScan, 'Get', 'cassetteIDs') + NumCassettes = SRP_JSON(arrayCassettes, 'GetCount') + For CassetteCnt = 1 to NumCassettes + mvScan = SRP_JSON(arrayCassettes, 'GetValue', CassetteCnt) + Next CassetteCnt + SRP_JSON(arrayCassettes, 'Release') + + arrayScanLog = SRP_JSON(objJSONScan, 'Get', 'scan.scanLog') + NumScanSessions = SRP_JSON(arrayScanLog, 'GetCount') + For ScanSessionCnt = 1 to NumScanSessions + objScan = SRP_JSON(arrayScanLog, 'Get', ScanSessionCnt) + mvScan = SRP_JSON(objScan, 'GetValue', 'date') + mvScan = SRP_JSON(objScan, 'GetValue', 'time') + mvScan = SRP_JSON(objScan, 'GetValue', 'data') + SRP_JSON(objScan, 'Release') + Next ScanSessionCnt + SRP_JSON(arrayScanLog, 'Release') + + SRP_JSON(objJSONScan, 'Release') + + end else + Error_Services('Add', 'Error parsing jsonScan in the ' : Service : ' service.') + end + end else + Error_Services('Add', 'jsonScan argument was missing in the ' : Service : ' service.') + end + + Response = mvScan + end service @@ -2177,152 +2186,152 @@ end service // data. //---------------------------------------------------------------------------------------------------------------------- Service DecodeScanData(ScanData) - - DecodedScanData = '' - - If Len(ScanData) then - DecodedScanData = ScanData - Swap '/A' with '!' in DecodedScanData - Swap '/B' with '"' in DecodedScanData - Swap '/C' with '#' in DecodedScanData - Swap '/D' with '$' in DecodedScanData - Swap '/E' with '%' in DecodedScanData - Swap '/F' with '&' in DecodedScanData - Swap '/G' with "'" in DecodedScanData - Swap '/H' with '(' in DecodedScanData - Swap '/I' with ')' in DecodedScanData - Swap '/J' with '*' in DecodedScanData - Swap '/K' with '+' in DecodedScanData - Swap '/L' with ',' in DecodedScanData - Swap '/O' with '/' in DecodedScanData - Swap '/Z' with ':' in DecodedScanData - Swap '%F' with ';' in DecodedScanData - Swap '%G' with '<' in DecodedScanData - Swap '%H' with '=' in DecodedScanData - Swap '%I' with '>' in DecodedScanData - Swap '%J' with '?' in DecodedScanData - Swap '%O' with '_' in DecodedScanData - end else - Error_Services('Add', 'The ScanData argument was missing in the ' : Service : ' service.') - end - - Response = DecodedScanData - + + DecodedScanData = '' + + If Len(ScanData) then + DecodedScanData = ScanData + Swap '/A' with '!' in DecodedScanData + Swap '/B' with '"' in DecodedScanData + Swap '/C' with '#' in DecodedScanData + Swap '/D' with '$' in DecodedScanData + Swap '/E' with '%' in DecodedScanData + Swap '/F' with '&' in DecodedScanData + Swap '/G' with "'" in DecodedScanData + Swap '/H' with '(' in DecodedScanData + Swap '/I' with ')' in DecodedScanData + Swap '/J' with '*' in DecodedScanData + Swap '/K' with '+' in DecodedScanData + Swap '/L' with ',' in DecodedScanData + Swap '/O' with '/' in DecodedScanData + Swap '/Z' with ':' in DecodedScanData + Swap '%F' with ';' in DecodedScanData + Swap '%G' with '<' in DecodedScanData + Swap '%H' with '=' in DecodedScanData + Swap '%I' with '>' in DecodedScanData + Swap '%J' with '?' in DecodedScanData + Swap '%O' with '_' in DecodedScanData + end else + Error_Services('Add', 'The ScanData argument was missing in the ' : Service : ' service.') + end + + Response = DecodedScanData + end service Service ResetDevData(CassetteIDs) - - DevCassettes = '277147,277425,277074,277265,277107,277106,276833,277006,277005,276833,276832,276895,276701,276700,277308,277118,277117,276604' - Swap ',' with @VM in DevCassettes - If CassetteIDs EQ '' then CassetteIDs = DevCassettes - - For each CassetteID in CassetteIDs using @VM - // Reset RDS record - RDSRec = Database_Services('ReadDataRow', 'RDS', CassetteID) - If Error_Services('NoError') then - If CassetteID EQ 277147 then - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - Database_Services('WriteDataRow', 'RDS', CassetteID, RDSRec, True$, False$, True$) - If Error_Services('NoError') then - WOMatKey = Xlate('RDS', CassetteID, 'WO_MAT_KEY', 'X') - WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) - If Error_Services('NoError') then - WOMatRec = '' - WOMatRec = '' - Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) - end - end - end else - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - RDSRec = '' - Database_Services('WriteDataRow', 'RDS', CassetteID, RDSRec, True$, False$, True$) - If Error_Services('NoError') then - WOMatKey = Xlate('RDS', CassetteID, 'WO_MAT_KEY', 'X') - WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) - If Error_Services('NoError') then - WOMatRec = '' - WOMatRec = '' - Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) - end - end - RDSLayerKeys = RDSRec - For each RDSLayerKey in RDSLayerKeys using @VM - RDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', RDSLayerKey) - * RDSLayerRec = '' - * RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - RDSLayerRec = '' - Database_Services('WriteDataRow', 'RDS_LAYER', RDSLayerKey, RDSLayerRec, True$, False$, True$) - Next RDSLayerKey - end - end - Next CassetteID - + + DevCassettes = '277147,277425,277074,277265,277107,277106,276833,277006,277005,276833,276832,276895,276701,276700,277308,277118,277117,276604' + Swap ',' with @VM in DevCassettes + If CassetteIDs EQ '' then CassetteIDs = DevCassettes + + For each CassetteID in CassetteIDs using @VM + // Reset RDS record + RDSRec = Database_Services('ReadDataRow', 'RDS', CassetteID) + If Error_Services('NoError') then + If CassetteID EQ 277147 then + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + Database_Services('WriteDataRow', 'RDS', CassetteID, RDSRec, True$, False$, True$) + If Error_Services('NoError') then + WOMatKey = Xlate('RDS', CassetteID, 'WO_MAT_KEY', 'X') + WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) + If Error_Services('NoError') then + WOMatRec = '' + WOMatRec = '' + Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) + end + end + end else + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + RDSRec = '' + Database_Services('WriteDataRow', 'RDS', CassetteID, RDSRec, True$, False$, True$) + If Error_Services('NoError') then + WOMatKey = Xlate('RDS', CassetteID, 'WO_MAT_KEY', 'X') + WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey) + If Error_Services('NoError') then + WOMatRec = '' + WOMatRec = '' + Database_Services('WriteDataRow', 'WO_MAT', WOMatKey, WOMatRec, True$, False$, True$) + end + end + RDSLayerKeys = RDSRec + For each RDSLayerKey in RDSLayerKeys using @VM + RDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', RDSLayerKey) + * RDSLayerRec = '' + * RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + RDSLayerRec = '' + Database_Services('WriteDataRow', 'RDS_LAYER', RDSLayerKey, RDSLayerRec, True$, False$, True$) + Next RDSLayerKey + end + end + Next CassetteID + end service Service RemoveOldScans() - - CleanDate = OConv((Date() - 30), 'D4/') - Query = 'SELECT SCANS WITH CREATED_DATE LT ':Quote(CleanDate) - GoSub ClearCursors - RList(Query, TARGET_ACTIVELIST$, '', '', '') - If Not(Get_Status(errCode)) then - Done = False$ - Loop - Readnext KeyID else Done = True$ - Until Done - Database_Services('DeleteDataRow', 'SCANS', KeyID) - Repeat - end - + + CleanDate = OConv((Date() - 30), 'D4/') + Query = 'SELECT SCANS WITH CREATED_DATE LT ':Quote(CleanDate) + GoSub ClearCursors + RList(Query, TARGET_ACTIVELIST$, '', '', '') + If Not(Get_Status(errCode)) then + Done = False$ + Loop + Readnext KeyID else Done = True$ + Until Done + Database_Services('DeleteDataRow', 'SCANS', KeyID) + Repeat + end + end service @@ -2332,13 +2341,14 @@ end service ClearCursors: - - For counter = 0 to 8 - ClearSelect counter - Next counter - + + For counter = 0 to 8 + ClearSelect counter + Next counter + return +