Implemented suggested changes and added extra error checking

This commit is contained in:
Infineon\Ouellette
2025-08-27 11:51:15 -07:00
parent d61ae234c9
commit 2eff7c5a37
4 changed files with 549 additions and 560 deletions

View File

@ -199,6 +199,7 @@ Refresh:
RDSNo = Get_Property(@Window : '.EDL_RDS', 'TEXT') RDSNo = Get_Property(@Window : '.EDL_RDS', 'TEXT')
If RowExists('RDS', RDSNo) then If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
if Error_Services('NoError') then
UnloadSigned = RDSRec<RDS_OPERATOR_OUT$> UnloadSigned = RDSRec<RDS_OPERATOR_OUT$>
ReactorNo = RDSRec<RDS_REACTOR$> ReactorNo = RDSRec<RDS_REACTOR$>
//Unload Extra 1 //Unload Extra 1
@ -282,6 +283,10 @@ Refresh:
Set_Property(@Window : '.PUB_SIGN_LOAD_EX_2', 'ENABLED', True$) Set_Property(@Window : '.PUB_SIGN_LOAD_EX_2', 'ENABLED', True$)
Set_Property(@Window : '.PUB_CLEAR_LOAD_EX_2', 'ENABLED', False$) Set_Property(@Window : '.PUB_CLEAR_LOAD_EX_2', 'ENABLED', False$)
end end
end else
Msg(@Window, 'Error reading RDS record from database.')
end
end else end else
ResponseValue = Set_Property(@Window, '@responsevalue', 0) ResponseValue = Set_Property(@Window, '@responsevalue', 0)
Post_Event(@Window, 'CLOSE') Post_Event(@Window, 'CLOSE')
@ -289,12 +294,11 @@ Refresh:
return return
ReactorChange: ReactorChange:
RDSNo = Get_Property(@Window : '.EDL_RDS', 'TEXT') RDSNo = Get_Property(@Window : '.EDL_RDS', 'TEXT')
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
if Error_Services('NoError') then
WONo = RDSRec<RDS_WO$> WONo = RDSRec<RDS_WO$>
ReactorNo = '' ReactorNo = ''
LLChosen = '' LLChosen = ''
@ -315,7 +319,7 @@ ReactorChange:
PickPlace = Xlate('REACTOR', ReactorNo, 'PICK_PLACE', 'X') PickPlace = Xlate('REACTOR', ReactorNo, 'PICK_PLACE', 'X')
If (Reactor_Services('GetReactorAvailChamberCount', ReactorNo) NE 0) OR (PickPlace EQ False$) then If (Reactor_Services('GetReactorAvailChamberCount', ReactorNo) NE 0) OR (PickPlace EQ False$) then
Query = 'SELECT REACT_STATE WITH SCHED_WO CONTAINING ':WONo Query = 'SELECT REACT_STATE WITH SCHED_WO CONTAINING ':WONo
ClearSelect GoSub ClearCursors
Set_Status(0) Set_Status(0)
RList(Query, TARGET_ACTIVELIST$, '', '' '') RList(Query, TARGET_ACTIVELIST$, '', '' '')
SchedReactors = '' SchedReactors = ''
@ -378,12 +382,27 @@ ReactorChange:
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, False$) Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, False$)
If Error_Services('NoError') then If Error_Services('NoError') then
Msg(@Window, 'Reactor successfully changed!') Msg(@Window, 'Reactor successfully changed!')
end else
Msg(@Window, 'Error changing reactor!')
end end
end end
end else
Msg(@Window, 'Error reading RDS from database!')
end
return
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ClearCursors:
For counter = 0 to 8
ClearSelect counter
Next counter
return return

View File

@ -2333,90 +2333,13 @@ Service UnsignLoadSignatureReady(RDSNo)
end service end service
Service UnsignLoadSignatureReady(RDSNo)
ErrorMessage = ''
UnsignEligible = True$
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo, True$, 0, False$)
If Error_Services('NoError') then
WONo = RDSRec<RDS_WO$>
CassNo = RDSRec<RDS_CASS_NO$>
WoMatKey = WONo : '*' : CassNo
If RowExists('WO_MAT', WoMatKey) then
WOMatCurrStatus = obj_WO_Mat('CurrStatus',WOMatKey)
//Cases to check for various statuses that should block unsigning the unload.
Begin Case
Case WOMatCurrStatus EQ 'HOLD'
ErrorMessage = 'Cassette is on HOLD and may not have the signature removed.'
Case Otherwise$
End Case
If ErrorMessage EQ '' then
//Check if any subsequent signature are set. If so RDS is not eligible.
UnloadExtra1Sig = RDSRec<RDS_OP_OUT_EX1$>
LoadExtra1Sig = RDSRec<RDS_OP_IN_EX2$>
UnloadExtra2Sig = RDSRec<RDS_OP_OUT_EX2$>
LoadExtra2Sig = RDSRec<RDS_OP_IN_EX3$>
UnloadSig = RDSRec<RDS_OPERATOR_OUT$>Xlate('RDS', RDSNo, 'OPERATOR_OUT', 'X')
CISigs = Xlate('RDS', RDSNo, 'LWI_CI_SIG', 'X')
swap @VM with '' in CISigs
ReactorType = XLATE('RDS', RDSNo, 'REACTOR_TYPE', 'X')
If ReactorType NE 'EPP' Then
FQASig = Xlate('RDS', RDSNo, 'SUP_VER_SIG', 'X')
end else
WMOutKey = Xlate('RDS', RDSNo, 'WM_OUT_KEY', 'X')
FQASig = Xlate('WM_OUT', WMOutKey, 'SUP_VER_SIG', 'X')
end
Begin Case
Case FQASig NE ''
ErrorMessage = 'FQA Signature is set.'
Case CISigs NE ''
ErrorMessage = 'Clean and Inspect Signatures are set.'
Case UnloadSig NE ''
ErrorMessage = 'Unload signature is set.'
Case LoadExtra2Sig NE ''
ErrorMessage = 'Load extra 2 signature is set.'
Case UnloadExtra2Sig NE ''
ErrorMessage = 'Unload extra 2 signature is set.'
Case LoadExtra1Sig NE ''
ErrorMessage = 'Load extra 1 signature is set.'
Case UnloadExtra1Sig NE ''
ErrorMessage = 'Unload extra 1 signature is set.'
End Case
end
end else
ErrorMessage = 'Unable to locate the WO_MAT record for this RDS in the WO_MAT table.'
end
end else
ErrorMessage = 'Error reading RDS Record. ' : Error_Services('GetMessage')
end
end else
ErrorMessage = 'Unable to locate RDS in the RDS Table.'
end
If ErrorMessage NE '' then
UnsignEligible = False$
ErrorMessage = 'Process Error: Unable to verify the load signature is Eligible to be unsigned: ' : ErrorMessage
Error_Services('Add', ErrorMessage)
end
Response = UnsignEligible
end service
Service LoadExtra1stReady(RDSNo) Service LoadExtra1stReady(RDSNo)
ErrorMsg = ''
Response = False$ Response = False$
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
if Error_Services('NoError') then
StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$> StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$>
UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$> UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$>
LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$> LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$>
@ -2428,7 +2351,7 @@ Service LoadExtra1stReady(RDSNo)
If Reactor NE '' then If Reactor NE '' then
WONo = RDSRec<RDS_WO$> WONo = RDSRec<RDS_WO$>
Query = 'SELECT REACT_STATE WITH SCHED_WO CONTAINING ':WONo Query = 'SELECT REACT_STATE WITH SCHED_WO CONTAINING ':WONo
ClearSelect GoSub ClearCursors
Set_Status(0) Set_Status(0)
RList(Query, TARGET_ACTIVELIST$, '', '' '') RList(Query, TARGET_ACTIVELIST$, '', '' '')
SchedReactors = '' SchedReactors = ''
@ -2439,17 +2362,23 @@ Service LoadExtra1stReady(RDSNo)
SchedReactors<0, -1> = SchedReactor SchedReactors<0, -1> = SchedReactor
Repeat Repeat
Locate Reactor in SchedReactors using @VM setting vPos else Locate Reactor in SchedReactors using @VM setting vPos then
Swap @VM with ',' in SchedReactors
ErrorMessage = 'Assigned reactor, ':Reactor:', does not equal any scheduled reactor(s), ':SchedReactors:'.'
Error_Services('Set', ErrorMessage)
Response = False$
return
end
end
If StandardLoadSignature NE '' AND UnloadExtra1Signature NE '' AND LoadExtra1Signature EQ '' And LoadExtra2Signature EQ ''AND UnloadExtra2Signature EQ '' and StandardUnloadSignature EQ '' then If StandardLoadSignature NE '' AND UnloadExtra1Signature NE '' AND LoadExtra1Signature EQ '' And LoadExtra2Signature EQ ''AND UnloadExtra2Signature EQ '' and StandardUnloadSignature EQ '' then
Response = True$ Response = True$
end else
ErrorMsg = 'RDS is not eligible to have Load Extra 1 signed.'
end
end else
Swap @VM with ',' in SchedReactors
ErrorMsg = 'Assigned reactor, ':Reactor:', does not equal any scheduled reactor(s), ':SchedReactors:'.'
end
end
end else
ErrorMsg = Error_Services('GetMessage')
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end end
end service end service
@ -2457,8 +2386,10 @@ end service
Service UnsignLoadExtra1stReady(RDSNo) Service UnsignLoadExtra1stReady(RDSNo)
ErrorMsg = ''
Response = False$ Response = False$
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
if Error_Services('NoError') then
StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$> StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$>
UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$> UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$>
LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$> LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$>
@ -2470,14 +2401,23 @@ Service UnsignLoadExtra1stReady(RDSNo)
Response = True$ Response = True$
end end
end end
end else
ErrorMsg = Error_Services('GetMessage')
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
end service end service
Service LoadExtra2ndReady(RDSNo) Service LoadExtra2ndReady(RDSNo)
ErrorMsg = ''
Response = False$ Response = False$
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
If Error_Services('NoError') then
StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$> StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$>
UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$> UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$>
LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$> LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$>
@ -2500,17 +2440,24 @@ Service LoadExtra2ndReady(RDSNo)
SchedReactors<0, -1> = SchedReactor SchedReactors<0, -1> = SchedReactor
Repeat Repeat
Locate Reactor in SchedReactors using @VM setting vPos else Locate Reactor in SchedReactors using @VM setting vPos then
Swap @VM with ',' in SchedReactors
ErrorMessage = 'Assigned reactor, ':Reactor:', does not equal any scheduled reactor(s), ':SchedReactors:'.'
Error_Services('Set', ErrorMessage)
Response = False$
return
end
end
If StandardLoadSignature NE '' AND UnloadExtra1Signature NE '' AND LoadExtra1Signature NE '' AND UnloadExtra2Signature NE '' And LoadExtra2Signature EQ '' and StandardUnloadSignature EQ '' then If StandardLoadSignature NE '' AND UnloadExtra1Signature NE '' AND LoadExtra1Signature NE '' AND UnloadExtra2Signature NE '' And LoadExtra2Signature EQ '' and StandardUnloadSignature EQ '' then
Response = True$ Response = True$
end else
ErrorMsg = 'RDS is not eligible to have the Load Extra 2 set.'
end
end else
Swap @VM with ',' in SchedReactors
ErrorMsg = 'Assigned reactor, ':Reactor:', does not equal any scheduled reactor(s), ':SchedReactors:'.'
Response = False$
end
end
end else
ErrorMsg = Error_Services('GetMessage')
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end end
end service end service
@ -2518,8 +2465,10 @@ end service
Service UnsignLoadExtra2ndReady(RDSNo) Service UnsignLoadExtra2ndReady(RDSNo)
ErrorMsg = ''
Response = False$ Response = False$
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
If Error_Services('NoError') then
StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$> StandardLoadSignature = RDSRec<RDS_OPERATOR_IN$>
UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$> UnloadExtra1Signature = RDSRec<RDS_OP_OUT_EX1$>
LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$> LoadExtra1Signature = RDSRec<RDS_OP_IN_EX2$>
@ -2531,6 +2480,13 @@ Service UnsignLoadExtra2ndReady(RDSNo)
Response = True$ Response = True$
end end
end end
end else
ErrorMsg = Error_Services('GetMessage')
end
If ErrorMsg NE '' then
Error_Services('Add', ErrorMsg)
end
end service end service
@ -3834,11 +3790,15 @@ Service UnsignPreEpiReady(RDSNo)
If UnsignLoadReady then If UnsignLoadReady then
//Check if LOAD signature is present //Check if LOAD signature is present
LoadSig = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_OPERATOR_IN$, True$, 0, False$) LoadSig = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_OPERATOR_IN$, True$, 0, False$)
If Error_Services('NoError') then
If LoadSig EQ '' then If LoadSig EQ '' then
UnsignPreEpiReady = True$ UnsignPreEpiReady = True$
end else end else
ErrorMsg = 'Load signature is set.' ErrorMsg = 'Load signature is set.'
end end
end else
ErrorMsg = Error_Services('GetMessage')
end
end else end else
ErrorMsg = 'A signature beyond pre-epi exists. Please check later stages of this RDS.' ErrorMsg = 'A signature beyond pre-epi exists. Please check later stages of this RDS.'
end end
@ -3883,3 +3843,4 @@ return

View File

@ -169,7 +169,6 @@ end event
Event PUB_SIGN.CLICK() Event PUB_SIGN.CLICK()
RDSNo = Get_Property(@WINDOW:'.RDS_NO','TEXT') RDSNo = Get_Property(@WINDOW:'.RDS_NO','TEXT')
ReactorType = Get_Property(@WINDOW:'.REACTOR_TYPE','TEXT') ReactorType = Get_Property(@WINDOW:'.REACTOR_TYPE','TEXT')
LoadLockVal = Get_Property(@WINDOW:'.LOAD_LOCK_SIDE_HIDDEN','TEXT') LoadLockVal = Get_Property(@WINDOW:'.LOAD_LOCK_SIDE_HIDDEN','TEXT')
@ -187,14 +186,15 @@ Event PUB_SIGN.CLICK()
Begin Case Begin Case
Case SignEventType EQ 'Sign' Case SignEventType EQ 'Sign'
debug
RDSNo = Get_Property(@WINDOW:'.RDS_NO','DEFPROP') RDSNo = Get_Property(@WINDOW:'.RDS_NO','DEFPROP')
WfrQty = Get_Property(@WINDOW:'.WAFERS_IN','TEXT') WfrQty = Get_Property(@WINDOW:'.WAFERS_IN','TEXT')
LLSide = Get_Property(@Window:'.LOAD_LOCK_SIDE', 'DEFPROP') LLSide = Get_Property(@Window:'.LOAD_LOCK_SIDE', 'DEFPROP')
Reactor = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_REACTOR$, True$, 0, False$) Reactor = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_REACTOR$, True$, 0, False$)
If Error_Services('NoError') then
If Reactor NE '' then If Reactor NE '' then
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor) ReactorRec = Database_Services('ReadDataRow', 'REACTOR', Reactor)
if Error_Services('NoError') then
ReactorType = ReactorRec<REACTOR_REACT_TYPE$> ReactorType = ReactorRec<REACTOR_REACT_TYPE$>
ROTREnabled = Xlate('REACTOR', Reactor, 'ENABLE_ROTR', 'X') ROTREnabled = Xlate('REACTOR', Reactor, 'ENABLE_ROTR', 'X')
@ -419,12 +419,20 @@ Event PUB_SIGN.CLICK()
ErrorMsg = Error_Services('GetMessage') ErrorMsg = Error_Services('GetMessage')
ErrMsg(ErrorMsg) ErrMsg(ErrorMsg)
end end
end else
ErrorMsg = Error_Services('GetMessage')
Msg(@Window, ErrorMsg)
end
end else end else
Msg(@Window, "Reactor load signature not allowed on a down reactor.") Msg(@Window, "Reactor load signature not allowed on a down reactor.")
end end
end else end else
Msg(@Window, "RDS is not assigned to a reactor.") Msg(@Window, "RDS is not assigned to a reactor.")
end end
end else
ErrorMsg = Error_Services('GetMessage')
Msg(@Window, ErrorMsg)
end
GoSub OLE_LL_Status GoSub OLE_LL_Status
Set_Property(@Window, 'SAVEWARN', False$) Set_Property(@Window, 'SAVEWARN', False$)
Send_Event(@Window, 'READ') Send_Event(@Window, 'READ')
@ -720,3 +728,4 @@ return

View File

@ -1925,6 +1925,9 @@ Service PushSigProfileToWoMat(RDSNo)
WOMatSigProf = obj_WO_Mat('CassSigProfile', WOMatKey) WOMatSigProf = obj_WO_Mat('CassSigProfile', WOMatKey)
WOMatSig = WOMatRec<WO_MAT_SIGNATURE$> WOMatSig = WOMatRec<WO_MAT_SIGNATURE$>
WOMatSigDTM = WOMatRec<WO_MAT_SIG_DTM$> WOMatSigDTM = WOMatRec<WO_MAT_SIG_DTM$>
WOMatSigProfOrig = WOMatSigProf
WOMatSigOrig = WOMatSig
WOMatSigDTMOrig = WOMatSigDTM
// Update WO_MAT signature profile to match for the "1VER" stage // Update WO_MAT signature profile to match for the "1VER" stage
Stage = '1VER' Stage = '1VER'
@ -1996,9 +1999,15 @@ Service PushSigProfileToWoMat(RDSNo)
WOMatSigDTM<0, vPos> = FQASigDTM WOMatSigDTM<0, vPos> = FQASigDTM
end end
If WOMatSigProf NE WOMatSigProfOrig then
Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIG_PROFILE$, WOMatSigProf) Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIG_PROFILE$, WOMatSigProf)
end
If WOMatSig NE WOMatSigOrig then
Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIGNATURE$, WOMatSig) Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIGNATURE$, WOMatSig)
end
If WOMatSigDTM NE WOMatSigDTMOrig then
Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIG_DTM$, WOMatSigDTM) Transaction_Services('PostWriteFieldTransaction', 'WO_MAT', WOMatKey, WO_MAT_SIG_DTM$, WOMatSigDTM)
end
end else end else
ErrorMsg = Error_Services('GetMessage') ErrorMsg = Error_Services('GetMessage')
@ -2364,15 +2373,14 @@ Service UnsignPreEpiSignature(RDSNo, UserId)
UnsignPreEpiReady = QA_Services('UnsignPreEpiReady', RDSNo) UnsignPreEpiReady = QA_Services('UnsignPreEpiReady', RDSNo)
if Error_Services('NoError') then if Error_Services('NoError') then
If UnsignPreEpiReady then If UnsignPreEpiReady then
Database_Services('WriteDataColumn', 'RDS', RDSNo, RDS_PRE_EPI_SIG$, '', True$, False$, False$) RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo, True$, 0, False$)
If Error_Services('NoError') then
Database_Services('WriteDataColumn', 'RDS', RDSNo, RDS_PRE_EPI_SIG_DATE$, '', True$, False$, False$)
If Error_Services('NoError') then
Database_Services('WriteDataColumn', 'RDS', RDSNo, RDS_PRE_EPI_SIG_TIME$, '', True$, False$, False$)
If Error_Services('NoError') then
Database_Services('WriteDataColumn', 'RDS', RDSNo, RDS_VERIFY_QTY$, '', True$, False$, False$)
if Error_Services('NoError') then if Error_Services('NoError') then
Database_Services('WriteDataColumn', 'RDS', RDSNo, RDS_REACTOR$, '', True$, False$, False$) RDSRec<RDS_PRE_EPI_SIG$> = ''
RDSRec<RDS_PRE_EPI_SIG_DATE$> = ''
RDSRec<RDS_PRE_EPI_SIG_TIME$> = ''
RDSRec<RDS_VERIFY_QTY$> = ''
RDSRec<RDS_REACTOR$> = ''
Database_Services('WriteDataRow', 'RDS', RDSNo, RDSRec, True$, False$, False$)
If Error_Services('NoError') then If Error_Services('NoError') then
PreEpiUnsign = True$ PreEpiUnsign = True$
end else end else
@ -2381,15 +2389,6 @@ Service UnsignPreEpiSignature(RDSNo, UserId)
end else end else
ErrorMsg = Error_Services('GetMessage') ErrorMsg = Error_Services('GetMessage')
end end
end else
ErrorMsg = 'Error clearing the RDS Pre Epi Signature Time on RDS ' : RDSNo : '.'
end
end else
ErrorMsg = 'Error clearing the RDS Pre Epi Signature Date on RDS ' : RDSNo : '.'
end
end else
ErrorMsg = 'Error clearing the RDS Pre Epi Signature on RDS ' : RDSNo : '.'
end
end else end else
ErrorMsg = 'Pre Epi is unable to be unsigned because a signature beyond pre-epi exists.' ErrorMsg = 'Pre Epi is unable to be unsigned because a signature beyond pre-epi exists.'
end end
@ -2464,3 +2463,4 @@ return