open-insight/LSL2/STPROC/RDS_SERVICES.txt
Ouellette Jonathan (CSC FI SPS MESLEO) 49c9ab09fd Merged PR 10039: Code to determine if a test wafer usage logging is required.
Description
Created method to determine if a TW is required.

HTR and ASM type reactors will required a test wafer to be logged on runs where a test wafer is prescribed.
ASM+ type reactors will require a test wafer to be logged on one run prior to a run where a test wafer is prescribed for metrology.
This code is gated by an active switch which will be removed when the system goes live.

EpiPro is not effected

Related work items: #222043
2025-02-04 18:53:58 +01:00

1781 lines
70 KiB
Plaintext

Function RDS_Services(@Service, @Params)
/***********************************************************************************************************************
Name : RDS_Services
Description : Handler program for all RDS services.
Notes : Application errors should be logged using the Error Services module. There are a few methodological
assumptions built into way errors are managed which are important to understand in order to properly
work with Error Services:
- The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to
the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger
this will appear backwards since the originating procedure always appears at the bottom of the
list and the current routine appears at the top of the list. We are using this orientation because
it is common to refer to the process of calling other procedures as 'drilling down'.
- The reason for defining the orientation of the call stack is because Error_Services allows for
multiple error conditions to be appended to an original error. In most cases this will happen when
a procedure at the bottom of the stack generates an error condition and then returns to its
calling procedure. This higher level procedure can optionally add more information relevant to
itself. This continues as the call stack 'bubbles' its way back to the top to where the
originating procedure is waiting.
- Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus)
preserve their error state until explicitly cleared. This can hinder the normal execution of code
since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists.
Our philosophy is that error conditions should automatically be cleared before a new procedure
is executed to avoid this problem. However, the nature of Basic+ does not make this easy to
automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our
philosophy then it should include a call into the 'Clear' service request at the top of the
program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.)
- Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any
error conditions that were set before.
Parameters :
Service [in] -- Name of the service being requested
Param1-10 [in/out] -- Additional request parameter holders
Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure
Metadata :
History : (Date, Initials, Notes)
05/14/18 djs Original programmer.
09/18/18 djs Added the IsEpiPro service.
08/23/21 dpc Added validation routine IsPackaged
08/28/23 djm Added view/add comment functions.
06/13/24 djm Add GetCurrentStatus service.
07/18/24 djm Update AddComment to use Obj_Post_Log to reduce lag.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$Insert APP_INSERTS
$Insert MSG_EQUATES
$Insert RTI_DEBUG_COMMON
$Insert SRPMail_Inserts
$Insert LOGICAL
$Insert SERVICE_SETUP
$Insert RDS_EQUATES
$Insert PROD_SPEC_EQUATES
$Insert RDS_LAYER_EQUATES
$Insert PRS_LAYER_EQUATES
$Insert RDS_TEST_EQUATES
$Insert TOOL_CLASS_EQUATES
$Insert TEST_POINT_MAP_EQUATES
$Insert CLEAN_INSP_EQUATES
$Insert REACT_RUN_EQUATES
$Insert REACTOR_EQUATES
$Insert WO_MAT_QA_EQUATES
$Insert PRS_STAGE_EQUATES
$Insert PRS_PROP_EQUATES
$Insert WO_LOG_EQUATES
$Insert WM_OUT_EQUATES
$Insert REACT_UTIL_EQU
$Insert WO_MAT_EQUATES
$Insert RLIST_EQUATES
$Insert REACT_MODE_EQUATES
$Insert LSL_USERS_EQUATES
$Insert TOOL_EQUATES
$Insert POPUP_EQUATES
$Insert NOTIFICATION_EQUATES
$Insert DICT_EQUATES
$Insert COMPANY_EQUATES
$Insert RETURN_TO_FAB_LOTS_EQUATES
EQU COL$LSID TO 1
EQU COL$RECIPE TO 2
EQU COL$RECIPE_NAME TO 3
EQU COL$PARAMS TO 4
EQU COL$PARMS_OUT TO 5
EQU COL$BLANK_COL TO 6
EQU COL$MET_NO TO 7
EQU COL$THICK_AVG TO 8
EQU COL$RRHO_AVG TO 9
EQU COL$MET_NO_Z1 TO 10
EQU COL$THICK_AVG_Z1 TO 11
EQU COL$RRHO_AVG_Z1 TO 12
EQU COL$MET_NO_Z2 TO 13
EQU COL$THICK_AVG_Z2 TO 14
EQU COL$RRHO_AVG_Z2 TO 15
EQU COL$MET_OUT TO 16
EQU COL$MET_OUT_Z1 TO 17
EQU COL$MET_OUT_Z2 TO 18
EQU COL$MET_TWSIG TO 19
EQU COL$MET_TWSIG_Z1 TO 20
EQU COL$MET_TWSIG_Z2 TO 21
EQU COMMA$ to ','
AutoDisplayErrors = FALSE$ ; // Set this to True$ when debugging so all errors will automatically display.
Declare subroutine SRP_Stopwatch, Error_Services, obj_Tables, Metrology_Services, obj_RDS_Test, SRP_JSON, Logging_Services
Declare subroutine RTI_Set_Debugger, Database_Services, Btree.Extract, Extract_SI_Keys, Obj_WO_Mat, Obj_WO_Mat_Log
Declare subroutine Dialog_Box, Obj_Notes, RList, Set_Status, Errmsg, Obj_React_Status , Reactor_Services
Declare subroutine Rds_Services, Obj_Post_Log
Declare function SRP_Sort_Array, Metrology_Services, obj_RDS_Test, obj_Test_Point_Map, Database_Services
Declare function Work_Order_Services, SRP_JSON, Logging_Services, Environment_Services, SRP_Trim, Error_Services
Declare function Memberof, Obj_WO_Mat, Obj_WO_Mat_Log, SRP_Array, DateTime, Dialog_Box, obj_Prod_Spec
Declare function RDS_Services, RTI_DistinctList, GetTickCount, Clean_Insp_Services, WO_Mat_QA_Services
Declare function PSN_Services, Rds_Layer_Services, SRP_Rotate_Array, Qa_Services, SRP_Date, SRP_Time, SRP_Datetime
Declare function Reactor_Services, Signature_Services, obj_rds, Test_Run_Services, Return_To_Fab_Services
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\RDS'
LogDate = Oconv(Date(), 'D4/')
LogTime = Oconv(Time(), 'MTS')
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Ctrl Performance Log.csv'
Headers = 'Logging DTM':@FM:'Ctrl':@FM:'Load/Calculate Time'
objCtrlLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, COMMA$, Headers, '', False$, False$)
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
GoToService else
Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end
Return Response else ''
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options BOOLEAN = True$, False$
Options STAGES = 'PRE', 'FWI', 'LWI', 'QA', 'LOAD', 'UNLOAD'
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------------------------------------------------
// GetCurrentStage
//
// RDSNo. - [Required]
//
// Returns the current stage of a lot. Replaces CURR_STAGE calculated column.
//----------------------------------------------------------------------------------------------------------------------
Service GetCurrentStage(RDSNo)
If RDSNo NE '' then
RDSCheck = Xlate('RDS', RDSNo, '', 'X', '')
If RDSCheck NE '' then
CurrStage = ''
WOMatKey = Xlate('RDS', RDSNo, 'WO_MAT_KEY', 'X')
SigProfile = Signature_Services('GetSigProfile', WOMatKey, FALSE$, RDSNo)
Stages = SigProfile<1>
Signatures = SigProfile<2>
SigCount = DCount(Signatures, @VM)
StageCount = DCount(Stages, @VM)
Swap @VM with @FM in Stages
Swap @VM with @FM in Signatures
For I = 1 to StageCount
If Signatures<I> EQ '' then
CurrStage = Stages<I>
end
Until Signatures<I> EQ ''
Next I
If CurrStage EQ '' then CurrStage = 'COMP'
Response = CurrStage
end else
ErrorMessage = 'Invalid RDSNo.'
Error_Services('Add', ErrorMessage)
end
end else
ErrorMessage = 'This service requires an RDSNo to be passed in.'
Error_Services('Add', ErrorMessage)
end
End Service
//----------------------------------------------------------------------------------------------------------------------
// GetComments
//
// RDSNo. - [Required]
//
// Returns a delimited array of all COMMENT, COMMENT_USER, and COMMENT_DATE OR
// EPP_COMMENT, EPP_COMMENT_USER, and EPP_COMMENT_DATE associated with an RDS record. Note: Dates are returned Oconv'd.
//----------------------------------------------------------------------------------------------------------------------
Service GetComments(RDSNo)
CommentArray = ''
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
CommentDates = Oconv(RDSRow<RDS_COMMENT_DATE$>, 'DT')
CommentUsers = RDSRow<RDS_COMMENT_USER$>
Comments = RDSRow<RDS_COMMENT_NOTE$>
CommentList = CommentDates :@FM: CommentUsers :@FM: Comments
CommentArray = SRP_Rotate_Array(CommentList)
Response = CommentArray
End Service
//----------------------------------------------------------------------------------------------------------------------
// AddComment
//
// RDSNo. - [Required]
// Comment - [Required]
// UsernameOpt - [Optional]
//
// Adds a COMMENT, COMMENT_USER, and COMMENT_DATE OR an EPP_COMMENT, EPP_COMMENT_USER, and EPP_COMMENT_DATE
// to an RDS record.
//----------------------------------------------------------------------------------------------------------------------
Service AddComment(RDSNo, Comment, UsernameOpt)
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
Username = @USER4
If Assigned(UsernameOpt) then
If UsernameOpt NE '' then
Username = UsernameOpt
end
end
CommentTime = Datetime()
Fields = RDS_COMMENT_DATE$:@VM ; Values = CommentTime:@VM
Fields := RDS_COMMENT_USER$:@VM ; Values := UserName:@VM
Fields := RDS_COMMENT_NOTE$ ; Values := Comment
oblParms = 'RDS':@RM
oblParms := RDSNo:@RM
oblParms := Fields:@RM
oblParms := Values:@RM
oblParms := "TOP" :@VM: "TOP" :@VM: "TOP"
obj_Post_Log('Create',oblParms)
End Service
//----------------------------------------------------------------------------------------------------------------------
// GetFinalQAStatus
//
// RDSNo. - [Required]
//
// Returns the boolean value of the Final QA status of a given RDS record. Returns True$ if
// the Final QA step is signed and False$ if it is not signed.
//----------------------------------------------------------------------------------------------------------------------
Service GetFinalQAStatus(RDSNo)
FinalQA = False$
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
WorkOrderNo = RDSRow<RDS_WO$>
WorkOrderRow = Database_Services('ReadDataRow', 'WO_LOG', WorkOrderNo)
ReactType = WorkOrderRow<WO_LOG_REACT_TYPE$>
// Check to see if the Final QA signature is in place.
If ReactType EQ 'EPP' then
CassetteNos = RDSRow<RDS_OUT_CASS_NO$>
For Each CassetteNo in CassetteNos using @VM
WMOutKey = RDSRow<RDS_WO_STEP_KEY$> : '*' : CassetteNo
WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', WMOutKey)
If WMOutRow<WM_OUT_SUP_VER_SIG$> NE '' then
FinalQA = true$
end
Until FinalQA
Next CassetteNo
end else
If RDSRow<RDS_SUP_VER_SIG$> NE '' then
FinalQA = True$
end
end
Response = FinalQA
End Service
Service IsPackaged(RDSNo, RDSType)
isPackaged = False$
//ReactType = XLATE('RDS', RDSNo, 'REACTOR_TYPE', '')
// Check to see if the Final QA signature is in place.
If RDSType EQ 'EPP' then
Convert '.' TO '*' in RDSNo
WMOutKey = Xlate('WM_OUT', RDSNo, 'WO_MAT_KEY', 'X')
WoMatAction = Database_Services('ReadDataColumn', 'WO_MAT',WMOutKey, 8)
isPackaged = Index(WoMatAction, 'PACK', 1) > 0
end else if RDSType EQ 'GAN' then
Convert '.' TO '*' in RDSNo
WoMatAction = Database_Services('ReadDataColumn', 'WO_MAT',RDSNo, 8)
isPackaged = Index(WoMatAction, 'PACK', 1) > 0
end else
RDSRow = Database_Services('ReadDataRow', 'RDS', RDSNo)
WoNo = RDSRow<RDS_WO$>
WoCassNo = RDSRow<RDS_CASS_NO$>
WoMatKey = WoNo:'*':WoCassNo
WoMatAction = Database_Services('ReadDataColumn', 'WO_MAT',WoMatKey, 8)
isPackaged = Index(WoMatAction, 'PACK', 1) > 0
end
Response = isPackaged
End Service
Service GetHoldStatus(RDSNo, RDSType)
Response = False$
If Error_Services('NoError') then
IF RDSType EQ 'EPP' then
Convert '.' to '*' in RDSNo
WOMatKey = Xlate('WM_OUT', RDSNo, 'WO_MAT_KEY', 'X')
end else iF RDSType EQ 'GAN' then
Convert '.' to '*' in RDSNo
WOMatKey = RDSNo
end else
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
WONo = RDSRec<RDS_WO$>
CassNo = RDSRec<RDS_CASS_NO$>
WOMatKey = WONo:'*':CassNo
end
If WOMatKey NE '' then
WOMatCurrStatus = obj_WO_Mat('CurrStatus', WOMatKey)
If WOMatCurrStatus EQ 'HOLD' then Response = True$
end else
ErrorMessage = 'Null work order or cassette number in ':Service' for RDS ':RDSNo:'.'
Error_Services('Add', ErrorMessage)
end
end
End Service
//----------------------------------------------------------------------------------------------------------------------
// GetRDSList
//
// WorkOrderNo. - [Required]
// KeysOnly. - [Optional]
//
// Returns a list of RDS records within a supplied Work Order.
// Rows are @FM delimted while columns are @VM delimited.
//----------------------------------------------------------------------------------------------------------------------
Service GetRDSList(WorkOrderNo, KeysOnly=BOOLEAN)
RDSList = ''
If WorkOrderNo NE '' then
rv = Set_Status(0)
RDSKeys = ''
extract_si_keys('RDS', 'WO', WorkOrderNo, RDSKeys)
StatusCode = ''
If Get_Status(StatusCode) then
Error_Services('Add', 'Error calling Extract_SI_Keys in the ' : Service : ' service. StatusCode: ' : StatusCode)
end else
NumRDS = DCount(RDSKeys, @VM)
@DICT = Database_Services('GetTableHandle', 'DICT.' : 'RDS')
If Error_Services('NoError') then
For Each @ID in RDSKeys using @VM
@RECORD = Database_Services('ReadDataRow', 'RDS', @ID)
If Error_Services('NoError') then
RDSDet = {ABBREV_OR_CO_NAME} : @VM
RDSDet := {WO} : @VM
RDSDet := {WO_STEP} : @VM
RDSDet := {RUN_ORDER_NUM} : @VM
RDSDet := @ID : @VM
RDSDet := {REACTOR} : @VM
RDSDet := {REACT_IDLE_TIME} : @VM
RDSDet := {HGCV_TEST} : @VM
RDSDet := {DATE_IN} : @VM
RDSDet := {TIME_IN} : @VM
RDSDet := {DATE_OUT} : @VM
RDSDet := {TIME_OUT} : @VM
RDSDet := {ELAPSED_HOURS} : @VM
RDSDet := {PO} : @VM
RDSDet := {PART_NUM} : @VM
RDSDet := {LOT_NUM} : @VM
RDSDet := {COMB_STATUS} : @VM
RDSDet := {NCR_SUM} : @VM
RDSDet := {HOLD_STATUS} : @VM
RDSDet := {SUPPL_INST}
If KeysOnly EQ True$ then
RDSList = Insert(RDSList, -1, 0, 0, @ID)
end else
RDSList = Insert(RDSList, -1, 0, 0, RDSDet)
end
end else
Error_Services('Add', 'Error reading RDS Record ' : @ID : ' in the ' : Service : ' service.')
end
Next @ID
end else
Error_Services('Add', 'Error opening RDS dictionary in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'WorkOrderNo argument was missing from the ' : Service : ' service.')
end
Response = RDSList
end service
//----------------------------------------------------------------------------------------------------------------------
// GetRDSData
//
// WorkOrderNo. - [Required]
// KeysOnly. - [Optional]
//
// Returns a list of RDS records within a supplied Work Order.
// Rows are @FM delimted while columns are @VM delimited.
//----------------------------------------------------------------------------------------------------------------------
Service GetRDSData(WorkOrderNo, Columns, ShowGasGauge, RDSOverrideList)
RDSList = ''
If ( (WorkOrderNo NE '') or (RDSOverrideList NE '') ) then
If ShowGasGauge NE True$ then ShowGasGauge = False$
rv = Set_Status(0)
RDSKeys = ''
If WorkOrderNo NE '' then
Extract_Si_Keys('RDS', 'WO', WorkOrderNo, RDSKeys)
end else
Swap @FM with @VM in RDSOverrideList
RDSKeys = RDSOverrideList
end
StatusCode = ''
If Get_Status(StatusCode) then
Error_Services('Add', 'Error calling Extract_SI_Keys in the ' : Service : ' service. StatusCode: ' : StatusCode)
end else
If RDSKeys NE '' then
NumRDS = DCount(RDSKeys, @VM)
If ShowGasGauge then
Def = ""
Def<MCAPTION$> = "Loading Run Data Sheets..."
Def<MTYPE$> = "G"
Def<MEXTENT$> = NumRDS
Def<MTEXTWIDTH$> = 400
Def<MCOL$> = -2 ;* message h-pos in pixels, or -2 (center screen, the default), -1 (center parent)
Def<MROW$> = -2 ;* message v-pos in pixels
MsgUp = Msg(@Window, Def)
end
@DICT = Database_Services('GetTableHandle', 'DICT.' : 'RDS')
If Error_Services('NoError') then
For each @ID in RDSKeys using @VM setting fPos
@RECORD = Database_Services('ReadDataRow', 'RDS', @ID)
If Error_Services('NoError') then
For each Column in Columns using @VM setting vPos
LoadTimeStart = GetTickCount()
Begin Case
Case Column EQ 'HOLD_STATUS'
HoldStatus = Calculate(Column)
If HoldStatus EQ 'No' then HoldStatus = 'Off Hold'
RDSList<fPos, vPos> = HoldStatus
Case Column EQ 'ELAPSED_HOURS'
Val = OConv(Calculate(Column), 'MD2L')
Hours = Field(Val, '.', 1)
Minutes = '0.':Field(Val, '.', 2)
Minutes = 60 * Minutes
Minutes = Minutes[1, 'F.']
Minutes = Fmt(Minutes, 'R(0)#2')
RDSList<fPos, vPos> = Hours:':':Minutes
Case Otherwise$
RDSList<fPos, vPos> = Calculate(Column)
End Case
Next Column
end else
Error_Services('Add', 'Error reading RDS Record ' : @ID : ' in the ' : Service : ' service.')
end
* update the gauge
If ShowGasGauge then Msg(@Window, MsgUp, fPos, MSGINSTUPDATE$)
Next @ID
end else
Error_Services('Add', 'Error opening RDS dictionary in the ' : Service : ' service.')
end
If ShowGasGauge then Msg(@Window, MsgUp) ;* take down the gauge
end
end
end else
Error_Services('Add', 'WorkOrderNo or RDSOverrideList argument was missing from the ' : Service : ' service.')
end
Response = RDSList
end service
//----------------------------------------------------------------------------------------------------------------------
// SetSupplement
//
// SupplementList. - [Required]
// Username. - [Optional]
//
// Accepts a list with the following structure:
// <1> Row Text
// <1,1> Column Text RDSNo
// <1,2> Column Text Supplement Instructions
//----------------------------------------------------------------------------------------------------------------------
Service SetSupplement(SupplementList, Username)
RDSNotificationListAdd = ''
RDSNotificationListRemove = ''
Action = ''
If SupplementList NE '' then
@DICT = Database_Services('GetTableHandle', 'DICT.' : 'RDS')
If Error_Services('NoError') then
For Each Row in SupplementList using @FM
ChangeDetected = False$
@ID = Row<1,1>
SupplementInst = Row<1,2>
@RECORD = Database_Services('ReadDataRow', 'RDS', @ID)
If Error_Services('NoError') then
If SupplementInst NE '' then
If SupplementInst NE {SUPPL_INST} then
// Supplement information has been added or updated.
ChangeDetected = True$
Action = 'Add'
{SUPPLEMENT} = True$
{SUPPL_INST} = SupplementInst
{SUPPL_ENTRY_DATE} = date()
{SUPPL_ENTRY_TIME} = time()
If Username NE '' then
{SUPPL_ENTRY_ID} = Username
end else
{SUPPL_ENTRY_ID} = @User4
end
end
end else
If SupplementInst NE {SUPPL_INST} then
// Supplement information has been removed.
ChangeDetected = True$
Action = 'Remove'
{SUPPLEMENT} = False$
{SUPPL_INST} = ''
{SUPPL_ENTRY_DATE} = ''
{SUPPL_ENTRY_TIME} = ''
{SUPPL_ENTRY_ID} = ''
end
end
If ChangeDetected And Action EQ 'Add' then
Database_Services('WriteDataRow', 'RDS', @ID, @RECORD)
RDSNotificationListAdd<-1> = @ID
end
If ChangeDetected And Action EQ 'Remove' then
Database_Services('WriteDataRow', 'RDS', @ID, @RECORD)
RDSNotificationListRemove<-1> = @ID
end
end else
Error_Services('Add', 'Error reading RDS Record ' : @ID : ' in the ' : Service : ' service.')
end
Next Row
end else
Error_Services('Add', 'Error opening RDS dictionary in the ' : Service : ' service.')
end
end else
Error_Services('Add', 'SupplementList argument was missing from the ' : Service : ' service.')
end
* //Now send an email notification
IF RDSNotificationListAdd NE '' then
Instructions = XLATE('RDS', RDSNotificationListAdd<1>, RDS_SUPPL_INST$, 'X')
PSN = XLATE('RDS', RDSNotificationListAdd<1>, RDS_PROD_SPEC_ID$, 'X')
WoNo = XLATE('RDS', RDSNotificationListAdd<1>, RDS_WO$, 'X')
ReactorNo = XLATE('RDS', RDSNotificationListAdd<1>, RDS_REACTOR$, 'X');
Message = 'This Supplement was created or updated by ':oconv( @user4, '[XLATE_CONV,LSL_USERS*FIRST_LAST]' ):' on ':OCONV( DATE(), 'D2/' ):' at ':OCONV( TIME(), 'MTH' ):'.' : CRLF$
Message := 'WO# : ' : WoNo : CRLF$
Message := 'PSN : ' : PSN : CRLF$
Message := 'Reactor No : ' : ReactorNo : CRLF$
//Message := 'Instructions : ' : Instructions
Message := CRLF$
Message := 'RDS #s : ' : CRLF$
for each RDSNo in RDSNotificationListAdd using @FM
Message := RDSNo : ' - ': XLATE('RDS', RDSNo, RDS_SUPPL_INST$, 'X') :CRLF$
Next RDSNo
Recipients = XLATE('NOTIFICATION','SUPPLEMENTS',NOTIFICATION_USER_ID$,'X')
SendFrom = 'System'
Subject = 'New or Updated Supplement Created for WO# ': WoNo
AttachWindow = ''
AttachKey = ''
SendToGroup = ''
Parms = Recipients:@RM:SendFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
end
IF RDSNotificationListRemove NE '' then
Instructions = XLATE('RDS', RDSNotificationListRemove<1>, RDS_SUPPL_INST$, 'X')
PSN = XLATE('RDS', RDSNotificationListRemove<1>, RDS_PROD_SPEC_ID$, 'X')
WoNo = XLATE('RDS', RDSNotificationListRemove<1>, RDS_WO$, 'X')
ReactorNo = XLATE('RDS', RDSNotificationListRemove<1>, RDS_REACTOR$, 'X');
Message = 'This Supplement was removed by ':oconv( @user4, '[XLATE_CONV,LSL_USERS*FIRST_LAST]' ):' on ':OCONV( DATE(), 'D2/' ):' at ':OCONV( TIME(), 'MTH' ):'.' : CRLF$
Message := 'WO# : ' : WoNo : CRLF$
Message := 'PSN : ' : PSN : CRLF$
Message := 'Reactor No : ' : ReactorNo : CRLF$
//Message := 'Instructions : ' : Instructions
Message := CRLF$
Message := 'RDS #s : ' : CRLF$
for each RDSNo in RDSNotificationListRemove using @FM
Message := RDSNo :CRLF$
Next RDSNo
Recipients = XLATE('NOTIFICATION','SUPPLEMENTS',NOTIFICATION_USER_ID$,'X')
SendFrom = 'System'
Subject = 'Supplement Removed for WO# ': WoNo
AttachWindow = ''
AttachKey = ''
SendToGroup = ''
Parms = Recipients:@RM:SendFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
obj_Notes('Create',Parms)
end
end service
//----------------------------------------------------------------------------------------------------------------------
// IsEpiPro
//
// RDSNo. - [Required]
//
// Returns True$ if RDS is an EpiPro run, False$ otherwise.
//----------------------------------------------------------------------------------------------------------------------
Service IsEpiPro(RDSNo)
IsEpiPro = False$
ReactorKey = Xlate('RDS', RDSNo, 'REACTOR', 'X')
ReactorType = Xlate('REACTOR', ReactorKey, 'REACT_TYPE', 'X')
If ReactorType _EQC 'EPP' or ReactorType _EQC 'P' or ReactorType _EQC 'EpiPro' then
IsEpiPro = True$
end
Response = IsEpiPro
End Service
//----------------------------------------------------------------------------------------------------------------------
// IsEpiProTestRun
//
// RDSNo. - [Required]
//
// Returns True$ if RDS is an EpiPro test run, False$ otherwise.
//----------------------------------------------------------------------------------------------------------------------
Service IsEpiProTestRun(RDSNo)
TestRun = True$
If RDSNo NE '' then
EpiPro = RDS_Services('IsEpiPro', RDSNo)
If EpiPro then
WaferChars = Xlate('RDS', RDSNo, 'WAFER_CHAR', 'X')
PocketChars = Xlate('RDS', RDSNo, 'POCKET_CHAR', 'X')
For each WaferChar in WaferChars using @VM setting vPos
If WaferChar EQ 'PROD' then
PocketChar = PocketChars<0, vPos>
If PocketChar NE 'TEST' then TestRun = False$
end
Until TestRun EQ False$
Next WaferChar
end else
Error_Services('Add', 'Error in ':Service:' service. This service only supports EpiPro runs.')
end
end else
Error_Services('Add', 'Error in ':Service:' service. Null RDSNo passed in.')
end
Response = TestRun
end service
//----------------------------------------------------------------------------------------------------------------------
// IsValidRDS
//
// Params - RDSNo, RDSType
// RDSNo can be acutal RDS or WMI for EPP (WO_NO.1.CASS_NO, e.g. 169515.1.20) or WO_MAT for GAN (WO_NO.CASS_NO, e.g. 169410.6)
// Returns True$ if RDS is valid
//----------------------------------------------------------------------------------------------------------------------
Service IsValidRDS(RDSNo, RDSType)
IsValid = False$
FirstChar = RDSNo[1,1]
*debug
Begin Case
Case RDSType EQ 'SIC'
If Num(RDSNo) then
If XLate('RDS', RDSNo, 'SEQ', 'X') NE '' then
IsValid = True$
end
end
Case RDSType EQ 'EPP'
CONVERT '.' TO '*' IN RDSNo
If XLATE('WM_OUT',RDSNo,'SLOT_NO','X') NE '' then
IsValid = True$
end
Case RDSTYpe EQ 'GAN'
CONVERT '.' TO '*' IN RDSNo
If XLATE('WO_MAT', RDSNo, 'RDS_NO', 'X') NE '' then
IsValid = True$
end
End Case
Response = IsValid
end service
Service IsValidSubLot(RDSNo, RDSType, SupplierLot)
IsValid = False$
rec = ''
*debug
Begin Case
Case RDSType EQ 'SIC'
compareLot = XLATE('RDS', RDSNo, RDS_LOT_NUM$, 'X')
if compareLot EQ SupplierLot then
IsValid = True$
end
Case RDSType EQ 'EPP'
CONVERT '.' TO '*' IN RDSNo
compareLot = XLATE('WM_IN', RDSNo, 'LOT_NO', 'X')
if compareLot EQ SupplierLot then
IsValid = True$
end
Case RDSType EQ 'GAN'
CONVERT '.' TO '*' IN RDSNo
compareLot = XLATE('WO_MAT', RDSNo, WO_MAT_LOT_NO$, 'X')
if compareLot EQ SupplierLot then
IsValid = True$
end
End Case
Response = IsValid
end service
Service GetRDSRunHistoryByReactorAndWO(ReactorNo, WO)
table = "RDS"
ErrorMessage = ''
RDSRecords = ''
RDSSortedByAssignmentDTM = ''
Open "DICT ":table To @DICT Else
ErrorMessage = 'Error opening RDS dictionary'
End
If ErrorMessage EQ '' then
srch_strng = "WO":@VM:WO:@FM:"REACTOR":@VM:ReactorNo:@FM
option = ""
flag = ""
Btree.Extract(srch_strng, table, @DICT, RDSRecords, option, flag)
end
RDSRecordsWithPreEpiSig = ''
for each RDSKey in RDSRecords using @VM setting RDSPos
ThisRDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey, True$, 0, False$)
ThisRDSPreEpiDT = ThisRDSRec<RDS_PRE_EPI_SIG_DATE$>
ThisRDSPreEpiTM = ThisRDSRec<RDS_PRE_EPI_SIG_TIME$>
ThisRDSPreEpiDTM = SRP_Datetime('Combine', ThisRDSPreEpiDT, ThisRDSPreEpiTM)
RDSRecordsWithPreEpiSig<1, RDSPos> = RDSKey
RDSRecordsWithPreEpiSig<2, RDSPos> = ThisRDSPreEpiDTM
Next RDSKey
RDSSortedByAssignmentDTM = SRP_Sort_Array(RDSRecordsWithPreEpiSig, 'AN2', 0)
FinalRDSSortedByAssignmentDTM = ''
for each RDS in RDSSortedByAssignmentDTM<1> using @VM setting SortedRDSPos
ThisRDSDtm = RDSSortedByAssignmentDTM<2, SortedRDSPos>
if ThisRDSDtm GT 0 then
FinalRDSSortedByAssignmentDTM<1, -1> = RDS
FinalRDSSortedByAssignmentDTM<2, -1> = OConv(ThisRDSDtm, 'DT')
end
Next RDS
Response = FinalRDSSortedByAssignmentDTM<1>
end service
Service IsTWLoggingReqd(RDSNo)
IsTWReqd = False$
ExistingTWRuns = Test_Run_Services('GetTestRunKeysByRDS', RDSNo)
If ExistingTWRuns EQ '' then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
WONo = RDSRec<RDS_WO$>
ReactNo = RDSRec<RDS_REACTOR$>
ReactorType = Database_Services('ReadDataColumn', 'REACTOR', ReactNo, REACTOR_REACT_TYPE$, True$, 0, False$)
ThisReactorRunOrder = 0
ReactRDSNos = RDS_Services('GetRDSRunHistoryByReactorAndWO', ReactNo, WONo)
LOCATE RDSNo IN ReactRDSNos USING @VM SETTING ThisReactorRunOrder ELSE Return
PSNo = RDSRec<RDS_PROD_SPEC_ID$>
PSRec = Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
PRSLayerKeys = PSRec<PROD_SPEC_PRS_LAYER_KEY$>
for each PRSLayerKey in PRSLayerKeys using @VM
PRSPropKeys = Database_Services('ReadDataColumn', 'PRS_LAYER', PRSLayerKey, 5)
for each PRSPropKey in PRSPropKeys using @VM
PRSPropRec = Database_Services('ReadDataRow', 'PRS_PROP', PRSPropKey)
WaferType = PRSPropRec<6>
TestType = Field(PRSPropKey, '*', 3)
Layer = Field(PRSPropKey, '*', 2)
MeasureFreq = PRSPropRec<PRS_PROP_FREQ$>
Start = PRSPropRec<PRS_PROP_MET_START$>
If WaferType NE 'Product' AND WaferType NE 'Prod' then
BEGIN CASE
CASE MeasureFreq = 'F' AND ThisReactorRunOrder = 1 ; IsTWReqd = 1
CASE ThisReactorRunOrder = Start ; IsTWReqd = 1
CASE NUM(MeasureFreq)
Begin Case
Case ReactorType EQ 'HTR'
//Logging required on lot the data gets logged to
IF MOD(ThisReactorRunOrder,MeasureFreq) - Start = 0 THEN
IsTWReqd = True$
END
Case ReactorType EQ 'ASM'
//Logging required on lot the data gets logged to
IF MOD(ThisReactorRunOrder,MeasureFreq) - Start = 0 THEN
IsTWReqd = True$
END
Case ReactorType EQ 'ASM+'
//Logging required on lot prior to the one the data gets logged to.
IF MOD(ThisReactorRunOrder,MeasureFreq) = 0 THEN
IsTWReqd = True$
END
End Case
END CASE
end
Until IsTWReqd EQ True$
Next PRSPropKey
Until IsTWReqd EQ True$
Next PRSLayerKey
end else
IsTWReqd = False$
end
//The code below will be removed upon final production usage.
TWTrackingSystemActive = Database_Services('ReadDataColumn', 'APP_INFO', 'NEW_TW_SYSTEM_ACTIVE_SWITCH', 1, True$, 0, False$)
If TWTrackingSystemActive EQ False$ then
IsTWReqd = False$
end
Response = IsTWReqd
end service
//----------------------------------------------------------------------------------------------------------------------
// VerifyEPPMetrology
//
// RDSNo. - [Required]
//
// Sets an error in Error_Services if there is an issue with the metrology data.
//----------------------------------------------------------------------------------------------------------------------
Service VerifyEPPMetrology(RDSNo)
If RDSNo NE '' then
ErrorMsg = ''
// ActivateRecord allows for the use of the curly brace notation {}
Database_Services('ActivateRecord', 'RDS', RDSNo)
If {REACTOR_TYPE} EQ 'EPP' then
LayerList = ''
LayerList<COL$LSID> = {RDS_LS_ID}
LayerList<COL$RECIPE> = {LS_RECIPE}
LayerList<COL$RECIPE_NAME> = {LS_RECIPE_NAME}
LayerList<COL$PARAMS> = {LS_PARMS_COMP}
LayerList<COL$PARMS_OUT> = {PARAM_OUT_OF_SPEC}
LayerList<COL$BLANK_COL> = ''
LayerList<COL$MET_NO> = {MET_KEYS}
LayerList<COL$THICK_AVG> = {TTHICK_AVG_ALL}
LayerList<COL$RRHO_AVG> = {TRES_AVG_ALL}
LayerList<COL$MET_NO_Z1> = {MET_KEYS_Z1}
LayerList<COL$THICK_AVG_Z1> = {TTHICK_AVG_ALL_Z1}
LayerList<COL$RRHO_AVG_Z1> = {TRES_AVG_ALL_Z1}
LayerList<COL$MET_NO_Z2> = {MET_KEYS_Z2}
LayerList<COL$THICK_AVG_Z2> = {TTHICK_AVG_ALL_Z2}
LayerList<COL$RRHO_AVG_Z2> = {TRES_AVG_ALL_Z2}
LayerList<COL$MET_OUT> = {MET_OUT_OF_SPEC}
LayerList<COL$MET_OUT_Z1> = {MET_OUT_OF_SPEC_Z1}
LayerList<COL$MET_OUT_Z2> = {MET_OUT_OF_SPEC_Z2}
LayerList<COL$MET_TWSIG> = {MET_TW_SIGNED}
LayerList<COL$MET_TWSIG_Z1> = {MET_TW_SIGNED_Z1}
LayerList<COL$MET_TWSIG_Z2> = {MET_TW_SIGNED_Z2}
LayerList = SRP_Array('Rotate', LayerList, @FM, @VM)
// Improvement for EpiPro to not consider a metrology zone "Out of Spec" if all wafers from that zone
// have been scrapped (i.e. the wafers were either test wafers or were NCR'd)
! WM_OUT data is duplicated here in the RDS and cannot be trusted (i.e., it is not kept in sync properly).
! We should consider modifying this to look at WM_OUT for NCR keys associated with the pocket.
Pockets = {POCKET}
Zones = {ZONE}
PocketChars = {POCKET_CHAR}
OutNCRs = {OUT_NCR}
Zone1Scrapped = False$
Zone2Scrapped = False$
NumZone1Wfrs = 0
NumZone2Wfrs = 0
NumZone1Scraps = 0
NumZone2Scraps = 0
Pocket = ''
For each Pocket in Pockets using @VM setting vPos
Zone = Zones<0, vPos>
PocketChar = PocketChars<0, vPos>
OutNCR = OutNCRs<0, vPos>
Begin Case
Case Zone EQ 1
If PocketChar NE 'DUMMY' then NumZone1Wfrs += 1
Case Zone EQ 2
If PocketChar NE 'DUMMY' then NumZone2Wfrs += 1
End Case
Begin Case
Case ( ( (PocketChar EQ 'TEST') or (OutNCR NE '') ) and (Zone EQ 1) )
NumZone1Scraps += 1
Case ( ( (PocketChar EQ 'TEST') or (OutNCR NE '') ) and (Zone EQ 2) )
NumZone2Scraps += 1
End Case
Next Pocket
If NumZone1Wfrs EQ NumZone1Scraps then Zone1Scrapped = True$
If NumZone2Wfrs EQ NumZone2Scraps then Zone2Scrapped = True$
/////////////////////////////////////////////////////////////////////////////////////////////////
FOR I = 1 TO COUNT(LayerList,@FM) + (LayerList NE '')
* Layer Set Parameters
IF ICONV(LayerList<I,COL$PARMS_OUT>,'B') = 1 ELSE
IF ICONV(LayerList<I,COL$PARAMS>,'B') = 0 THEN
ErrorMsg = 'Recipe Parameters incomplete for RDS: ':RDSNo
END
END
* ASM Metrology
IF LayerList<I,COL$MET_NO> NE '' THEN
MetNo = LayerList<I,COL$MET_NO>
MetRec = XLATE('RDS_TEST',MetNo,'','X')
TWSigned = obj_RDS_Test('TWSignedOff',MetNo:@RM:MetRec)
TestComp = obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)
OutOfSpec = obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec)
IF NOT(obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)) THEN
ErrorMsg = 'Metrology not signed off for Met No: ':MetNo: 'for RDS: ':RDSNo
END ELSE
IF (obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec) = 1) THEN
ErrorMsg = 'Metrology ':MetNo:' is out of spec for RDS: ':RDSNo
END ELSE
IF LayerList<I,COL$THICK_AVG> = '' AND LayerList<I,COL$RRHO_AVG> = '' AND LayerList<I,COL$MET_NO> NE '' THEN
ErrorMsg = 'Metrology incomplete for RDS: ':RDSNo
END
END
END
end
* Zone 1 EpiPRO Metrology
// Update logic to not throw an error if wafers from a failed zone are NCR'd
IF LayerList<I,COL$MET_NO_Z1> NE '' THEN
MetNo = LayerList<I,COL$MET_NO_Z1>
MetRec = XLATE('RDS_TEST',MetNo,'','X')
TWSigned = obj_RDS_Test('TWSignedOff',MetNo:@RM:MetRec)
TestComp = obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)
OutOfSpec = obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec)
IF NOT(obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)) THEN
ErrorMsg = 'Zone 1 Metrology is Incomplete for RDS: ':RDSNo
END ELSE
IF ( (obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec) = 1) and (Zone1Scrapped EQ False$) ) THEN
ErrorMsg = 'Zone 1 Metrology is Out of Spec for RDS: ':RDSNo
END ELSE
IF LayerList<I,COL$THICK_AVG_Z1> = '' AND LayerList<I,COL$RRHO_AVG_Z1> = '' AND LayerList<I,COL$MET_NO_Z1> NE '' THEN
ErrorMsg = 'Zone 1 Metrology is Incomplete for RDS: ':RDSNo
END
//Added check for missing res avg data - JRO
/*IF LayerList<I,COL$THICK_AVG_Z1> NE '' AND LayerList<I,COL$RRHO_AVG_Z1> = '' AND LayerList<I,COL$MET_NO_Z1> NE '' THEN
If Error_Services('NoError') then Error_Services('Add', 'Zone 1 Metrology is missing Resistivity data for RDS: ':RDSNo)
END
*/
END
END
END
* Zone 2 EpiPRO Metrology
// Update logic to not throw an error if wafers from a failed zone are NCR'd
IF LayerList<I,COL$MET_NO_Z2> NE '' THEN
MetNo = LayerList<I,COL$MET_NO_Z2>
MetRec = XLATE('RDS_TEST',MetNo,'','X')
TWSigned = obj_RDS_Test('TWSignedOff',MetNo:@RM:MetRec)
TestComp = obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)
OutOfSpec = obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec)
IF NOT(obj_RDS_Test('TestComplete',MetNo:@RM:MetRec)) THEN
ErrorMsg = 'Zone 2 Metrology is Incomplete for RDS: ':RDSNo
END ELSE
IF ( (obj_RDS_Test('OutOfSpec',MetNo:@RM:MetRec) = 1) and (Zone2Scrapped EQ False$) ) THEN
ErrorMsg = 'Zone 2 Metrology is Out of Spec for RDS: ':RDSNo
END ELSE
IF LayerList<I,COL$THICK_AVG_Z2> = '' AND LayerList<I,COL$RRHO_AVG_Z2> = '' AND LayerList<I,COL$MET_NO_Z2> NE '' THEN
ErrorMsg = 'Zone 2 Metrology is Incomplete for RDS: ':RDSNo
END
/*
//Added check for missing res avg data - JRO
IF LayerList<I,COL$THICK_AVG_Z2> NE '' AND LayerList<I,COL$RRHO_AVG_Z2> = '' AND LayerList<I,COL$MET_NO_Z2> NE '' THEN
If Error_Services('NoError') then Error_Services('Add', 'Zone 2 Metrology is missing Resistivity data for RDS: ':RDSNo)
END
*/
END
END
END
NEXT I
end else
ErrorMsg = 'Non-EpiPro RDS passed to RDS_Services(':Service:')'
end
end else
ErrorMsg = 'Null RDS value passed to RDS_Services(':Service:')'
end
If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
end service
Service RDSVerifyInst(RDSNo, Stage=STAGES)
Database_Services('ActivateRecord', 'RDS', RDSNo)
VerInst = ''
Begin Case
Case Stage EQ 'PRE'
VerInst = {PRE_INST}
Case Stage EQ 'FWI'
VerInst = {FWI_INST}
Case Stage EQ 'LWI'
VerInst = {LWI_INST}
Case Stage EQ 'QA'
VerInst = {QA_INST}
Case Stage EQ 'LOAD'
VerInst = {LOAD_INST}
Case Stage EQ 'UNLOAD'
VerInst = {UNLOAD_INST}
Case Stage EQ 'POST'
VerInst = {POST_INST}
End Case
Response = Dialog_Box('RDS_VER', @Window, VerInst)
Begin Case
Case Stage EQ 'PRE'
{PRE_INST_ACK} = Response
Case Stage EQ 'FWI'
{FWI_INST_ACK} = Response
Case Stage EQ 'LWI'
{LWI_INST_ACK} = Response
Case Stage EQ 'QA'
{QA_INST_ACK} = Response
Case Stage EQ 'LOAD'
{LOAD_INST_ACK} = Response
Case Stage EQ 'UNLOAD'
{UNLOAD_INST_ACK} = Response
Case Stage EQ 'POST'
{POST_INST_ACK} = Response
End Case
Database_Services('WriteDataRow', 'RDS', RDSNo, @Record, True$, False$, True$)
end service
Service CopyRDSLayerParameters(RDSNo)
If (RDSNo NE '') then
RunOrderNo = Xlate('RDS', RDSNo, 'RUN_ORDER_NUM', 'X')
If (RunOrderNo GT 1) then
PrevRunNo = RunOrderNo - 1
WONo = Xlate('RDS', RDSNo, 'WO', 'X')
CopyWOMatKey = WONo:'*':PrevRunNo
CopyRDSNo = Xlate('WO_MAT', CopyWOMatKey, 'RDS_NO', 'X')
// Get RDSLayer keys -> copy tool parameters to each layer
CopyRDSLayerKeys = Xlate('RDS', CopyRDSNo, 'RDS_LAYER_KEYS', 'X')
If CopyRDSLayerKeys NE '' then
For each CopyRDSLayerKey in CopyRDSLayerKeys
// Copy RDS layer records
LayerID = Field(CopyRDSLayerKey, '*', 2)
DestRDSLayerKey = RDSNo:'*':LayerID
CopyRDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', CopyRDSLayerKey)
DestRDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', DestRDSLayerKey)
DestRDSLayerRec<RDS_LAYER_DOPANT$> = CopyRDSLayerRec<RDS_LAYER_DOPANT$>
DestRDSLayerRec<RDS_LAYER_EPI_DILUENT$> = CopyRDSLayerRec<RDS_LAYER_EPI_DILUENT$>
DestRDSLayerRec<RDS_LAYER_EPI_TIME$> = CopyRDSLayerRec<RDS_LAYER_EPI_TIME$>
DestRDSLayerRec<RDS_LAYER_DILUENT_ADJ_PARAM$> = CopyRDSLayerRec<RDS_LAYER_DILUENT_ADJ_PARAM$>
DestRDSLayerRec<RDS_LAYER_DOPANT_FLOW$> = CopyRDSLayerRec<RDS_LAYER_DOPANT_FLOW$>
DestRDSLayerRec<RDS_LAYER_HCL_FLOW$> = CopyRDSLayerRec<RDS_LAYER_HCL_FLOW$>
DestRDSLayerRec<RDS_LAYER_BAKE_TIME$> = CopyRDSLayerRec<RDS_LAYER_BAKE_TIME$>
DestRDSLayerRec<RDS_LAYER_EPI_H2_FLOW$> = CopyRDSLayerRec<RDS_LAYER_EPI_H2_FLOW$>
DestRDSLayerRec<RDS_LAYER_TCS_FLOW$> = CopyRDSLayerRec<RDS_LAYER_TCS_FLOW$>
DestRDSLayerRec<RDS_LAYER_DCS_FLOW$> = CopyRDSLayerRec<RDS_LAYER_DCS_FLOW$>
DestRDSLayerRec<RDS_LAYER_AUX1$> = CopyRDSLayerRec<RDS_LAYER_AUX1$>
DestRDSLayerRec<RDS_LAYER_AUX2$> = CopyRDSLayerRec<RDS_LAYER_AUX2$>
DestRDSLayerRec<RDS_LAYER_F_OFFSET$> = CopyRDSLayerRec<RDS_LAYER_F_OFFSET$>
DestRDSLayerRec<RDS_LAYER_S_OFFSET$> = CopyRDSLayerRec<RDS_LAYER_S_OFFSET$>
DestRDSLayerRec<RDS_LAYER_R_OFFSET$> = CopyRDSLayerRec<RDS_LAYER_R_OFFSET$>
DestRDSLayerRec<RDS_LAYER_ETCH1$> = CopyRDSLayerRec<RDS_LAYER_ETCH1$>
DestRDSLayerRec<RDS_LAYER_ETCH2$> = CopyRDSLayerRec<RDS_LAYER_ETCH2$>
DestRDSLayerRec<RDS_LAYER_ETCH3$> = CopyRDSLayerRec<RDS_LAYER_ETCH3$>
DestRDSLayerRec<RDS_LAYER_OVERGROW_REQ$> = CopyRDSLayerRec<RDS_LAYER_OVERGROW_REQ$>
DestRDSLayerRec<RDS_LAYER_SUSC_ETCH$> = CopyRDSLayerRec<RDS_LAYER_SUSC_ETCH$>
DestRDSLayerRec<RDS_LAYER_UL_TEMP$> = CopyRDSLayerRec<RDS_LAYER_UL_TEMP$>
DestRDSLayerRec<RDS_LAYER_MODIFY_USER$, -1> = 'CopyService'
DestRDSLayerRec<RDS_LAYER_MODIFY_DTM$, -1> = DateTime()
Database_Services('WriteDataRow', 'RDS_LAYER', DestRDSLayerKey, DestRDSLayerRec, True$, True$, True$)
Next CopyRDSLayerKey
end
end else
Error_Services('Add', 'No previous run to copy RDS layer parameters from in ':Service:' service.')
end
end else
Error_Services('Add', 'RDSNo not supplied in ':Service:' service.')
end
end service
Service RemovePocketNCR(RDSNo, Pocket)
If ( (RDSNo NE '') and (Pocket NE '') ) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
If Error_Services('NoError') then
RDSRec<RDS_OUT_NCR$, Pocket> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec)
end
end
end service
Service AddPocketNCR(RDSNo, Pocket, NCRNo)
If ( (RDSNo NE '') and (Pocket NE '') and (NCRNo NE '') ) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
If Error_Services('NoError') then
RDSRec<RDS_OUT_NCR$, Pocket> = NCRNo
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec)
end
end
end service
Service ConvertRecordToJSON(KeyID, Record, itemURL)
jsonRecord = ''
If KeyID NE '' then
If Record EQ '' then Record = Database_Services('ReadDataRow', 'RDS', KeyID)
If Error_Services('NoError') then
@DICT = Database_Services('GetTableHandle', 'DICT.RDS')
@ID = KeyID
@RECORD = Record
If SRP_JSON(objJSON, 'New', 'Object') then
If SRP_JSON(objRDS, 'New', 'Object') then
WOMatKey = {WO_MAT_KEY}
SAPBatchNo = Database_Services('ReadDataColumn', 'WO_MAT', WOMatKey, WO_MAT_SAP_BATCH_NO$, True$, 0, False$)
SRP_JSON(objRDS, 'SetValue', 'keyId', @ID)
SRP_JSON(objRDS, 'SetValue', 'reactor', {REACTOR})
SRP_JSON(objRDS, 'SetValue', 'workOrder', {WO})
SRP_JSON(objRDS, 'SetValue', 'cassNo', {CASS_NO})
SRP_JSON(objRDS, 'SetValue', 'combStatus', {COMB_STATUS})
SRP_JSON(objRDS, 'SetValue', 'partNo', {PART_NUM})
SRP_JSON(objRDS, 'SetValue', 'PSN', {PROD_SPEC_ID})
SRP_JSON(objRDS, 'SetValue', 'cassNo', {CASS_NO})
SRP_JSON(objRDS, 'SetValue', 'entryId', {ENTRY_ID})
SRP_JSON(objRDS, 'SetValue', 'entryDtm', Trim(OConv({ENTRY_DATE}, 'D4/H'):' ':OConv({ENTRY_TIME}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'preEpiSig', {PRE_EPI_SIG})
SRP_JSON(objRDS, 'SetValue', 'preEpiSigDtm', Trim(OConv({PRE_EPI_SIG_DATE}, 'D4/H'):' ':OConv({PRE_EPI_SIG_TIME}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'operatorIn', {OPERATOR_IN})
SRP_JSON(objRDS, 'SetValue', 'dtmIn', Trim(OConv({DATE_IN}, 'D4/H'):' ':OConv({TIME_IN}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'operatorOut', {OPERATOR_OUT})
SRP_JSON(objRDS, 'SetValue', 'dtmOut', Trim(OConv({DATE_OUT}, 'D4/H'):' ':OConv({TIME_OUT}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'postEpiSig', {POST_EPI_SIG})
SRP_JSON(objRDS, 'SetValue', 'postEpiSigDtm', Trim(OConv({POST_EPI_SIG_DATE}, 'D4/H'):' ':OConv({POST_EPI_SIG_TIME}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'SapBatchNo', SAPBatchNo)
SAPTxDtm = Xlate('WO_MAT', {WO_MAT_KEY}, 'SAP_TX_DTM', 'X')
SRP_JSON(objRDS, 'SetValue', 'sapTxDtm', Trim(OConv(SAPTxDtm, 'DT2/^H')))
SRP_JSON(objRDS, 'SetValue', 'supVerSig', {SUP_VER_SIG})
SRP_JSON(objRDS, 'SetValue', 'supVerSigDtm', Trim(OConv({SUP_VER_SIG_DATE}, 'D4/H'):' ':OConv({SUP_VER_SIG_TIME}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'shipDtm', Trim(OConv({SHIP_DATE}, 'D4/H'):' ':OConv({SHIP_TIME}, 'MTHS')))
SRP_JSON(objRDS, 'SetValue', 'subPartNo', {SUB_PART_NO})
SRP_JSON(objRDS, 'SetValue', 'shipNo', {SHIP_NO})
SRP_JSON(objRDS, 'SetValue', 'cassWaferQty', {CASS_WAFER_QTY})
SRP_JSON(objRDS, 'SetValue', 'loadLockSide', {LOAD_LOCK_SIDE})
SRP_JSON(objRDS, 'SetValue', 'waferSize', {WAFER_SIZE})
SRP_JSON(objRDS, 'SetValue', 'reactorType', {REACTOR_TYPE})
CurrWfrCnt = Xlate('WO_MAT', {WO_MAT_KEY}, 'CURR_WFR_CNT', 'X')
SRP_JSON(objRDS, 'SetValue', 'CURR_WFR_CNT', CurrWfrCnt)
CustNo = Database_Services('ReadDataColumn', 'WO_LOG', {WO}, WO_LOG_CUST_NO$, True$, 0, False$)
CustReshipNo = Database_Services('ReadDataColumn', 'WO_MAT', {WO_MAT_KEY}, WO_MAT_RESHIP_CUST_NO$, True$, 0, False$)
If CustReshipNo NE '' then
CustNo = CustReshipNo
end
CustName = Database_Services('ReadDataColumn', 'COMPANY', CustNo, COMPANY_CO_NAME$, True$, 0, False$)
CustAbbrev = Database_Services('ReadDataColumn', 'COMPANY', CustNo, COMPANY_ABBREV$, True$, 0, False$)
SRP_JSON(objRDS, 'SetValue', 'CustNo', CustNo)
SRP_JSON(objRDS, 'SetValue', 'CustName', CustName)
SRP_JSON(objRDS, 'SetValue', 'CustAbbrev', CustAbbrev)
// Save system variables
AtID = @ID
AtRecord = @Record
AtDict = @Dict
// Add a PSN object
ProdSpecJSON = PSN_Services('ConvertRecordToJSON', {PROD_SPEC_ID})
If SRP_JSON(objProdSpecResponse, 'Parse', ProdSpecJSON) EQ '' then
objProdSpec = SRP_JSON(objProdSpecResponse, 'Get', 'prodSpec')
SRP_JSON(objRDS, 'Set', 'prodSpec', objProdSpec)
SRP_JSON(objProdSpec, 'Release')
SRP_JSON(objProdSpecResponse, 'Release')
end
// Restore system variables
@ID = AtID
@Record = AtRecord
@Dict = AtDict
// Add CLEAN_INSP objects
CINos = ''
CINos<0, -1> = {PRE_CI_NO}
CINos<0, -1> = {FWI_CI_NO}
CINos<0, -1> = {LWI_CI_NO}
CINos<0, -1> = {POST_CI_NO}
If CINos NE '' then
If SRP_JSON(objCleanInspArray, 'New', 'Array') then
For each CINo in CINos using @VM setting vPos
If CINo NE '' then
CleanInspJSON = Clean_Insp_Services('ConvertRecordToJSON', CINo)
If SRP_JSON(objCleanInsp, 'Parse', CleanInspJSON) EQ '' then
objTemp = SRP_JSON(objCleanInsp, 'Get', 'cleanInsp')
SRP_JSON(objCleanInspArray, 'Add', objTemp)
SRP_JSON(objTemp, 'Release')
SRP_JSON(objCleanInsp, 'Release')
end
end
Next CINo
SRP_JSON(objRDS, 'Set', 'cleanInsp', objCleanInspArray)
SRP_JSON(objCleanInspArray, 'Release')
end
end
// Save system variables
// Restore system variables
@ID = AtID
@Record = AtRecord
@Dict = AtDict
AtID = @ID
AtRecord = @Record
AtDict = @Dict
If RowExists('WO_MAT_QA', WOMatKey) then
// Add WO_MAT_QA object
WOMatQAJSON = WO_Mat_QA_Services('ConvertRecordToJSON', WOMatKey)
If SRP_JSON(objWOMatQA, 'Parse', WOMatQAJSON) EQ '' then
objTemp = SRP_JSON(objWOMatQA, 'Get', 'woMatQa')
SRP_JSON(objRDS, 'Set', 'woMatQA', objTemp)
SRP_JSON(objTemp, 'Release')
SRP_JSON(objWOMatQA, 'Release')
end
end else
If SRP_JSON(objWOMatQA, 'New', 'Object') then
SRP_JSON(objRDS, 'Set', 'woMatQA', objWOMatQA)
SRP_JSON(objWOMatQA, 'Release')
end
end
// Restore system variables
@ID = AtID
@Record = AtRecord
@Dict = AtDict
If SRP_JSON(objRDSLayerArray, 'New', 'Array') then
RDSLayerKeys = {RDS_LAYER_KEYS}
For each RDSLayerKey in RDSLayerKeys using @VM setting vPos
//If SRP_JSON(objRDSLayer, 'New', 'Object') then
//SRP_JSON(objRDSLayer, 'SetValue', 'keyId', RDSLayerKey)
//SRP_JSON(objRDSLayerArray, 'Add', objRDSLayer)
rdsLayerJson = Rds_Layer_Services('ConvertRecordToJSON', RDSLayerKey)
If SRP_Json(objTempHandle, 'Parse', rdsLayerJson) EQ '' then
SRP_JSON(objRDSLayerArray, 'Add', objTempHandle)
SRP_JSON(objTempHandle, 'Release')
end
//SRP_JSON(objRDSLayer, 'Release')
//end
Next RDSLayerKey
//SRP_JSON(objRDS, 'Set', 'rdsLayerIds', objRDSLayerArray)
SRP_JSON(objRDS, 'Set', 'rdsLayers', objRDSLayerArray)
SRP_JSON(objRDSLayerArray, 'Release')
end
AllRTFRecords = Return_To_Fab_Services('GetReturnToFabRecordIdByCassId', KeyID)
If AllRTFRecords NE '' then
objRTFRecords = ''
If SRP_JSON(objRTFRecords, 'New', 'Array') then
For each RTFRecordId in AllRTFRecords using @VM setting vPos
objRTF = ''
If SRP_JSON(objRTF, 'New', 'Object') then
RTFRecord = Database_Services('ReadDataRow', 'RETURN_TO_FAB_LOTS', RTFRecordId, True$, 0, False$)
SRP_JSON(objRTF, 'SetValue', 'ReturnToFabLotsId', RTFRecordId)
SRP_JSON(objRTF, 'SetValue', 'StartDtm', OConv(RTFRecord<RETURN_TO_FAB_LOTS_MH_INIT_DTM$>, 'DT'))
SRP_JSON(objRTF, 'SetValue', 'Completed', RTFRecord<RETURN_TO_FAB_LOTS_COMPLETED$>, 'Boolean')
SRP_JSON(objRTFRecords, 'Set', 'ReturnToFabRecord', objRTF)
SRP_JSON(objRTFRecords, 'Add', objRTF)
SRP_JSON(objRTF, 'Release')
end
Next RTFRecordId
SRP_JSON(objRDS, 'Set', 'ReturnToFabRecords', objRTFRecords)
SRP_JSON(objRTFRecords, 'Release')
end
end else
SRP_JSON(objRDS, 'SetValue', 'ReturnToFabRecords', '')
end
SRP_JSON(objJSON, 'Set', 'rds', objRDS)
SRP_JSON(objRDS, 'Release')
end
If itemURL NE '' then
// The itemURL was passed in so add HAL+JSON properties.
// Create the _links property and then all link objects needed for this resource.
If SRP_JSON(objLinks, 'New', 'Object') then
// Create a self link.
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(objJSON, 'Set', '_links', objLinks)
SRP_JSON(objLinks, 'Release')
end
// Create the _class property for this resource.
SRP_JSON(objJSON, 'SetValue', '_class', 'resource')
end
jsonRecord = SRP_JSON(objJSON, 'Stringify', 'Styled')
SRP_JSON(objJSON, 'Release')
end else
Error_Services('Add', 'Unable to create JSON representation in the ' : Service : ' service.')
end
end
end else
Error_Services('Add', 'KeyID argument was missing in the ' : Service : ' service.')
end
Response = jsonRecord
end service
Service GetRDSMoves(ReportDTM)
DatesToSearch = ''
ReportDTM = FIELD(ReportDTM, ' ', 1)
query = 'SELECT RDS WITH DATE_OUT EQ ': QUOTE(ReportDTM)
Set_Status(0)
RList(query, TARGET_ACTIVELIST$, "", "", "")
IF Get_Status(errCode) THEN
ErrMsg(errCode)
RETURN
END
RDSList = ''
IF @RecCount then
EoF = 0
NumKeys = @RecCount
Cnt = 0
Loop
ReadNext RDSKey Else EoF = 1
until EoF
RDSList<-1> = RDSKey
Repeat
end
GoSub ClearCursors
Response = RDSList
end service
Service SignUnloadExtra1(RDSNo, LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
UnloadExtra1Ready = Qa_Services('UnloadExtra1stReady', RDSNo)
If UnloadExtra1Ready then
RDSRec<RDS_OP_OUT_EX1$> = LSLUsername
RDSRec<RDS_OP_OUT_EX1_DATE$> = SRP_Date('Today')
RDSRec<RDS_OP_OUT_EX1_TIME$> = SRP_Time('Now')
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Unload Extra 1 Signed from Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('RemoveRDSFromReactorLoad', RDSNo, Reactor, LSLUserName)
end else
Error_Services('Add', 'Unload Extra 1 is not able to be signed at this stage')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Sign Unload Extra 1 routine')
end
end service
Service UnsignUnloadExtra1(RDSNo, LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
Reactor = RDSRec<RDS_REACTOR$>
If Reactor NE '' then
CurrReactorLoadCapacity = Reactor_Services('GetReactorAvailChamberCount', Reactor)
If CurrReactorLoadCapacity GT 0 then
UnsignUnloadExtra1Ready = Qa_Services('UnsignUnloadExtra1stReady', RDSNo)
if UnsignUnloadExtra1Ready then
RDSRec<RDS_OP_OUT_EX1$> = ''
RDSRec<RDS_OP_OUT_EX1_DATE$> = ''
RDSRec<RDS_OP_OUT_EX1_TIME$> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Unload Extra 1 Unsigned on Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('AddRDSToReactorLoad', RDSNo, Reactor)
end else
Error_Services('Add', 'Unsign Load Extra 1 is not able to be unsigned.')
end
end else
Error_Services('Add', 'Reactor #' : Reactor : ' does not currently have the capacity to be loaded. Unload a lot to allow.')
end
end else
Error_Services('Add', 'RDS is not assigned to a reactor.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Unsign Load Extra 1 routine')
end
end service
Service SignLoadExtra1(RDSNo,LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
Reactor = RDSRec<RDS_REACTOR$>
If Reactor NE '' then
CurrReactorLoadCapacity = Reactor_Services('GetReactorAvailChamberCount', Reactor)
If CurrReactorLoadCapacity GT 0 then
LoadExtra1Ready = Qa_Services('LoadExtra1stReady', RDSNo)
If LoadExtra1Ready then
RDSRec<RDS_OP_IN_EX2$> = LSLUsername
RDSRec<RDS_OP_IN_EX2_DATE$> = SRP_Date('Today')
RDSRec<RDS_OP_IN_EX2_TIME$> = SRP_Time('Now')
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Load Extra 1 Signed to Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('AddRDSToReactorLoad', RDSNo, Reactor)
end else
Error_Services('Add', 'Load Extra 1 is not able to be signed at this stage')
end
end else
Error_Services('Add', 'Reactor #' : Reactor : ' does not currently have the capacity to be loaded. Unload a lot to allow.')
end
end else
Error_Services('Add', 'RDS is not assigned to a reactor.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Sign Unload Extra 1 routine')
end
end service
Service UnsignLoadExtra1(RDSNo, LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
UnsignLoadExtra1Ready = Qa_Services('UnsignLoadExtra1stReady', RDSNo)
if UnsignLoadExtra1Ready then
RDSRec<RDS_OP_IN_EX2$> = ''
RDSRec<RDS_OP_IN_EX2_DATE$> = ''
RDSRec<RDS_OP_IN_EX2_TIME$> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Load Extra 1 Unsigned on Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('RemoveRDSFromReactorLoad', RDSNo, Reactor, LSLUserName)
end else
Error_Services('Add', 'Unsign Load Extra 1 is not able to be unsigned.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Unsign Load Extra 1 routine')
end
end service
Service SignUnloadExtra2(RDSNo,LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
UnloadExtra2ndReady = Qa_Services('UnloadExtra2ndReady', RDSNo)
If UnloadExtra2ndReady then
RDSRec<RDS_OP_OUT_EX2$> = LSLUsername
RDSRec<RDS_OP_OUT_EX2_DATE$> = SRP_Date('Today')
RDSRec<RDS_OP_OUT_EX2_TIME$> = SRP_Time('Now')
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Unload Extra 2 Signed from Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('RemoveRDSFromReactorLoad', RDSNo, Reactor, LSLUserName)
end else
Error_Services('Add', 'Unload Extra 2 is not able to be signed at this stage')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Sign Unload Extra 1 routine')
end
end service
Service UnsignUnloadExtra2(RDSNo, LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
Reactor = RDSRec<RDS_REACTOR$>
If Reactor NE '' then
CurrReactorLoadCapacity = Reactor_Services('GetReactorAvailChamberCount', Reactor)
If CurrReactorLoadCapacity GT 0 then
UnsignUnloadExtra2Ready = Qa_Services('UnsignUnloadExtra2ndReady', RDSNo)
if UnsignUnloadExtra2Ready then
RDSRec<RDS_OP_OUT_EX2$> = ''
RDSRec<RDS_OP_OUT_EX2_DATE$> = ''
RDSRec<RDS_OP_OUT_EX2_TIME$> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Unload Extra 2 Unsigned on Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('AddRDSToReactorLoad', RDSNo, Reactor)
end else
Error_Services('Add', 'Unsign Load Extra 2 is not able to be unsigned.')
end
end else
Error_Services('Add', 'Reactor #' : Reactor : ' does not currently have the capacity to be loaded. Unload a lot to allow.')
end
end else
Error_Services('Add', 'RDS is not assigned to a reactor.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Unsign Unload Extra 1 routine')
end
end service
Service SignLoadExtra2(RDSNo,LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
Reactor = RDSRec<RDS_REACTOR$>
If Reactor NE '' then
CurrReactorLoadCapacity = Reactor_Services('GetReactorAvailChamberCount', Reactor)
If CurrReactorLoadCapacity GT 0 then
LoadExtra2Ready = Qa_Services('LoadExtra2ndReady', RDSNo)
if LoadExtra2Ready then
RDSRec<RDS_OP_IN_EX3$> = LSLUsername
RDSRec<RDS_OP_IN_EX3_DATE$> = SRP_Date('Today')
RDSRec<RDS_OP_IN_EX3_TIME$> = SRP_Time('Now')
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Load Extra 2 Signed to Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('AddRDSToReactorLoad', RDSNo, Reactor)
end else
Error_Services('Add', 'Load Extra 2 is not able to be signed at this stage')
end
end else
Error_Services('Add', 'Reactor #' : Reactor : ' does not currently have the capacity to be loaded. Unload a lot to allow.')
end
end else
Error_Services('Add', 'RDS is not assigned to a reactor.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Sign Unload Extra 1 routine')
end
end service
Service UnsignLoadExtra2(RDSNo, LSLUserName)
IF LSLUserName NE '' AND RowExists('LSL_USERS', LSLUserName) then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
UnsignLoadExtra2Ready = Qa_Services('UnsignLoadExtra2ndReady', RDSNo)
if UnsignLoadExtra2Ready then
RDSRec<RDS_OP_IN_EX3$> = ''
RDSRec<RDS_OP_IN_EX3_DATE$> = ''
RDSRec<RDS_OP_IN_EX3_TIME$> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, True$)
Reactor = RDSRec<RDS_REACTOR$>
If Error_Services('NoError') then
Rds_Services('AddComment', RDSNo, 'Load Extra 2 Unsigned on Reactor ' : Reactor, LSLUserName)
end
Reactor_Services('RemoveRDSFromReactorLoad', RDSNo, Reactor, LSLUserName)
end else
Error_Services('Add', 'Unsign Load Extra 2 is not able to be unsigned.')
end
end else
Error_Services('Add', 'RDS ' : RDSNo : ' does not exist.')
end
end else
Error_Services('Add', 'Invalid user passed to Unsign Unload Extra 1 routine')
end
end service
Service ApplyAbortMetrology(RdsKeys)
Result = False$
ErrorMsg = ''
If RdsKeys NE '' then
Convert @VM to @FM in RdsKeys
If RowExists('RDS', RdsKeys) then
For each RdsKey in RdsKeys using @FM
WoNo = Xlate('RDS', RdsKey, RDS_WO$, 'X')
// Set a flag on the CI record indicating the run was aborted
CleanInspKey = Xlate('RDS', RdsKey, 'LWI_CI_NO', 'X')
CIRec = Database_Services('ReadDataRow', 'CLEAN_INSP', CleanInspKey)
CIRec<CLEAN_INSP_WAFERS_REMOVED$> = True$
Database_Services('WriteDataRow', 'CLEAN_INSP', CleanInspKey, CIRec, True$, False$, False$)
If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
If ErrorMsg EQ '' then
// Change the QA metrology requirements to all wafers
CassNo = Xlate('RDS', RdsKey, 'CASS_NO', 'X')
WoMatQaKey = WoNo : '*' : CassNo
WoMatQaRec = Xlate('WO_MAT_QA', WoMatQaKey, '', 'X')
WoWaferQty = Xlate('WO_MAT', WoMatQaKey, WO_MAT_WAFER_QTY$, 'X')
WoMatQaStages = WoMatQaRec<WO_MAT_QA_STAGE$>
WoMatQaProfiles = WoMatQaRec<WO_MAT_QA_PROFILE$>
WoMatQaSlots = WoMatQaRec<WO_MAT_QA_SLOT$>
WoMatQaWfrQtys = WoMatQaRec<WO_MAT_QA_WFR_QTY$>
WoMatQaProps = WoMatQaRec<WO_MAT_QA_PROP$>
WoMatQaToolClasses = WoMatQaRec<WO_MAT_QA_TOOL_CLASS$>
WoMatQaRecipes = WoMatQaRec<WO_MAT_QA_RECIPE$>
WoMatQaRecipePatterns = WoMatQaRec<WO_MAT_QA_RECIPE_PATTERN$>
WoMatQaMin = WoMatQaRec<WO_MAT_QA_MIN$>
WoMatQaMax = WoMatQaRec<WO_MAT_QA_MAX$>
WoMatQaOOS = WoMatQaRec<WO_MAT_QA_OUT_OF_SPEC$>
StageCount = DCount(WoMatQaStages, @VM)
For stageIdx = 1 to StageCount
If (WoMatQaStages<0, stageIdx> _EQC 'QA') and (WoMatQaProfiles<0, stageIdx> _EQC '1ADE') then
Slot = WoMatQaSlots<0, stageIdx>
If (Slot _NEC 'L') then
WoMatQaSlots<0, stageIdx> = 'A'
WoMatQaWfrQtys<0, stageIdx> = WoWaferQty
end
If (Slot _EQC 'L') then
WoMatQaStages<0, stageIdx> = ''
WoMatQaProfiles<0, stageIdx> = ''
WoMatQaSlots<0, stageIdx> = ''
WoMatQaWfrQtys<0, stageIdx> = ''
WoMatQaProps<0, stageIdx> = ''
WoMatQaToolClasses<0, stageIdx> = ''
WoMatQaRecipes<0, stageIdx> = ''
WoMatQaRecipePatterns<0, stageIdx> = ''
WoMatQaMin<0, stageIdx> = ''
WoMatQaMax<0, stageIdx> = ''
WoMatQaOOS<0, stageIdx> = ''
end
end
Next stageIdx
WoMatQaRec<WO_MAT_QA_STAGE$> = WoMatQaStages
WoMatQaRec<WO_MAT_QA_PROFILE$> = WoMatQaProfiles
WoMatQaRec<WO_MAT_QA_SLOT$> = WoMatQaSlots
WoMatQaRec<WO_MAT_QA_WFR_QTY$> = WoMatQaWfrQtys
WoMatQaRec<WO_MAT_QA_PROP$> = WoMatQaProps
WoMatQaRec<WO_MAT_QA_TOOL_CLASS$> = WoMatQaToolClasses
WoMatQaRec<WO_MAT_QA_RECIPE$> = WoMatQaRecipes
WoMatQaRec<WO_MAT_QA_RECIPE_PATTERN$> = WoMatQaRecipePatterns
WoMatQaRec<WO_MAT_QA_MIN$> = WoMatQaMin
WoMatQaRec<WO_MAT_QA_MAX$> = WoMatQaMax
WoMatQaRec<WO_MAT_QA_OUT_OF_SPEC$> = WoMatQaOOS
Database_Services('WriteDataRow', 'WO_MAT_QA', WoMatQaKey, WoMatQaRec, True$, False$, False$)
If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
end
Next RdsKey
end else
Convert @FM to ',' in RdsKeys
ErrorMsg = 'Error in ':Service:' service. One or more Rds records (':RdsKeys:') do not exist!'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null RdsKeys passed into service!'
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end else
Result = True$
end
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ClearCursors:
For counter = 0 to 8
ClearSelect counter
Next counter
return