Compare commits

...

10 Commits

Author SHA1 Message Date
aaf415e62c Common IndexOf on six methods 2025-09-30 09:10:29 -07:00
af279541ae Reduced available react item part types to just ASM, HTR, and EPP to prevent validation issues. 2025-09-26 15:12:37 -07:00
2036ed3289 Fixed an issue which was preventing work orders without received material from being scheduled. 2025-09-26 13:40:16 -07:00
edd09af821 Fixed obj_Prod_Spec('GetQAMet'). Added RDS_Test_Services('UpdateRDSTestSpecs'). 2025-09-26 11:30:17 -07:00
febe660fcf Updated WEB_OI_WIZARD form to launch centered on the screen sized to 3/4 of the client area. Updated the UpdateOpenWorkOrderData service to also update all work order quantities to ensure the OPEN_QTY_STATIC is set after routing a work order. 2025-09-25 16:30:41 -07:00
245f832445 Modified UpdateQAMet service to support reactor scheduled metrology tests 2025-09-25 22:35:05 +00:00
f07e4476a7 updated schedule related services to account for voided cassettes 2025-09-24 16:00:16 -07:00
12f354dcaa commented out localhost case until a better way to determine local development is implemented 2025-09-24 10:49:59 -07:00
d2f98a342d adding in GetOIWizardBaseURL 2025-09-24 10:38:26 -07:00
b83a3fb57b Merged PR 26794: Added increased error checking in CopyRDSLayerParameters service
Added increased error checking in CopyRDSLayerParameters service
2025-09-24 17:12:27 +00:00
16 changed files with 1045 additions and 564 deletions

View File

@ -17,15 +17,15 @@
"<1,4>": "",
"<1,5>": "0",
"<1,6>": "0",
"<1,7>": "-2083",
"<1,8>": "-1097",
"<1,7>": "-1184",
"<1,8>": "-761",
"<1,9>": "OI Wizard",
"<1,10>": {
"<1,10,1>": "0x84CF0000",
"<1,10,2>": "0x100"
},
"<1,11>": {
"<1,11,1>": "0x8000",
"<1,11,1>": "0xC000",
"<1,11,2>": "0x80000000"
},
"<1,12>": "",
@ -165,7 +165,7 @@
"<1,62,1>": "0",
"<1,62,2>": "",
"<1,62,3>": "",
"<1,62,4>": "0",
"<1,62,4>": "1",
"<1,62,5>": "0",
"<1,62,6>": "0",
"<1,62,7>": "",
@ -227,10 +227,10 @@
"<1,2>": "",
"<1,3>": "WEBVIEW",
"<1,4>": "WEB_OI_WIZARD",
"<1,5>": "12",
"<1,6>": "12",
"<1,7>": "2060",
"<1,8>": "1076",
"<1,5>": "9",
"<1,6>": "8",
"<1,7>": "1167",
"<1,8>": "745",
"<1,9>": "",
"<1,10>": {
"<1,10,1>": "0x56000000",

View File

@ -43,6 +43,10 @@
"<8,3>": {
"<8,3,1>": "Update RDS Layer Parameters",
"<8,3,2>": "UPDATE_RDS_LAYER"
},
"<8,4>": {
"<8,4,1>": "Update RDS Test Specs",
"<8,4,2>": "UPDATE_RDS_TEST"
}
},
"<9>": {

View File

@ -41,16 +41,8 @@
"<8,2,2>": "High Thruput"
},
"<8,3>": {
"<8,3,1>": "K2K",
"<8,3,2>": "Kit 2000"
},
"<8,4>": {
"<8,4,1>": "EPP",
"<8,4,2>": " EpiPro"
},
"<8,5>": {
"<8,5,1>": "STD",
"<8,5,2>": "Standard"
"<8,3,1>": "EPP",
"<8,3,2>": " EpiPro"
}
},
"<9>": {

View File

@ -80,6 +80,7 @@ Service GetServer()
end service
Service IsProd()
Machine = Environment_Services('GetServer')
@ -279,6 +280,27 @@ Service GetMetrologyProductionPath()
end service
//----------------------------------------------------------------------------------------------------------------------
// GetOIWizardBaseUrl
//
// Returns the OIWizardBaseUrl.
//----------------------------------------------------------------------------------------------------------------------
Service GetOIWizardBaseUrl()
Machine = Environment_Services('GetServer')
Begin Case
Case ( (Machine _EQC 'MESTSA01EC') or (Machine _EQC 'MESTST1009') or (Machine _EQC 'MESTST1010') )
Response = 'https://mestsa008.infineon.com:50186/'
// Uncomment this case and add your hostname if testing locally.
//Case ( (Machine EQ 'ISCN5CG2430JV1') or (Machine _EQC 'MESTSA09EC') )
// Response = 'http://localhost:12009/'
Case Otherwise$
Response = 'https://messa014.infineon.com:50184/'
End Case
end service
//----------------------------------------------------------------------------------------------------------------------
// GetControlPlanProductionPath
//

View File

@ -254,6 +254,7 @@ Service GetStratus(Handle)
Result<10> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Batch'); // BatchID
Result<11> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Cassette'); // Cassette
Result<12> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].GradeMean'); // ThickAvg
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
END
ForOffset = (RecordIndex - 1) * FieldPositionIncrement;
Result<FieldPosition + ForOffset> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Slot'); // Position
@ -283,6 +284,7 @@ Service GetBioRad(Handle)
Result<8> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Layer'); // RunDataLayer
Result<9> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Zone'); // RunDataZone
Result<11> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Wafer'); // DataSlotId
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
END
ForOffset = (RecordIndex - 1) * FieldPositionIncrement;
Result<FieldPosition + ForOffset> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Position'); // Position
@ -310,6 +312,7 @@ Service GetCDE(Handle)
Result<8> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].PSN'); // PSN
Result<9> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Layer'); // RunDataLayer
Result<10> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Zone'); // RunDataZo
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
END
ForOffset = (RecordIndex - 1) * FieldPositionIncrement;
Result<FieldPosition + ForOffset> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].InferredPoint'); // Position
@ -338,6 +341,7 @@ Service GetHgCV(Handle)
Result<5> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].PSN'); // PSN
Result<8> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Wafer'); // LayerZonePair
Result<11> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Date'); // Timestamp
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
END
ForOffset = (RecordIndex - 1) * FieldPositionIncrement;
Result<FieldPosition + ForOffset> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Site'); // Position
@ -359,6 +363,7 @@ Service GetTencor(Handle)
IF RecordIndex EQ 1 THEN
Result<9> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Date'); // Timestamp
Result<10> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].HazeAverageAvg'); // HazeAvg
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
Result<28> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].RDS'); // RDSKeyID
Result<30> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].WaferRecipe'); // ScanRecipe
Result<39> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].SumOfDefectsAvg'); // SoDAvg
@ -381,6 +386,7 @@ Service GetSP1(Handle)
IF RecordIndex EQ 1 THEN
Result<9> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Date'); // Timestamp
Result<10> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].DcnHazeAvgMean'); // HazeAvg
Result<13> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].IndexOf');
Result<28> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].RDS'); // RDSKeyID
Result<30> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].Session'); // ScanRecipe
Result<3> = SRP_JSON(Handle, 'GETVALUE', 'Records[':RecordIndex:'].DcnLpdMean'); // SoDAvg

View File

@ -44,7 +44,7 @@ $insert SUPPLEMENTS_EQUATES
equ WOCust$ to 2
Declare subroutine SRP_Show_Window, Rds_Services, ErrMsg, Start_Window, Placedialog, Supplement_Services, Hold_Services
Declare subroutine Labeling_Services
Declare subroutine Labeling_Services
Declare function Database_Services, Material_Services, Rds_Services, RGB, SRP_Array, MemberOf, Supplement_Services
Declare function Hold_Services, Datetime, Printer_Select
@ -59,11 +59,11 @@ If Event EQ 'OLE' then
Transfer Param1 to Event
Transfer Param2 to Param1
Transfer Param3 to Param2
* Transfer Param4 to Param3
* Transfer Param5 to Param4
* Transfer Param6 to Param5
* Transfer Param7 to Param6
* Transfer Param8 to Param7
Transfer Param4 to Param3
Transfer Param5 to Param4
Transfer Param6 to Param5
Transfer Param7 to Param6
Transfer Param8 to Param7
end
GoToEvent Event for CtrlEntID
@ -186,78 +186,83 @@ Event PUB_ENG_OPTIONS.CLICK()
NumRows = DCount(WOMatKeys, @VM)
Begin Case
ServiceModules = ''
Services = ''
Caption = ''
Case SelOpt EQ 'CLEAN_INSP'
Caption = "Updating Clean & Insp specs for selected RDS cassettes..."
ServiceModules = 'CLEAN_INSP_SERVICES'
Services = 'UpdateAllCleanInsp'
For each Sel in SelOpt using @VM
If Sel EQ 'CLEAN_INSP' then
Caption<0, -1> = "Updating Clean & Insp specs for selected RDS cassettes..."
ServiceModules<0, -1> = 'CLEAN_INSP_SERVICES'
Services<0, -1> = 'UpdateAllCleanInsp'
end
Case SelOpt EQ 'QA_MET'
Caption = "Updating QA Metrology specs for selected RDS cassettes..."
ServiceModules = 'WO_MAT_QA_SERVICES'
Services = 'UpdateQAMet'
If SelOpt EQ 'QA_MET' then
Caption<0, -1> = "Updating QA Metrology specs for selected RDS cassettes..."
ServiceModules<0, -1> = 'WO_MAT_QA_SERVICES'
Services<0, -1> = 'UpdateQAMet'
end
Case SelOpt EQ 'UPDATE_RDS_LAYER'
Caption = "Updating RDS Layer specs for selected RDS cassettes..."
ServiceModules = 'RDS_LAYER_SERVICES'
Services = 'UpdateRDSLayerSpecs'
If SelOpt EQ 'UPDATE_RDS_LAYER' then
Caption<0, -1> = "Updating RDS Layer specs for selected RDS cassettes..."
ServiceModules<0, -1> = 'RDS_LAYER_SERVICES'
Services<0, -1> = 'UpdateRDSLayerSpecs'
end
Case SelOpt EQ 'CLEAN_INSP':@VM:'QA_MET'
Caption = "Updating Clean & Insp and QA Metrology specs for selected RDS cassettes..."
ServiceModules = 'CLEAN_INSP_SERVICES':@VM:'WO_MAT_QA_SERVICES'
Services = 'UpdateAllCleanInsp':@VM:'UpdateQAMet'
If SelOpt EQ 'UPDATE_RDS_TEST' then
Caption<0, -1> = "Updating RDS Test specs for selected RDS cassettes..."
ServiceModules<0, -1> = 'RDS_TEST_SERVICES'
Services<0, -1> = 'UpdateRDSTestSpecs'
end
Next Sel
Case SelOpt EQ 'QA_MET':@VM:'UPDATE_RDS_LAYER'
Caption = "Updating RDS Layer and QA Metrology specs for selected RDS cassettes..."
ServiceModules = 'WO_MAT_QA_SERVICES':@VM:'RDS_LAYER_SERVICES'
Services = 'UpdateQAMet':@VM:'UpdateRDSLayerSpecs'
Case SelOpt EQ 'CLEAN_INSP':@VM: 'UPDATE_RDS_LAYER'
Caption = "Updating RDS Layer and Clean & Insp specs for selected RDS cassettes..."
ServiceModules = 'CLEAN_INSP_SERVICES':@VM:'RDS_LAYER_SERVICES'
Services = 'UpdateAllCleanInsp':@VM:'UpdateRDSLayerSpecs'
Case SelOpt EQ 'CLEAN_INSP':@VM:'QA_MET':@VM: 'UPDATE_RDS_LAYER'
Caption = "Updating Clean & Insp, QA Metrology, and RDS Layer specs for selected RDS cassettes..."
ServiceModules = 'CLEAN_INSP_SERVICES':@VM:'WO_MAT_QA_SERVICES' :@VM: 'RDS_LAYER_SERVICES'
Services = 'UpdateAllCleanInsp':@VM:'UpdateQAMet' :@VM: 'UpdateRDSLayerSpecs'
End Case
Swap @VM with CRLF$ in Caption
If ServiceModules NE '' then
Def = ""
ErrorMsg = ''
Def = ''
Def<MCAPTION$> = Caption
Def<MTYPE$> = "GC"
Def<MEXTENT$> = NumRows
Def<MTEXTWIDTH$> = 600
MsgUp = Msg(@WINDOW, Def) ;* Start gas guage message
Def<MCOL$> = -2
Def<MROW$> = -2
MsgUp = Msg(@Window, Def) ;* Start gas guage message
For each WOMatKey in WOMatKeys using @VM setting vPos
Running = Msg(@WINDOW, MsgUp, vPos, MSGINSTUPDATE$) ;* Update gas guage
Running = Msg(@Window, MsgUp, vPos, MSGINSTUPDATE$) ;* Update gas guage
For each ServiceModule in ServiceModules using @VM setting sPos
Service = Services<0, sPos>
If Service = 'UpdateRDSLayerSpecs' then
If ( (Service _EQC 'UpdateRDSLayerSpecs') or (Service _EQC 'UpdateRDSTestSpecs') ) then
RDSKey = SelRDSList<4, vPos>
Ans = Function(@ServiceModule(Service, RDSKey))
end else
Ans = Function(@ServiceModule(Service, WOMatKey))
end
If Error_Services('HasError') then
Error_Services('DisplayError')
ErrorMsg = Error_Services('GetMessage')
end
Until (ErrorMsg NE '')
Next ServiceModule
Until (ErrorMsg NE '')
Next WOMatKey
Msg(@WINDOW,MsgUp) ;* Take gas guage down
Msg(@Window,MsgUp) ;* Take gas guage down
end
If Error_Services('NoError') then
Def = ""
Def = ''
Def<MCOL$> = -2
Def<MROW$> = -2
If (ErrorMsg EQ '') then
Def<MICON$> = '*'
Def<MCAPTION$> = 'Success'
Def<MTEXT$> = "Update complete!"
Def<MTYPE$> = "BO"
MsgUp = Msg(@window, Def)
Def<MTEXT$> = 'Update complete!'
end else
Def<MICON$> = 'H'
Def<MCAPTION$> = 'Update failed!'
Def<MTEXT$> = ErrorMsg
end
Def<MTYPE$> = "BO"
MsgUp = Msg(@Window, Def, 'OK')
end
end event
@ -277,7 +282,7 @@ Event PUB_ON_HOLD.CLICK()
HoldEntity = 'RDS'
HoldType = 'HOLD'
HoldData = ''
HoldData = Dialog_Box('DIALOG_HOLD',@WINDOW,Transition:@FM:@FM:HoldType)
HoldData = Dialog_Box('DIALOG_HOLD',@Window,Transition:@FM:@FM:HoldType)
If HoldData NE 'Cancel' then
GoSub GetView
Hold_Services('EnableMultipleHolds', WOMatKeys, HoldEntity, RDSKeys, 'NDW_RDS_QUERY', '', HoldData)
@ -289,7 +294,7 @@ Event PUB_ON_HOLD.CLICK()
MsgInfo<MTYPE$> = 'BNY'
MsgInfo<MTEXT$> = 'Hold Successful. Would you like to print label(s)?'
MsgInfo<MICON$> = '!'
PrintLabel = Msg(@WINDOW,MsgInfo,'')
PrintLabel = Msg(@Window,MsgInfo,'')
HoldBy = HoldData<1>
Reason = HoldData<2>
Stage = HoldData<4>
@ -333,7 +338,7 @@ Event PUB_OFF_HOLD.CLICK()
Transition = True$
HoldType = 'HOLD'
HoldData = ''
HoldData = Dialog_Box('DIALOG_HOLD',@WINDOW,Transition:@FM:@FM:HoldType)
HoldData = Dialog_Box('DIALOG_HOLD',@Window,Transition:@FM:@FM:HoldType)
If HoldData NE 'Cancel' then
GoSub GetView
Hold_Services('DisableMultipleHolds', WOMatKeys, 'RDS', RDSKeys, 'NDW_RDS_QUERY', '', HoldData)
@ -666,7 +671,7 @@ CheckSelectedForHolds:
Until HoldOnFlag EQ True$ and HoldOffFlag EQ True$
Next K
end
if MemberOf(@USER4, 'ENG_TECH') OR MemberOf(@USER4, 'LEAD') OR MemberOf(@USER4, 'SUPERVISOR') then
if MemberOf(@User4, 'ENG_TECH') OR MemberOf(@User4, 'LEAD') OR MemberOf(@User4, 'SUPERVISOR') then
// IF ANY SELECTED LOTS ARE ON HOLD, ENABLE PUB_OFF_HOLD
Set_Property(@Window:'.PUB_OFF_HOLD', 'ENABLED', HoldOffFlag)
end else

View File

@ -723,12 +723,16 @@ Event OLE_SCHEDULE.OnContextMenuClick(Item, UserData)
Description = AddEventDetails<5>
WaferQty = AddEventDetails<6>
NewApptID = Schedule_Services('AddSchedEvent', ReactorNo, WorkOrder, StartDTM, StopDTM, Description, WaferQty)
NewAppt = Schedule_Services('GetScheduleEvent', NewApptID)
If Error_Services('NoError') then
GoSub RefreshReactor
If NewApptID NE '' then
SchedRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', NewApptID)
Schedule_Services('NotifySupervisorsIfSameDayChange', SchedRec)
NewAppt = Schedule_Services('GetScheduleEvent', NewApptID)
If Error_Services('NoError') then
GoSub RefreshReactor
If NewApptID NE '' then
SchedRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', NewApptID)
Schedule_Services('NotifySupervisorsIfSameDayChange', SchedRec)
end
end else
Error_Services('DisplayError')
end
end else
Error_Services('DisplayError')

View File

@ -1221,7 +1221,6 @@ Event PUB_REM_CASS.CLICK()
WmInKeys = ''
for each CassetteToVoid in CassettesToVoid using @FM
WmInKeys<1, -1> = CassetteToVoid<1,4>
//Work_Order_Services('SignVoidWMI', WMIToVoid, @USER4)
Next CassetteToVoid
Service_Services('PostProcedure', 'WORK_ORDER_SERVICES', 'SignVoidWMI':SD$:WmInKeys:SD$:WoNo:SD$:@USER4)
If Error_Services('HasError') then
@ -1240,7 +1239,6 @@ Event PUB_REM_CASS.CLICK()
CassNo = XLATE('RDS', RDSToVoid, RDS_CASS_NO$, 'X')
WOMatKey = WONo : '*' : CassNo
WoMatKeyList<1, -1> = WoMatKey
//Work_Order_Services('SignVoidNonEPP', WOMatKey, @USER4)
If Error_Services('HasError') then
ErrorMessage = Error_Services('GetMessage')
end
@ -1332,7 +1330,7 @@ Event PUB_REM_WM_OUT.CLICK()
WmOutKeys<1, -1> = CassetteToVoid<1,3>
Until ErrorMessage NE ''
Next CassetteToVoid
Service_Services('PostProcedure', 'WORK_ORDER_SERVICES', 'SignVoidWMO':SD$:WmInKeys:SD$:WoNo:SD$:@USER4)
Service_Services('PostProcedure', 'WORK_ORDER_SERVICES', 'SignVoidWMO':SD$:WmOutKeys:SD$:WoNo:SD$:@USER4)
If Error_Services('HasError') then
ErrorMessage = Error_Services('GetMessage')
end

View File

@ -2108,5 +2108,3 @@ GetQAMet:
RETURN

View File

@ -14,7 +14,6 @@ COMPILE FUNCTION obj_WO_React(Method,Parms)
*/
DECLARE FUNCTION Get_Status, Msg, Utility, obj_Tables, NextKey, obj_Prod_Spec, obj_WO_Mat_QA, GetTickCount
Declare function Environment_Services, Database_Services
DECLARE SUBROUTINE Set_Status, Msg, obj_Tables, RList, ErrMsg, Btree.Extract, obj_WO_Mat_QA, Mona_Services
@ -70,222 +69,213 @@ RETURN Result
AddRdsNo:
* * * * * * *
StartTick = GetTickCount()
MetricName = 'AddRdsNo'
StartTick = GetTickCount()
MetricName = 'AddRdsNo'
WONo = Parms[1,@RM]
StepNo = Parms[COL2()+1,@RM]
ReactNo = Parms[COL2()+1,@RM]
RdsNo = Parms[COL2()+1,@RM]
CassNo = Parms[COL2()+1,@RM]
WONo = Parms[1,@RM]
StepNo = Parms[COL2()+1,@RM]
ReactNo = Parms[COL2()+1,@RM]
RdsNo = Parms[COL2()+1,@RM]
CassNo = Parms[COL2()+1,@RM]
IF WONo = '' THEN RETURN
IF StepNo = '' THEN RETURN
IF ReactNo = '' THEN RETURN
IF RdsNo = '' THEN RETURN
IF CassNo = '' THEN RETURN
IF WONo = '' THEN RETURN
IF StepNo = '' THEN RETURN
IF ReactNo = '' THEN RETURN
IF RdsNo = '' THEN RETURN
IF CassNo = '' THEN RETURN
WOReactKey = WONo:'*':StepNo:'*':ReactNo
otParms = 'WO_REACT':@RM:WOReactKey
WOReactRec = obj_Tables('ReadOnlyRec',otParms)
RDSNos = WOReactRec<WO_REACT_RDS_NO$>
CassNos = WOReactRec<WO_REACT_CASS_NO$>
PSNos = XLATE('WO_LOG',WoNo,'PROD_VER_STEP_PSN','X')
PSNo = PSNos<1,StepNo>
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:@RM:1) ;* * * Get Reactor Scheduled QA Metrology * * *
IF QAMetData = '' THEN RETURN ;* No reactor scheduled QA_MET specified
Start = QAMetData<COL$QA_MET_START>
Interval = QAMetData<COL$QA_MET_INTERVAL>
Stage = QAMetData<COL$QA_MET_STAGE>
MetPropCd = QAMetData<COL$QA_MET_PROP>
GOSUB BuildAllTestPos ;* Set RDSNos, Start and Interval -> returns AllTestPos
* * * Find where the the RDS being added will be in the list. * * *
LOCATE RDSNo IN WOReactRec<WO_REACT_RDS_NO$> USING @VM SETTING InsPos THEN
WOReactKey = WONo:'*':StepNo:'*':ReactNo
otParms = 'WO_REACT':@RM:WOReactKey
WOReactRec = obj_Tables('UnlockRec',otParms)
RETURN ;* RDSNo already in this list -> nothing to do.
WOReactRec = obj_Tables('ReadOnlyRec',otParms)
RDSNos = WOReactRec<WO_REACT_RDS_NO$>
CassNos = WOReactRec<WO_REACT_CASS_NO$>
END ELSE
PSNos = XLATE('WO_LOG',WoNo,'PROD_VER_STEP_PSN','X')
PSNo = PSNos<1,StepNo>
LOCATE InsPos IN AllTestPos USING @VM SETTING TrimPos ELSE Null
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:@RM:1) ;* * * Get Reactor Scheduled QA Metrology * * *
IF QAMetData = '' THEN RETURN ;* No reactor scheduled QA_MET specified
Start = QAMetData<COL$QA_MET_START>
Interval = QAMetData<COL$QA_MET_INTERVAL>
Stage = QAMetData<COL$QA_MET_STAGE>
MetPropCd = QAMetData<COL$QA_MET_PROP>
GOSUB BuildAllTestPos ;* Set RDSNos, Start and Interval -> returns AllTestPos
* * * Find where the the RDS being added will be in the list. * * *
LOCATE RDSNo IN WOReactRec<WO_REACT_RDS_NO$> USING @VM SETTING InsPos THEN
otParms = 'WO_REACT':@RM:WOReactKey
WOReactRec = obj_Tables('UnlockRec',otParms)
RETURN ;* RDSNo already in this list -> nothing to do.
END ELSE
LOCATE InsPos IN AllTestPos USING @VM SETTING TrimPos ELSE Null
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
GOSUB RemSchedQA ;* Removes unsigned QAMet from cassettes scheduled past the box being removed
END
WOReactRec = INSERT(WOReactRec,WO_REACT_RDS_NO$,InsPos,0,RDSNo)
WOReactRec = INSERT(WOReactRec,WO_REACT_CASS_NO$,InsPos,0,CassNo) ;* Inserts the passed in RDSNo & associated cassette number from the data fields
RDSNos = WOReactRec<WO_REACT_RDS_NO$> ;* List after insert
CassNos = WOReactRec<WO_REACT_CASS_NO$> ;* List after insert
* * * Now build list for cassette
GOSUB BuildAllTestPos
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
GOSUB RemSchedQA ;* Removes unsigned QAMet from cassettes scheduled past the box being removed
// Add QAMet spec data to cassettes now associated with the test
// positions after removing the RDS & Cassno from the lists
GOSUB AddSchedQA
END
otParms = FIELDSTORE(otParms,@RM,4,0,WOReactRec)
// Done with updates to the WO_REACT record
obj_Tables('WriteOnlyRec',otParms)
WOReactRec = INSERT(WOReactRec,WO_REACT_RDS_NO$,InsPos,0,RDSNo)
WOReactRec = INSERT(WOReactRec,WO_REACT_CASS_NO$,InsPos,0,CassNo) ;* Inserts the passed in RDSNo & associated cassette number from the data fields
Result = Log
RDSNos = WOReactRec<WO_REACT_RDS_NO$> ;* List after insert
CassNos = WOReactRec<WO_REACT_CASS_NO$> ;* List after insert
* * * Now build list for cassette
GOSUB BuildAllTestPos
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
GOSUB AddSchedQA ;* Add QAMet spec data to cassettes now associated with the test positions after removing the RDS & Cassno from the lists
otParms = FIELDSTORE(otParms,@RM,4,0,WOReactRec)
obj_Tables('WriteOnlyRec',otParms) ;* Done with updates to the WO_REACT record
Result = Log
EndTick = GetTickCount()
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
EndTick = GetTickCount()
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
RETURN
* * * * * * *
RemRDSNo:
* * * * * * *
StartTick = GetTickCount()
MetricName = 'RemRDSNo'
StartTick = GetTickCount()
MetricName = 'RemRDSNo'
WONo = Parms[1,@RM]
StepNo = Parms[COL2()+1,@RM]
ReactNo = Parms[COL2()+1,@RM]
RdsNo = Parms[COL2()+1,@RM]
CassNo = Parms[COL2()+1,@RM]
WONo = Parms[1,@RM]
StepNo = Parms[COL2()+1,@RM]
ReactNo = Parms[COL2()+1,@RM]
RdsNo = Parms[COL2()+1,@RM]
CassNo = Parms[COL2()+1,@RM]
IF WONo = '' THEN RETURN
IF StepNo = '' THEN RETURN
IF ReactNo = '' THEN RETURN
IF RdsNo = '' THEN RETURN
IF CassNo = '' THEN RETURN
IF WONo = '' THEN RETURN
IF StepNo = '' THEN RETURN
IF ReactNo = '' THEN RETURN
IF RdsNo = '' THEN RETURN
IF CassNo = '' THEN RETURN
WOReactKey = WONo:'*':StepNo:'*':ReactNo
WOReactKey = WONo:'*':StepNo:'*':ReactNo
otParms = 'WO_REACT':@RM:WOReactKey
// 10/12/18 Changed to ReadOnlyRec as per Francois' instructions. - djs
WOReactRec = obj_Tables('ReadOnlyRec',otParms)
otParms = 'WO_REACT':@RM:WOReactKey
RDSNos = WOReactRec<WO_REACT_RDS_NO$>
CassNos = WOReactRec<WO_REACT_CASS_NO$>
WOReactRec = obj_Tables('ReadOnlyRec',otParms)
PSNos = XLATE('WO_LOG',WoNo,'PROD_VER_STEP_PSN','X')
PSNo = PSNos<1,StepNo>
RDSNos = WOReactRec<WO_REACT_RDS_NO$>
CassNos = WOReactRec<WO_REACT_CASS_NO$>
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:@RM:1) ;* * * Get Reactor Scheduled QA Metrology * * *
PSNos = XLATE('WO_LOG',WoNo,'PROD_VER_STEP_PSN','X')
PSNo = PSNos<1,StepNo>
Start = QAMetData<COL$QA_MET_START>
Interval = QAMetData<COL$QA_MET_INTERVAL>
Stage = QAMetData<COL$QA_MET_STAGE>
MetPropCd = QAMetData<COL$QA_MET_PROP>
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:@RM:1) ;* * * Get Reactor Scheduled QA Metrology * * *
GOSUB BuildAllTestPos ;* Set RDSNos, Start and Interval -> returns AllTestPos
Start = QAMetData<COL$QA_MET_START>
Interval = QAMetData<COL$QA_MET_INTERVAL>
Stage = QAMetData<COL$QA_MET_STAGE>
MetPropCd = QAMetData<COL$QA_MET_PROP>
IF AllTestPos NE '' THEN
GOSUB BuildAllTestPos ;* Set RDSNos, Start and Interval -> returns AllTestPos
* * * Find where the the RDS being removed is in the list. * * *
IF AllTestPos NE '' THEN
LOCATE RDSNo IN WOReactRec<WO_REACT_RDS_NO$> USING @VM SETTING RemPos THEN
* * * Find where the the RDS being removed is in the list. * * *
LOCATE RemPos IN AllTestPos USING @VM SETTING TrimPos ELSE Null
LOCATE RDSNo IN WOReactRec<WO_REACT_RDS_NO$> USING @VM SETTING RemPos THEN
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
LOCATE RemPos IN AllTestPos USING @VM SETTING TrimPos ELSE Null
GOSUB RemSchedQA ;* Removes unsigned QAMet from cassettes scheduled past the box being removed
END ELSE
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
otParms = 'WO_REACT':@RM:WOReactKey
WOReactRec = obj_Tables('UnlockRec',otParms)
GOSUB RemSchedQA ;* Removes unsigned QAMet from cassettes scheduled past the box being removed
END ELSE
RETURN ;* RDSNo is not in this list -> nothing to do.
END
END ;* End of check for AllTestPos null
otParms = 'WO_REACT':@RM:WOReactKey
WOReactRec = obj_Tables('UnlockRec',otParms)
WOReactRec = DELETE(WOReactRec,WO_REACT_RDS_NO$,RemPos,0)
WOReactRec = DELETE(WOReactRec,WO_REACT_CASS_NO$,RemPos,0) ;* Removes the passed in RDSNo & associated cassette number from the data fields
RETURN ;* RDSNo is not in this list -> nothing to do.
END
END ;* End of check for AllTestPos null
RDSNos = WOReactRec<WO_REACT_RDS_NO$> ;* List after removal
CassNos = WOReactRec<WO_REACT_CASS_NO$> ;* List after removal
WOReactRec = DELETE(WOReactRec,WO_REACT_RDS_NO$,RemPos,0)
WOReactRec = DELETE(WOReactRec,WO_REACT_CASS_NO$,RemPos,0) ;* Removes the passed in RDSNo & associated cassette number from the data fields
* * * Now build list for cassette
RDSNos = WOReactRec<WO_REACT_RDS_NO$> ;* List after removal
CassNos = WOReactRec<WO_REACT_CASS_NO$> ;* List after removal
GOSUB BuildAllTestPos
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
* * * Now build list for cassette
GOSUB AddSchedQA ;* Add QAMet spec data to cassettes now associated with the test positions after removing the RDS & Cassno from the lists
otParms = FIELDSTORE(otParms,@RM,4,0,WOReactRec)
// 10/12/18 Changed to WriteOnlyRec as per Francois' instructions. - djs
obj_Tables('WriteOnlyRec',otParms) ;* Done with updates to the WO_REACT record
GOSUB BuildAllTestPos
ChangePosList = FIELD(AllTestPos,@VM,TrimPos,SeqCnt)
Result = Log
GOSUB AddSchedQA ;* Add QAMet spec data to cassettes now associated with the test positions after removing the RDS & Cassno from the lists
otParms = FIELDSTORE(otParms,@RM,4,0,WOReactRec)
EndTick = GetTickCount()
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
obj_Tables('WriteOnlyRec',otParms) ;* Done with updates to the WO_REACT record
Result = Log
EndTick = GetTickCount()
Mona_Services('QueueLatencyAndCountMetrics', MonaResource, MetricName, StartTick, EndTick)
RETURN
************** Internal Methods *************
* * * * * * *
BuildAllTestPos:
* * * * * * *
AllTestPos = ''
AllTestPos = ''
RDSCnt = COUNT(RDSNos,@VM) + (RDSNos NE '')
SeqCnt = 0
RDSCnt = COUNT(RDSNos,@VM) + (RDSNos NE '')
SeqCnt = 0
FOR TestSeq = 1 TO RDSCnt
IF REM((TestSeq - Start),Interval) = 0 THEN
AllTestPos<1,-1> = TestSeq ;* Build list of list positions to have QAMet scheduled
SeqCnt += 1
END
NEXT TestSeq
FOR TestSeq = 1 TO RDSCnt
IF REM((TestSeq - Start),Interval) = 0 THEN
AllTestPos<1,-1> = TestSeq ;* Build list of list positions to have QAMet scheduled
SeqCnt += 1
END
NEXT TestSeq
Log := 'AllTestPos: ':AllTestPos:@FM
Log := 'AllTestPos: ':AllTestPos:@FM
RETURN
* * * * * * *
RemSchedQA:
* * * * * * *
chgCnt = COUNT(ChangePosList,@VM) + (ChangePosList NE '')
chgCnt = COUNT(ChangePosList,@VM) + (ChangePosList NE '')
FOR I = 1 TO chgCnt
RemCassNo = CassNos<1,ChangePoslist<1,I>>
Log:= 'RemSched on CassNo: ':RemCassNo:@FM
FOR I = 1 TO chgCnt
RemCassNo = CassNos<1,ChangePoslist<1,I>>
Log:= 'RemSched on CassNo: ':RemCassNo:@FM
owmParms = WONo:@RM:StepNo:@RM:RemCassNo:@RM:Stage:@RM:MetPropCd
owmParms = WONo:@RM:StepNo:@RM:RemCassNo:@RM:Stage:@RM:MetPropCd
obj_WO_Mat_QA('RemQAMet',owmParms) ;* Unschedule test boxes before list change
obj_WO_Mat_QA('RemQAMet',owmParms) ;* Unschedule test boxes before list change
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
*obj_WO_Mat('RemQAMet',owmParms) ;* Dead 6/5/2015 JCH - Remove after a few days
*IF Get_Status(errCode) THEN
* ErrMsg(errCode)
*END
NEXT I
NEXT I
RETURN
@ -294,47 +284,39 @@ RETURN
AddSchedQA:
* * * * * * *
chgCnt = COUNT(ChangePosList,@VM) + (ChangePosList NE '')
chgCnt = COUNT(ChangePosList,@VM) + (ChangePosList NE '')
FOR I = 1 TO chgCnt
AddCassNo = CassNos<1,ChangePoslist<1,I>>
FOR I = 1 TO chgCnt
AddCassNo = CassNos<1,ChangePoslist<1,I>>
Log:= 'AddSched on CassNo: ':AddCassNo:@FM
Log:= 'AddSched on CassNo: ':AddCassNo:@FM
owmParms = WONo:@RM
owmParms := StepNo:@RM
owmParms := AddCassNo:@RM
owmParms := QAMetData<COL$QA_MET_STAGE>:@RM
owmParms := QAMetData<COL$QA_MET_TEST>:@RM
owmParms := QAMetData<COL$QA_MET_PROP>:@RM
owmParms := QAMetData<COL$QA_MET_TOOL_CLASS>:@RM
owmParms := QAMetData<COL$QA_MET_MIN>:@RM
owmParms := QAMetData<COL$QA_MET_MAX>:@RM
owmParms := QAMetData<COL$QA_MET_SLOT>:@RM
owmParms := QAMetData<COL$QA_MET_RECIPE>:@RM
owmParms := QAMetData<COL$QA_MET_RECIPE_PATTERN>:@RM
owmParms := QAMetData<COL$QA_MET_WFR_QTY>:@RM
owmParms := QAMetData<COL$QA_MET_WFR_TYPE>:@RM
owmParms := QAMetData<COL$QA_MET_REACT_SCHED>:@RM
owmParms := QAMetData<COL$QA_MET_SHIP_DOC>:@RM
owmParms := QAMetData<COL$QA_MET_PHASE_MIN> ; // 10/15/18 - djs - Added Phase Min Spec for HgCV
owmParms = WONo:@RM
owmParms := StepNo:@RM
owmParms := AddCassNo:@RM
owmParms := QAMetData<COL$QA_MET_STAGE>:@RM
owmParms := QAMetData<COL$QA_MET_TEST>:@RM
owmParms := QAMetData<COL$QA_MET_PROP>:@RM
owmParms := QAMetData<COL$QA_MET_TOOL_CLASS>:@RM
owmParms := QAMetData<COL$QA_MET_MIN>:@RM
owmParms := QAMetData<COL$QA_MET_MAX>:@RM
owmParms := QAMetData<COL$QA_MET_SLOT>:@RM
owmParms := QAMetData<COL$QA_MET_RECIPE>:@RM
owmParms := QAMetData<COL$QA_MET_RECIPE_PATTERN>:@RM
owmParms := QAMetData<COL$QA_MET_WFR_QTY>:@RM
owmParms := QAMetData<COL$QA_MET_WFR_TYPE>:@RM
owmParms := QAMetData<COL$QA_MET_REACT_SCHED>:@RM
owmParms := QAMetData<COL$QA_MET_SHIP_DOC>:@RM
owmParms := QAMetData<COL$QA_MET_PHASE_MIN> ; // 10/15/18 - djs - Added Phase Min Spec for HgCV
obj_WO_Mat_QA('AddQAMet', owmParms) ;* Schedule test boxes after list change
obj_WO_Mat_QA('AddQAMet', owmParms) ;* Schedule test boxes after list change
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
IF Get_Status(errCode) THEN
ErrMsg(errCode)
END
*obj_WO_Mat('AddQAMet',owmParms) ;* Dead 6/5/2015 JCH - remove after a few days
*IF Get_Status(errCode) THEN
* ErrMsg(errCode)
*END
NEXT I
NEXT I
RETURN

View File

@ -1157,37 +1157,47 @@ Service CopyRDSLayerParameters(RDSNo)
CopyRDSLayerKeys = Xlate('RDS', CopyRDSNo, 'RDS_LAYER_KEYS', 'X')
If CopyRDSLayerKeys NE '' then
For each CopyRDSLayerKey in CopyRDSLayerKeys
Until ErrMsg NE ''
// 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$)
if Error_Services('NoError') then
DestRDSLayerRec = Database_Services('ReadDataRow', 'RDS_LAYER', DestRDSLayerKey)
If Error_Services('NoError') then
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$)
If Error_Services('HasError') then
ErrMsg = Error_Services('GetMessage')
end
end else
ErrMsg = Error_Services('GetMessage')
end
end else
ErrMsg = Error_Services('GetMessage')
end
Next CopyRDSLayerKey
end
end else
@ -3381,3 +3391,4 @@ ClearCursors:
return

View File

@ -0,0 +1,204 @@
Compile function RDS_TEST_Services(@Service, @Params)
/***********************************************************************************************************************
Name : Rds_Test_Services
Description : Handler program for all RDS_TEST 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)
09/26/2025 djs Original programmer.
***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
$Insert SERVICE_SETUP
$insert APP_INSERTS
$Insert RDS_EQUATES
$Insert RDS_TEST_EQUATES
$Insert PROD_SPEC_EQUATES
$Insert RDS_LAYER_EQUATES
$INSERT PRS_LAYER_EQU
Declare function Database_Services, Error_Services, obj_Prod_Spec
Declare subroutine Database_Services, Error_Services
GoToService
Return Response or ""
//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------
Service UpdateRDSTestSpecs(RdsNo)
ErrorMsg = ''
If (RDSNo NE '') then
If RowExists('RDS', RDSNo) then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSNo)
If Error_Services('NoError') then
LayerKeys = RDSRec<RDS_RDS_LAYER_KEYS$>
PSNId = RDSRec<RDS_PROD_SPEC_ID$>
For each LayerKey in LayerKeys using @VM setting vPos
LayerSet = Field(LayerKey, '*', 2, 1)
LayerSpecs = obj_Prod_Spec('GetLayerProp',PSNId:@RM:LayerSet:@RM:1) ;* Last parameter specifies no output conversion on return data
LayerSpecs = Field(LayerSpecs,@FM,2,99) ;* Returns with the layer set ID in the first field of each line
ErrCode = ''
If Not(Get_Status(ErrCode)) then
WaferSize = Xlate('PROD_SPEC', PSNId, 'SUB_WAFER_SIZE', 'X')
SubOrientation = Xlate('PROD_SPEC', PSNId, 'SUB_ORIENTATION', 'X')
ResUnits = LayerSpecs<PRS_LAYER_RES_UNITS$>
ReactorType = Xlate('PROD_SPEC', PSNId, PROD_SPEC_REACTOR_TYPE$, 'X')
ThickFilmMet = Xlate('PROD_SPEC', PSNId, PROD_SPEC_THICKFILM_MET$, 'X') ;* Added 1/16/2009 JCH
RdsTestKeys = Database_Services('ReadDataColumn', 'RDS_LAYER', LayerKey, RDS_LAYER_RDS_TEST_KEYS$)
If Error_Services('NoError') then
For each RdsTestKey in RdsTestKeys using @VM setting RdsTestPos
RdsTestRec = Database_Services('ReadDataRow', 'RDS_TEST', RdsTestKey)
If Error_Services('NoError') then
RDSTestRec<RDS_TEST_WAFER_SIZE$> = WaferSize
RDSTestRec<RDS_TEST_SUB_ORIENTATION$> = SubOrientation
RDSTestRec<RDS_TEST_SPEC_DOPANT$> = LayerSpecs<PRS_LAYER_DOPANT$>
RDSTestRec<RDS_TEST_SPEC_RECIPE$> = LayerSpecs<PRS_LAYER_RECIPE$>
RDSTestRec<RDS_TEST_SPEC_RECIPE_NAME$> = LayerSpecs<PRS_LAYER_RECIPE_NAME$>
RDSTestRec<RDS_TEST_SPEC_THICK_MIN$> = LayerSpecs<PRS_LAYER_THICK_MIN$>
RDSTestRec<RDS_TEST_SPEC_THICK_TARGET$> = LayerSpecs<PRS_LAYER_THICK_TARGET$>
RDSTestRec<RDS_TEST_SPEC_THICK_MAX$> = LayerSpecs<PRS_LAYER_THICK_MAX$>
RDSTestRec<RDS_TEST_SPEC_THICK_UNITS$> = LayerSpecs<PRS_LAYER_THICK_UNITS$>
RDSTestRec<RDS_TEST_SPEC_RES_MIN$> = LayerSpecs<PRS_LAYER_RES_MIN$>
RDSTestRec<RDS_TEST_SPEC_RES_TARGET$> = LayerSpecs<PRS_LAYER_RES_TARGET$>
RDSTestRec<RDS_TEST_SPEC_RES_MAX$> = LayerSpecs<PRS_LAYER_RES_MAX$>
RDSTestRec<RDS_TEST_SPEC_RES_UNITS$> = LayerSpecs<PRS_LAYER_RES_UNITS$>
RDSTestRec<RDS_TEST_SPEC_CON_MIN$> = LayerSpecs<PRS_LAYER_CONC_MIN$>
RDSTestRec<RDS_TEST_SPEC_CON_TARGET$> = LayerSpecs<PRS_LAYER_CONC_TARGET$>
RDSTestRec<RDS_TEST_SPEC_CON_MAX$> = LayerSpecs<PRS_LAYER_CONC_MAX$>
RDSTestRec<RDS_TEST_SPEC_CON_UNITS$> = LayerSpecs<PRS_LAYER_CONC_UNITS$>
RDSTestRec<RDS_TEST_SPEC_STRESS_MIN$> = LayerSpecs<PRS_LAYER_STRESS_MIN$>
RDSTestRec<RDS_TEST_SPEC_STRESS_MAX$> = LayerSpecs<PRS_LAYER_STRESS_MAX$>
RDSTestRec<RDS_TEST_SPEC_TRANS$> = LayerSpecs<PRS_LAYER_TRANS_SPEC$>
RDSTestRec<RDS_TEST_SPEC_CRES_MIN$> = LayerSpecs<PRS_LAYER_CRES_MIN$>
RDSTestRec<RDS_TEST_SPEC_CRES_TARGET$> = LayerSpecs<PRS_LAYER_CRES_TARGET$>
RDSTestRec<RDS_TEST_SPEC_CRES_MAX$> = LayerSpecs<PRS_LAYER_CRES_MAX$>
RDSTestRec<RDS_TEST_SPEC_CRES_UNITS$> = LayerSpecs<PRS_LAYER_CRES_UNITS$>
For A = 11 to 19
RDSTestRec<A> = LayerSpecs<PRS_LAYER_THICK_MEASUREMENT$,A-10>
Next A
For A = 24 to 32
RDSTestRec<A> = LayerSpecs<PRS_LAYER_RES_MEASUREMENT$,A-23>
Next A
For A = 37 to 45
RDSTestRec<A> = LayerSpecs<PRS_LAYER_CONC_MEASUREMENT$,A-36>
Next A
For A = 50 to 58
RDSTestRec<A> = LayerSpecs<PRS_LAYER_STRESS_MEASUREMENT$,A-49>
Next A
For A = 121 to 129
RDSTestRec<A> = LayerSpecs<PRS_LAYER_CRES_MEASUREMENT$,A-120>
Next A
RDSTestRec<RDS_TEST_SPEC_THICK_MPATTERN$> = LayerSpecs<PRS_LAYER_THICK_MEASUREMENT$,PRS_MPATTERN$>
RDSTestRec<RDS_TEST_SPEC_RES_MPATTERN$> = LayerSpecs<PRS_LAYER_RES_MEASUREMENT$,PRS_MPATTERN$>
RDSTestRec<RDS_TEST_SPEC_CON_MPATTERN$> = LayerSpecs<PRS_LAYER_CONC_MEASUREMENT$,PRS_MPATTERN$>
RDSTestRec<RDS_TEST_SPEC_STRESS_MPATTERN$> = LayerSpecs<PRS_LAYER_STRESS_MEASUREMENT$,PRS_MPATTERN$>
RDSTestRec<RDS_TEST_SPEC_CRES_MPATTERN$> = LayerSpecs<PRS_LAYER_CRES_MEASUREMENT$,PRS_MPATTERN$>
RDSTestRec<RDS_TEST_REACTOR_TYPE$> = ReactorType
If ( (ReactorType EQ 'P') or (ReactorType EQ 'EPP') or (ThickFilmMet EQ True$) ) then
SpecMap = XLATE('PROD_SPEC', PSNId, PROD_SPEC_TEST_POINT_MAP$, 'X') ;* Added 4/8/2009 JCH new field in PROD_SPEC
If SpecMap NE '' then
RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = SpecMap
end else
;* Added ThickFilmMet check - 1/16/2009 JCH
AllTargetThicks = XLATE('PROD_SPEC', PSNId, 'THICK_TARGET_ALL', 'X')
TargetCnt = COUNT(AllTargetThicks,@VM) + (AllTargetThicks NE '')
Begin Case
Case TargetCnt = 2
CombinedThick = SUM(AllTargetThicks)
Case TargetCnt = 1 OR TargetCnt = 3
CombinedThick = AllTargetThicks[-1,'B':@VM]
End Case
If OCONV(CombinedThick,'MD2') > '65.0' then
RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'FTIR_T'
end else
RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'FTIR'
end
end
end else
RDSTestRec<RDS_TEST_TEST_POINT_MAP$> = 'ASM17' ;* 17 Point linear test pattern until PROD_SPEC is updated support other types
end
Database_Services('WriteDataRow', 'RDS_TEST', RdsTestKey, RdsTestRec)
If Error_Services('HasError') then
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
Next RdsTestKey
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error calling obj_Prod_Spec("GetLayerProp"). Error code: ':ErrCode
end
Next LayerKey
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. RDS ':RdsNo:' does not exist'
end
end else
ErrorMsg = 'Error in ':Service:' service. Null RDSNo passed into service'
end
If (ErrorMsg NE '') then Error_Services('Add', ErrorMsg)
End Service

View File

@ -30,22 +30,23 @@ Function Schedule_Services(@Service, @Params)
#pragma precomp SRP_PreCompiler
$insert APP_INSERTS
$insert SERVICE_SETUP
$insert RLIST_EQUATES
$insert REACTOR_EQUATES
$insert SCHED_DET_NG_EQUATES
$insert WO_LOG_EQUATES
$Insert APP_INSERTS
$Insert SERVICE_SETUP
$Insert RLIST_EQUATES
$Insert REACTOR_EQUATES
$Insert SCHED_DET_NG_EQUATES
$Insert WO_LOG_EQUATES
$Insert WO_MAT_EQUATES
$insert WO_SCHEDULE_NG_EQUATES
$insert COMPANY_EQUATES
$insert PROD_VER_EQUATES
$insert PRS_LAYER_EQU
$insert SCHEDULE_EVENT_SUMMMARY_EQUATES
$insert EPI_PART_EQUATES
$insert PROD_SPEC_EQUATES
$insert SCHED_HIST_EQUATES
$Insert WO_SCHEDULE_NG_EQUATES
$Insert COMPANY_EQUATES
$Insert PROD_VER_EQUATES
$Insert PRS_LAYER_EQU
$Insert SCHEDULE_EVENT_SUMMMARY_EQUATES
$Insert EPI_PART_EQUATES
$Insert PROD_SPEC_EQUATES
$Insert SCHED_HIST_EQUATES
$Insert RDS_EQUATES
$Insert WM_IN_EQUATES
Equ new_exist$ To 0 ; * Reduce Mode 0
Equ next_cur$ To 1
@ -59,7 +60,7 @@ Declare subroutine Mona_Services
Declare function SRP_Array, Schedule_Services, Memory_Services, Database_Services, SRP_Sort_Array, Datetime
Declare function Epi_Part_Services, SRP_Math, SRP_Hash, obj_Prod_Spec, Logging_Services, Environment_Services
Declare function Work_Order_Services, RTI_CreateGUID, Reactor_Services, Schedule_Services, NextKey, SRP_Datetime
Declare function SRP_Time, Lsl_Users_Services, GetTickCount
Declare function SRP_Time, Lsl_Users_Services, GetTickCount, obj_WO_Mat
Date = Oconv(Date(), 'D4/')
LogFileName = Date[7, 4] : '-' : Date[1, 2] : '-' : Date[4, 2] : ' Scheduler Log.csv'
@ -1246,13 +1247,58 @@ Service AdjustScheduleEvents(ReactNo)
Schedule_Services('LogActivity', ReactNo, LogData)
LogData<3> = 'Event complete: ':OConv(EventRec<SCHED_DET_NG.EVENT_COMP$>, "Btrue,false")
Schedule_Services('LogActivity', ReactNo, LogData)
LogData<3> = 'Event unprocessed cassettes: ':EventRec<SCHED_DET_NG.UNPROCESSED_CASS$>
Schedule_Services('LogActivity', ReactNo, LogData)
LogData<3> = 'Event processed cassettes: ':EventRec<SCHED_DET_NG.PROCESSED_CASS$>
Schedule_Services('LogActivity', ReactNo, LogData)
EventAdjustment = Schedule_Services('GetEventAdjustment', EventKey)
UnprocessedCass = EventRec<SCHED_DET_NG.UNPROCESSED_CASS$>
ProcessedCass = EventRec<SCHED_DET_NG.PROCESSED_CASS$>
AllCassList = SRP_Array('Join', UnprocessedCass, ProcessedCass, 'OR', @VM)
AllCassList = SRP_Array('SortSimpleList', AllCassList, 'AscendingNumbers', @VM)
EventComp = (UnprocessedCass EQ '')
// Check each cassette to see if it was voided
VoidedQty = 0
WONo = EventRec<SCHED_DET_NG.WO_NO$>
EventWfrs = EventRec<SCHED_DET_NG.EVENT_TOTAL_WFRS$>
VoidedCassList = ''
VoidedWfrQty = 0
For each CassNo in AllCassList using @VM
If Epipro then
WmInKey = WoNo:'*1*':CassNo
Voided = Xlate('WM_IN', WmInKey, 'VOID', 'X')
CassQty = Xlate('WM_IN', WmInKey, 'WFR_CNT', 'X')
end else
WOMatKey = WoNo:'*':CassNo
Voided = Xlate('WO_MAT', WOMatKey, 'VOID', 'X')
CassQty = Xlate('WO_MAT', WOMatKey, 'WAFER_QTY', 'X')
end
If Voided then
VoidedCassList<0, -1> = CassNo
VoidedWfrQty += CassQty
end
Next CassNo
UnprocessedCass = SRP_Array('Join', UnprocessedCass, VoidedCassList, 'NOT', @VM)
ProcessedCass = SRP_Array('Join', ProcessedCass, VoidedCassList, 'NOT', @VM)
AllCassList = SRP_Array('Join', AllCassList, VoidedCassList, 'NOT', @VM)
EventWfrs -= VoidedWfrQty
EventRec<SCHED_DET_NG.UNPROCESSED_CASS$> = UnprocessedCass
EventRec<SCHED_DET_NG.PROCESSED_CASS$> = ProcessedCass
EventRec<SCHED_DET_NG.EVENT_TOTAL_WFRS$> = EventWfrs
Database_Services('WriteDataRow', 'SCHED_DET_NG', EventKey, EventRec, True$, False$, True$)
// Check each unprocessed cassette to ensure it does not need to be moved to the processed column
For each CassNo in UnprocessedCass using @VM
Schedule_Services('MarkCassProcessed', WONo, CassNo, Datetime())
Next CassNo
EventRec = Schedule_Services('GetScheduleDetail', EventKey)
UnprocessedCass = EventRec<SCHED_DET_NG.UNPROCESSED_CASS$>
ProcessedCass = EventRec<SCHED_DET_NG.PROCESSED_CASS$>
AllCassList = SRP_Array('Join', UnprocessedCass, ProcessedCass, 'OR', @VM)
AllCassList = SRP_Array('SortSimpleList', AllCassList, 'AscendingNumbers', @VM)
EventAdjustment = Schedule_Services('GetEventAdjustment', EventKey)
EventComp = (UnprocessedCass EQ '')
If Not(EventRec<SCHED_DET_NG.EVENT_COMP$>) and EventComp then
LogData = ''
@ -1263,9 +1309,7 @@ Service AdjustScheduleEvents(ReactNo)
end
EventRec<SCHED_DET_NG.EVENT_COMP$> = EventComp
WONo = EventRec<SCHED_DET_NG.WO_NO$>
ReactNo = EventRec<SCHED_DET_NG.REACT_NO$>
EventWfrs = EventRec<SCHED_DET_NG.EVENT_TOTAL_WFRS$>
WOQty = Xlate('WO_LOG', WONo, 'QTY', 'X')
// If work order event is engaged then set start DTM to first cassette DTM in.
// If previous event end time overlaps (e.g. soft block finished sooner than scheduled)
@ -2258,6 +2302,7 @@ end service
Service AddSchedEvent(ReactorNo, WorkOrderNo, StartDTM, StopDTM, Description, WaferQty)
// Create a unique key ID for the new event
ErrorMsg = ''
NewEventKeyID = RTI_CreateGUID()
NewEventRec = ''
NewEventRec<SCHED_DET_NG.REACT_NO$> = ReactorNo
@ -2267,16 +2312,17 @@ Service AddSchedEvent(ReactorNo, WorkOrderNo, StartDTM, StopDTM, Description, Wa
NewEventRec<SCHED_DET_NG.EVENT_TOTAL_WFRS$> = WaferQty
EpiPro = (Xlate('WO_LOG', WorkOrderNo, 'REACT_TYPE', 'X') EQ 'EPP')
CurrDTM = Datetime()
EventProcCassList = ''
EventUnprocCassList = ''
LastLoadedRDS = ''
LastUnloadedRDS = ''
EventProcCassList = ''
EventUnprocCassList = ''
LastLoadedRDS = ''
LastUnloadedRDS = ''
// Determine start cassette and slot number
PrevSchedQty = Schedule_Services('GetScheduledWfrQty', WorkOrderNo)
StartCass = SRP_Math('CEILING', ( (PrevSchedQty + 1) / 25))
PrevSchedQty = Schedule_Services('GetScheduledWfrQty', WorkOrderNo)
VoidedQty = Work_Order_Services('GetVoidedWaferCount', WorkOrderNo)
StartCass = SRP_Math('CEILING', ( (PrevSchedQty + VoidedQty + 1) / 25))
If StartCass EQ 0 then StartCass = 1
StartSlot = Mod(PrevSchedQty, 25) + 1
TotalSchedQty = PrevSchedQty + WaferQty
TotalSchedQty = PrevSchedQty + WaferQty + VoidedQty
StopCass = SRP_Math('CEILING', ( TotalSchedQty / 25 ) )
StopSlot = Mod(TotalSchedQty, 25)
If StopSlot EQ 0 then StopSlot = 25
@ -2284,128 +2330,192 @@ Service AddSchedEvent(ReactorNo, WorkOrderNo, StartDTM, StopDTM, Description, Wa
RDSKeys = ''
If EpiPro then
For CassNo = StartCass to StopCass
WMIKey = WorkOrderNo:'*1*':CassNo
WMIRdsList = Xlate('WM_IN', WMIKey, 'RDS_NO', 'X')
If WMIRdsList NE '' then
Begin Case
Case ( (CassNo EQ StartCass) and (CassNo EQ StopCass) )
StartIndex = StartSlot
StopIndex = StopSlot
Case CassNo EQ StartCass
StartIndex = StartSlot
StopIndex = 25
Case CassNo EQ StopCass
StartIndex = 1
StopIndex = StopSlot
Case Otherwise$
StartIndex = 1
StopIndex = 25
End Case
For SlotIndex = StartIndex to StopIndex
RDSKeys<0, -1> = WMIRdsList<0, SlotIndex>
Next SlotIndex
WMIKey = WorkOrderNo:'*1*':CassNo
If RowExists('WM_IN', WMIKey) then
WMIRec = Database_Services('ReadDataRow', 'WM_IN', WMIKey)
end else
// No RDS keys exist for this cassette yet, so it's unprocessed
EventUnprocCassList<0, -1> = CassNo
// Material not received yet
WMIRec = ''
end
If Error_Services('NoError') then
Voided = WMIRec<WM_IN_VOID$>
If Not(Voided) then
WMIRdsList = WMIRec<WM_IN_RDS_NO$>
If WMIRdsList NE '' then
Begin Case
Case ( (CassNo EQ StartCass) and (CassNo EQ StopCass) )
StartIndex = StartSlot
StopIndex = StopSlot
Case CassNo EQ StartCass
StartIndex = StartSlot
StopIndex = 25
Case CassNo EQ StopCass
StartIndex = 1
StopIndex = StopSlot
Case Otherwise$
StartIndex = 1
StopIndex = 25
End Case
For SlotIndex = StartIndex to StopIndex
RDSKeys<0, -1> = WMIRdsList<0, SlotIndex>
Next SlotIndex
end else
// No RDS keys exist for this cassette yet, so it's unprocessed
EventUnprocCassList<0, -1> = CassNo
end
end
end else
ErrorMsg = Error_Services('GetMessage')
end
Until (ErrorMsg NE '')
Next CassNo
If RDSKeys NE '' then
RDSKeys = SRP_Array('Clean', RDSKeys, 'TrimAndMakeUnique', @VM)
For each RDSKey in RDSKeys using @VM setting vPos
DtmOut = Xlate('RDS', RDSKey, 'DATETIME_OUT', 'X')
WMIKeys = Xlate('RDS', RDSKey, 'WM_IN_KEY', 'X')
For each WMIKey in WMIKeys using @VM
CassNo = Field(WMIKey, '*', 3)
If DtmOut NE '' then
LastUnloadedRDS = RDSKey
Locate CassNo in EventProcCassList using @VM setting Dummy else
EventProcCassList<0, -1> = CassNo
end
If (ErrorMsg EQ '') then
If RDSKeys NE '' then
RDSKeys = SRP_Array('Clean', RDSKeys, 'TrimAndMakeUnique', @VM)
For each RDSKey in RDSKeys using @VM setting vPos
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey)
If Error_Services('NoError') then
DateOut = RDSRec<RDS_DATE_OUT$>
TimeOut = RDSRec<RDS_TIME_OUT$>
TimeOut = TimeOut/86400
TimeOut = SRP_Math('ROUND', TimeOut, 5)
TimeOut = TimeOut[2, 6]
DtmOut = DateOut:TimeOut
end else
Locate CassNo in EventUnprocCassList using @VM setting Dummy else
EventUnprocCassList<0, -1> = CassNo
end
ErrorMsg = Error_Services('GetMessage')
end
Next WMIKey
Next RDSKey
end
If (ErrorMsg EQ '' ) then
WMIKeys = Xlate('RDS', RDSKey, 'WM_IN_KEY', 'X')
For each WMIKey in WMIKeys using @VM
CassNo = Field(WMIKey, '*', 3)
If DtmOut NE '' then
LastUnloadedRDS = RDSKey
Locate CassNo in EventProcCassList using @VM setting Dummy else
EventProcCassList<0, -1> = CassNo
end
end else
Locate CassNo in EventUnprocCassList using @VM setting Dummy else
EventUnprocCassList<0, -1> = CassNo
end
end
Next WMIKey
end
Until (ErrorMsg NE '')
Next RDSKey
end
EventUnprocCassList = SRP_Array('SortSimpleList', EventUnprocCassList, 'AscendingNumbers', @VM)
// This line ensures EpiPro cassettes are not recorded as both processed and unprocessed.
EventProcCassList = SRP_Array('Join', EventProcCassList, EventUnprocCassList, 'NOT', @VM)
EventUnprocCassList = SRP_Array('SortSimpleList', EventUnprocCassList, 'AscendingNumbers', @VM)
// This line ensures EpiPro cassettes are not recorded as both processed and unprocessed.
EventProcCassList = SRP_Array('Join', EventProcCassList, EventUnprocCassList, 'NOT', @VM)
end
end else
For CassNo = StartCass to StopCass
WOMatKey = WorkOrderNo:'*':CassNo
RDSKey = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
DtmOut = Xlate('RDS', RDSKey, 'DATETIME_OUT', 'X')
If DtmOut NE '' then
LastUnloadedRDS = RDSKey
Locate CassNo in EventProcCassList using @VM setting Dummy else
EventProcCassList<0, -1> = CassNo
DtmOut = ''
WOMatKey = WorkOrderNo:'*':CassNo
If RowExists('WO_MAT', WOMatKey) then
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
end else
// Material not received yet
WOMatRec = ''
end
If Error_Services('NoError') then
Voided = WOMatRec<WO_MAT_VOID$>
If Not(Voided) then
RDSKey = WOMatRec<WO_MAT_RDS_NO$>
If (RDSKey NE '') then
RDSRec = Database_Services('ReadDataRow', 'RDS', RDSKey)
If Error_Services('NoError') then
DateOut = RDSRec<RDS_DATE_OUT$>
TimeOut = RDSRec<RDS_TIME_OUT$>
TimeOut = TimeOut/86400
TimeOut = SRP_Math('ROUND', TimeOut, 5)
TimeOut = TimeOut[2, 6]
DtmOut = DateOut:TimeOut
end else
ErrorMsg = Error_Services('GetMessage')
end
end
end
end else
Locate CassNo in EventUnprocCassList using @VM setting Dummy else
EventUnprocCassList<0, -1> = CassNo
ErrorMsg = Error_Services('GetMessage')
end
If (ErrorMsg EQ '') then
If (DtmOut NE '') then
LastUnloadedRDS = RDSKey
Locate CassNo in EventProcCassList using @VM setting Dummy else
EventProcCassList<0, -1> = CassNo
end
end else
Locate CassNo in EventUnprocCassList using @VM setting Dummy else
EventUnprocCassList<0, -1> = CassNo
end
end
end
Until (ErrorMsg NE '')
Next CassNo
end
EventComp = (EventUnprocCassList EQ '')
If EventComp then StopDtm = Xlate('RDS', LastUnloadedRDS, 'DATETIME_OUT', 'X')
If (ErrorMsg EQ '') then
// Update event
NewEventRec<SCHED_DET_NG.EVENT_COMP$> = EventComp
NewEventRec<SCHED_DET_NG.PROCESSED_CASS$> = EventProcCassList
NewEventRec<SCHED_DET_NG.UNPROCESSED_CASS$> = EventUnprocCassList
NewEventRec<SCHED_DET_NG.STOP_DTM$> = StopDtm
Database_Services('WriteDataRow', 'SCHED_DET_NG', NewEventKeyID, NewEventRec)
EventComp = (EventUnprocCassList EQ '')
If EventComp then StopDtm = Xlate('RDS', LastUnloadedRDS, 'DATETIME_OUT', 'X')
If Error_Services('NoError') then
// Determine where to insert the event in the REACTOR record linked list
// Add the event to the REACTOR record event list
ReactRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
ReactSchedEvents = ReactRec<REACTOR_SCHED_EVENTS$>
CurrNumEvents = DCount(ReactSchedEvents, @VM)
// Add our new event key ID to the reactor event list
NewNumEvents = CurrNumEvents + 1
InsertPos = ''
For EventIndex = 1 to CurrNumEvents Step 1
ThisEventKey = ReactSchedEvents<0, EventIndex>
ThisStartDTM = Xlate('SCHED_DET_NG', ThisEventKey, 'START_DTM', 'X')
IF ThisStartDTM GT StartDTM then
// We found our location
InsertPos = EventIndex
end
Until InsertPos NE ''
Next EventIndex
If InsertPos EQ '' then InsertPos = NewNumEvents
ReactSchedEvents = Insert(ReactSchedEvents, 0, InsertPos, 0, NewEventKeyID)
ReactRec<REACTOR_SCHED_EVENTS$> = ReactSchedEvents
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, ReactRec)
// Update event
NewEventRec<SCHED_DET_NG.EVENT_COMP$> = EventComp
NewEventRec<SCHED_DET_NG.PROCESSED_CASS$> = EventProcCassList
NewEventRec<SCHED_DET_NG.UNPROCESSED_CASS$> = EventUnprocCassList
NewEventRec<SCHED_DET_NG.STOP_DTM$> = StopDtm
Database_Services('WriteDataRow', 'SCHED_DET_NG', NewEventKeyID, NewEventRec)
// Check if there is an overlap with the previous event. If so, then set previous event's stop DTM to this event's
// start DTM.
If NewNumEvents GT 1 then
PrevEventKey = ReactSchedEvents<0, (NewNumEvents - 1)>
If PrevEventKey NE '' then
PrevEventRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', PrevEventKey)
PrevEventStopDTM = PrevEventRec<SCHED_DET_NG.STOP_DTM$>
If PrevEventStopDTM GT StartDTM then
PrevEventStopDTM = StartDTM
PrevEventRec<SCHED_DET_NG.STOP_DTM$> = PrevEventStopDTM
Database_Services('WriteDataRow', 'SCHED_DET_NG', PrevEventKey, PrevEventRec, True$, False$, True$)
If Error_Services('NoError') then
// Determine where to insert the event in the REACTOR record linked list
// Add the event to the REACTOR record event list
ReactRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
ReactSchedEvents = ReactRec<REACTOR_SCHED_EVENTS$>
CurrNumEvents = DCount(ReactSchedEvents, @VM)
// Add our new event key ID to the reactor event list
NewNumEvents = CurrNumEvents + 1
InsertPos = ''
For EventIndex = 1 to CurrNumEvents Step 1
ThisEventKey = ReactSchedEvents<0, EventIndex>
ThisStartDTM = Xlate('SCHED_DET_NG', ThisEventKey, 'START_DTM', 'X')
IF ThisStartDTM GT StartDTM then
// We found our location
InsertPos = EventIndex
end
Until InsertPos NE ''
Next EventIndex
If InsertPos EQ '' then InsertPos = NewNumEvents
ReactSchedEvents = Insert(ReactSchedEvents, 0, InsertPos, 0, NewEventKeyID)
ReactRec<REACTOR_SCHED_EVENTS$> = ReactSchedEvents
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, ReactRec)
// Check if there is an overlap with the previous event. If so, then set previous event's stop DTM to this event's
// start DTM.
If NewNumEvents GT 1 then
PrevEventKey = ReactSchedEvents<0, (NewNumEvents - 1)>
If PrevEventKey NE '' then
PrevEventRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', PrevEventKey)
PrevEventStopDTM = PrevEventRec<SCHED_DET_NG.STOP_DTM$>
If PrevEventStopDTM GT StartDTM then
PrevEventStopDTM = StartDTM
PrevEventRec<SCHED_DET_NG.STOP_DTM$> = PrevEventStopDTM
Database_Services('WriteDataRow', 'SCHED_DET_NG', PrevEventKey, PrevEventRec, True$, False$, True$)
end
end
end
// Record schedule change in SCHED_HIST table
Schedule_Services('AddSchedHist', NewEventKeyID, ReactorNo, 'ADD', @User4)
Response = NewEventKeyID
end
// Record schedule change in SCHED_HIST table
Schedule_Services('AddSchedHist', NewEventKeyID, ReactorNo, 'ADD', @User4)
Response = NewEventKeyID
end
If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
end service
@ -3200,19 +3310,33 @@ Service MarkCassProcessed(WONo, CassNo, ProcessedDTM)
CassComp = True$
end
end else
CassComp = True$
WOMatKey = WoNo:'*':CassNo
CurrWaferCount = obj_WO_Mat('CurrWaferCnt', WOMatKey)
RDSNo = Xlate('WO_MAT', WOMatKey, 'RDS_NO', 'X')
DateOut = Xlate('RDS', RDSNo, 'DATE_OUT', 'X')
CassComp = ( (CurrWaferCount EQ 0) or (DateOut NE '') )
end
UnprocessedCassettes = SchedDetNGRec<SCHED_DET_NG.UNPROCESSED_CASS$>
If CassComp then
RecChanged = False$
UnprocessedCassettes = SchedDetNGRec<SCHED_DET_NG.UNPROCESSED_CASS$>
Locate CassNo in UnprocessedCassettes using @VM setting vPos then
UnprocessedCassettes = Delete(UnprocessedCassettes, 0, vPos, 0)
ProcessedCassettes = SchedDetNGRec<SCHED_DET_NG.PROCESSED_CASS$>
ProcessedCassettes<0, -1> = CassNo
UnprocessedCassettes = Delete(UnprocessedCassettes, 0, vPos, 0)
RecChanged = True$
end
ProcessedCassettes = SchedDetNGRec<SCHED_DET_NG.PROCESSED_CASS$>
Locate CassNo in ProcessedCassettes using @VM setting vPos else
ProcessedCassettes<0, -1> = CassNo
ProcessedCassettes = SRP_Array('Clean', ProcessedCassettes, 'TrimAndMakeUnique', @VM)
ProcessedCassettes = SRP_Array('SortSimpleList', ProcessedCassettes, 'AscendingNumbers', @VM)
RecChanged = True$
end
If RecChanged then
SchedDetNGRec<SCHED_DET_NG.UNPROCESSED_CASS$> = UnprocessedCassettes
SchedDetNGRec<SCHED_DET_NG.PROCESSED_CASS$> = ProcessedCassettes
Database_Services('WriteDataRow', 'SCHED_DET_NG', SchedDetNGKey, SchedDetNGRec, True$, False$, True$)
Done = True$
end
Done = True$
end
Until Done EQ True$
Repeat

View File

@ -25,12 +25,23 @@ Event WINDOW.CREATE(CreateParam)
OIWizardBaseUrl = Environment_Services('GetOIWizardBaseUrl')
Set_Property(@Window, '@BASE_URL', OIWizardBaseUrl)
InitNavPage = CreateParam
InitNavPage = CreateParam
Set_Property(@Window, '@INIT_NAV_PAGE', InitNavPage)
Set_Property(@Window, '@FIRST_RENDER', True$)
Set_Property(@Window:'.WEBVIEW_MAIN', 'AUTOSIZEHEIGHT', True$)
Set_Property(@Window:'.WEBVIEW_MAIN', 'AUTOSIZEWIDTH', True$)
PlaceDialog(-2, -2)
ScreenSize = Get_Property('SYSTEM', 'SIZE')
ClientWidth = ScreenSize<3>
ClientHeight = ScreenSize<4>
FormSize = Get_Property(@Window, 'SIZE')
FormWidth = Int(ClientWidth * (3/4))
FormHeight = Int(ClientHeight * (3/4))
FormSize<1> = Int( (ClientWidth - FormWidth ) / 2 )
FormSize<2> = Int( (ClientHeight - FormHeight ) / 2 )
FormSize<3> = FormWidth
FormSize<4> = FormHeight
FormSize<5> = True$
Set_Property(@Window, 'SIZE', FormSize)
End Event
@ -103,4 +114,3 @@ Event WINDOW.TIMER()
end event

View File

@ -2344,6 +2344,38 @@ Service UpdateOpenWorkOrderData()
Logging_Services('AppendLog', objVerifyWOMatKeysLog, LogData, @RM, @FM)
MonaStatus = 'critical'
end
Work_Order_Services('UpdateReceivedQty', NextOpenWoLogKey)
If Error_Services('HasError') then
LogData<1> = OConv(Datetime(), 'DT/^S')
ErrorMsg = 'Error calling UpdateReceivedQty for WO_LOG ':NextOpenWoLogKey:'. ':Error_Services('GetMessage')
LogData<4> = ErrorMsg
Logging_Services('AppendLog', objVerifyWOMatKeysLog, LogData, @RM, @FM)
MonaStatus = 'critical'
end
Work_Order_Services('UpdateReleasedQty', NextOpenWoLogKey)
If Error_Services('HasError') then
LogData<1> = OConv(Datetime(), 'DT/^S')
ErrorMsg = 'Error calling UpdateReleasedQty for WO_LOG ':NextOpenWoLogKey:'. ':Error_Services('GetMessage')
LogData<4> = ErrorMsg
Logging_Services('AppendLog', objVerifyWOMatKeysLog, LogData, @RM, @FM)
MonaStatus = 'critical'
end
Work_Order_Services('UpdateScrappedQty', NextOpenWoLogKey)
If Error_Services('HasError') then
LogData<1> = OConv(Datetime(), 'DT/^S')
ErrorMsg = 'Error calling UpdateScrappedQty for WO_LOG ':NextOpenWoLogKey:'. ':Error_Services('GetMessage')
LogData<4> = ErrorMsg
Logging_Services('AppendLog', objVerifyWOMatKeysLog, LogData, @RM, @FM)
MonaStatus = 'critical'
end
Work_Order_Services('UpdateShippedQty', NextOpenWoLogKey)
If Error_Services('HasError') then
LogData<1> = OConv(Datetime(), 'DT/^S')
ErrorMsg = 'Error calling UpdateShippedQty for WO_LOG ':NextOpenWoLogKey:'. ':Error_Services('GetMessage')
LogData<4> = ErrorMsg
Logging_Services('AppendLog', objVerifyWOMatKeysLog, LogData, @RM, @FM)
MonaStatus = 'critical'
end
end
end else
LogData<1> = OConv(Datetime(), 'DT/^S')
@ -2579,6 +2611,56 @@ Service GetWoLogZpl(WoNo)
end service
Service GetVoidedWaferCount(WorkOrderNo)
ErrorMsg = ''
VoidedWaferCount = 0
If WorkOrderNo NE '' then
If RowExists('WO_LOG', WorkOrderNo) then
ReactorType = Xlate('WO_LOG', WorkOrderNo, 'PS_REACTOR_TYPE', 'X')
If ReactorType EQ 'EPP' then
Query = 'SELECT WM_IN WITH WO_NO EQ ':WorkOrderNo:' AND WITH VOID EQ ':True$
Rlist(Query, TARGET_ACTIVELIST$, '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
EOF = False$
Loop
Readnext WmInKey else EOF = True$
Until EOF
VoidedWaferCount += Xlate('WM_IN', WmInKey, 'WFR_CNT', 'X')
Repeat
end else
ErrorMsg = 'Error in ':Service: 'service. Error calling RList. Error code: ':ErrCode
end
end else
Query = 'SELECT WO_MAT WITH WO_NO EQ ':WorkOrderNo:' AND WITH VOID EQ ':True$
Rlist(Query, TARGET_ACTIVELIST$, '', '', '')
ErrCode = ''
If Not(Get_Status(ErrCode)) then
EOF = False$
Loop
Readnext WoMatKey else EOF = True$
Until EOF
VoidedWaferCount += Xlate('WO_MAT', WoMatKey, 'WAFER_QTY', 'X')
Repeat
end else
ErrorMsg = 'Error in ':Service: 'service. Error calling RList. Error code: ':ErrCode
end
end
end else
ErrorMsg = 'Error in ':Service: 'service. WO_LOG ':WorkOrderNo:' does not exist.'
end
end else
ErrorMsg = 'Error in ':Service: 'service. Null WorkOrderNo passed into service.'
end
If ErrorMsg NE '' then Error_Services('Add', ErrorMsg)
Response = VoidedWaferCount
end service
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -57,6 +57,8 @@ $Insert PRS_LAYER_EQUATES
$Insert PRS_STAGE_EQUATES
$Insert PROD_VER_EQUATES
$Insert QA_MET_EQUATES ;* Used in GetQAMet data structure return variable
$Insert RDS_EQUATES
$Insert WO_REACT_EQUATES
Declare function Database_Services, SRP_JSON, Error_Services, obj_Prod_Spec, Wo_Mat_Qa_Services
Declare subroutine Database_Services, SRP_JSON, Error_Services
@ -196,126 +198,164 @@ Service UpdateQAMet(WOMatKey)
WOMatQARec = ''
ErrorMsg = ''
If (WOMatKey NE '') then
WONo = Field(WOMatKey, '*', 1)
CassNo = Field(WOMatKey, '*', 2)
RDSNo = Database_Services('ReadDataColumn', 'WO_MAT', WOMatKey, WO_MAT_RDS_NO$)
If Error_Services('NoError') then
If (RDSNo NE '') then
// Check if it has been assigned to a reactor
ReactNo = Database_Services('ReadDataColumn', 'RDS', RDSNo, RDS_REACTOR$)
If Error_Services('HasError') then
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
// Either not signed into a reactor yet or this WO_MAT is EpiPro and therefore there is no
// 1-to-1 RDS record. Because of this, reactor scheduled QA met is not possible with EpiPro.
ReactNo = ''
end
If (ErrorMsg EQ '') then
WOStepKeys = Database_Services('ReadDataColumn', 'WO_LOG', WONo, WO_LOG_WO_STEP_KEY$)
If Error_Services('NoError') then
StepCnt = DCount(WOStepKeys,@VM)
MetLine = 1
// Get original WO_MAT_QA record to copy any test results
OrigWOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey)
OrigQAStages = OrigWOMatQARec<WO_MAT_QA_STAGE$>
OrigQAProfiles = OrigWOMatQARec<WO_MAT_QA_PROFILE$>
OrigQASlots = OrigWOMatQARec<WO_MAT_QA_SLOT$>
OrigQASlotTests = OrigWOMatQARec<WO_MAT_QA_SLOT_TEST$>
OrigQAResults = OrigWOMatQARec<WO_MAT_QA_RESULT$>
OrigQASigs = OrigWOMatQARec<WO_MAT_QA_SIG$>
OrigQASigDtms = OrigWOMatQARec<WO_MAT_QA_SIG_DTM$>
OrigQAStdResults = OrigWOMatQARec<WO_MAT_QA_STD_RESULT$>
OrigQADataPoints = OrigWOMatQARec<WO_MAT_QA_DATA_POINTS$>
OrigQAMinResults = OrigWOMatQARec<WO_MAT_QA_MIN_RESULT$>
OrigQAMaxResults = OrigWOMatQARec<WO_MAT_QA_MAX_RESULT$>
OrigQARangeResults = OrigWOMatQARec<WO_MAT_QA_RANGE_PCT_RESULT$>
OrigQAEdgeResults = OrigWOMatQARec<WO_MAT_QA_EDGE_MEAN_RESULT$>
OrigQA5mmResults = OrigWOMatQARec<WO_MAT_QA_5MM_PCT_RESULT$>
OrigQAOutOfSpecs = OrigWOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
OrigQAFailReasons = OrigWOMatQARec<WO_MAT_QA_FAIL_REASON$>
WONo = Field(WOMatKey, '*', 1)
CassNo = Field(WOMatKey, '*', 2)
FOR WOStepNo = 1 TO StepCnt
PSNo = Database_Services('ReadDataColumn', 'WO_STEP', WOStepKeys<1,WOStepNo>, WO_STEP_PROD_SPEC_ID$)
If Error_Services('NoError') then
PSRec = Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
If Error_Services('NoError') then
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:PSRec)
QAStages = QAMetData<COL$QA_MET_STAGE>
StageCnt = DCount(QAStages,@VM)
* * * * * * * * Build QA_MET profile - Work Order scheduled only * * * * * * * *
WOStepKeys = XLATE('WO_LOG', WONo, WO_LOG_WO_STEP_KEY$, 'X')
If (ReactNo NE '') then
WOReactKey = WONo:'*':WOStepNo:'*':ReactNo
end else
WOReactKey = ''
end
StepCnt = DCount(WOStepKeys,@VM)
If (WOReactKey NE '') then
WOReactRDSNos = Database_Services('ReadDataColumn', 'WO_REACT', WOReactKey, WO_REACT_RDS_NO$)
If Error_Services('HasError') then
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end
EpiProPSNo = ''
EpiProPSRec = ''
If (ErrorMsg EQ '') then
For StageNo = 1 to StageCnt
Stage = QAMetData<COL$QA_MET_STAGE,StageNo>
MetTest = QAMetData<COL$QA_MET_TEST,StageNo> ;* StageRec<PRS_STAGE_MET_TEST$>
Interval = QAMetData<COL$QA_MET_INTERVAL,StageNo> ;* StageRec<PRS_STAGE_MET_INTERVAL$,StageNo>
Start = QAMetData<COL$QA_MET_START,StageNo> ;* StageRec<PRS_STAGE_MET_START$,StageNo>
ReactSched = QAMetData<COL$QA_MET_REACT_SCHED,StageNo> ;* StageRec<PRS_STAGE_MET_REACT_SCHED$,StageNo>
TestFlag = False$
MetLine = 1
// Get original WO_MAT_QA record to copy any test results
OrigWOMatQARec = Database_Services('ReadDataRow', 'WO_MAT_QA', WOMatKey)
OrigQAStages = OrigWOMatQARec<WO_MAT_QA_STAGE$>
OrigQAProfiles = OrigWOMatQARec<WO_MAT_QA_PROFILE$>
OrigQASlots = OrigWOMatQARec<WO_MAT_QA_SLOT$>
OrigQASlotTests = OrigWOMatQARec<WO_MAT_QA_SLOT_TEST$>
OrigQAResults = OrigWOMatQARec<WO_MAT_QA_RESULT$>
OrigQASigs = OrigWOMatQARec<WO_MAT_QA_SIG$>
OrigQASigDtms = OrigWOMatQARec<WO_MAT_QA_SIG_DTM$>
OrigQAStdResults = OrigWOMatQARec<WO_MAT_QA_STD_RESULT$>
OrigQADataPoints = OrigWOMatQARec<WO_MAT_QA_DATA_POINTS$>
OrigQAMinResults = OrigWOMatQARec<WO_MAT_QA_MIN_RESULT$>
OrigQAMaxResults = OrigWOMatQARec<WO_MAT_QA_MAX_RESULT$>
OrigQARangeResults = OrigWOMatQARec<WO_MAT_QA_RANGE_PCT_RESULT$>
OrigQAEdgeResults = OrigWOMatQARec<WO_MAT_QA_EDGE_MEAN_RESULT$>
OrigQA5mmResults = OrigWOMatQARec<WO_MAT_QA_5MM_PCT_RESULT$>
OrigQAOutOfSpecs = OrigWOMatQARec<WO_MAT_QA_OUT_OF_SPEC$>
OrigQAFailReasons = OrigWOMatQARec<WO_MAT_QA_FAIL_REASON$>
* WO_MAT record is used to check for pre-existing signatures jch 6/7/2015
WOMatRec = Database_Services('ReadDataRow', 'WO_MAT', WOMatKey)
FOR WOStepNo = 1 TO StepCnt
PSNo = XLATE('WO_STEP', WOStepKeys<1,WOStepNo>, WO_STEP_PROD_SPEC_ID$, 'X')
PSRec = Database_Services('ReadDataRow', 'PROD_SPEC', PSNo)
QAMetData = obj_Prod_Spec('GetQAMet',PSNo:@RM:PSRec)
QAStages = QAMetData<COL$QA_MET_STAGE>
StageCnt = COUNT(QAStages,@VM) + (QAStages NE '')
FOR StageNo = 1 TO StageCnt
Stage = QAMetData<COL$QA_MET_STAGE,StageNo>
MetTest = QAMetData<COL$QA_MET_TEST,StageNo> ;* StageRec<PRS_STAGE_MET_TEST$>
Interval = QAMetData<COL$QA_MET_INTERVAL,StageNo> ;* StageRec<PRS_STAGE_MET_INTERVAL$,StageNo>
Start = QAMetData<COL$QA_MET_START,StageNo> ;* StageRec<PRS_STAGE_MET_START$,StageNo>
ReactSched = QAMetData<COL$QA_MET_REACT_SCHED,StageNo> ;* StageRec<PRS_STAGE_MET_REACT_SCHED$,StageNo>
TestFlag = 0
IF Interval NE '' AND Start NE '' THEN
IF Interval = Start THEN
IF REM(CassNo,Interval) = 0 THEN TestFlag = 1
END ELSE
IF ABS((Start + INT(CassNo/Interval)*Interval) - CassNo) = 0 THEN TestFlag = 1
END
IF TestFlag AND NOT(ReactSched) THEN
WOMatQARec<WO_MAT_QA_PROFILE$,MetLine> = WOStepNo:QAMetData<COL$QA_MET_TEST,StageNo> ;* StageRec<PRS_STAGE_MET_TEST$,N>
WOMatQARec<WO_MAT_QA_PROP$,MetLine> = QAMetData<COL$QA_MET_PROP,StageNo> ;* StageRec<PRS_STAGE_MET_PROP$,N>
WOMatQARec<WO_MAT_QA_TOOL_CLASS$,MetLine> = QAMetData<COL$QA_MET_TOOL_CLASS,StageNo> ;* StageRec<PRS_STAGE_MET_TOOL_CLASS$,N>
WOMatQARec<WO_MAT_QA_STAGE$,MetLine> = QAMetData<COL$QA_MET_STAGE,StageNo>
WOMatQARec<WO_MAT_QA_MIN$,MetLine> = QAMetData<COL$QA_MET_MIN,StageNo> ;* StageRec<PRS_STAGE_MET_MIN$,N>
WOMatQARec<WO_MAT_QA_MAX$,MetLine> = QAMetData<COL$QA_MET_MAX,StageNo> ;* StageRec<PRS_STAGE_MET_MAX$,N>
WOMatQARec<WO_MAT_QA_SLOT$,MetLine> = QAMetData<COL$QA_MET_SLOT,StageNo> ;* StageRec<PRS_STAGE_MET_SLOT$,N>
WOMatQARec<WO_MAT_QA_RECIPE$,MetLine> = QAMetData<COL$QA_MET_RECIPE,StageNo> ;* StageRec<PRS_STAGE_MET_RECIPE$,N>
WOMatQARec<WO_MAT_QA_RECIPE_PATTERN$,MetLine> = QAMetData<COL$QA_MET_RECIPE_PATTERN,StageNo> ;* StageRec<PRS_STAGE_MET_RECIPE_PATTERN$,StageNo>
WOMatQARec<WO_MAT_QA_WFR_QTY$,MetLine> = QAMetData<COL$QA_MET_WFR_QTY,StageNo> ;* StageRec<PRS_STAGE_MET_WFR_QTY$,StageNo>
WOMatQARec<WO_MAT_QA_WFR_TYPE$,MetLine> = QAMetData<COL$QA_MET_WFR_TYPE,StageNo> ;* StageRec<PRS_STAGE_MET_WFR_TYPE$,StageNo>
WOMatQARec<WO_MAT_QA_REACT_SCHED$,MetLine> = ReactSched ;* StageRec<PRS_STAGE_MET_REACT_SCHED$,StageNo>
WOMatQARec<WO_MAT_QA_SHIP_DOC$,MetLine> = QAMetData<COL$QA_MET_SHIP_DOC,StageNo> ;* StageRec<PRS_STAGE_MET_SHIP_DOC$,StageNo>
WOMatQARec<WO_MAT_QA_PHASE_MIN$,MetLine> = QAMetData<COL$QA_MET_PHASE_MIN,StageNo>
If OrigWOMatQARec NE '' then
CurrStage = QAMetData<COL$QA_MET_STAGE,StageNo>
CurrProfile = WOStepNo:QAMetData<COL$QA_MET_TEST,StageNo>
CurrSlot = QAMetData<COL$QA_MET_SLOT,StageNo>
// Copy any existing results from the original WO_MAT_QA record.
If OrigQAStages NE '' then
Found = False$
For each OrigQAStage in OrigQAStages using @VM setting sPos
OrigQAProfile = OrigQAProfiles<0, sPos>
OrigQASlot = OrigQASlots<0, sPos>
If ( (CurrStage EQ OrigQAStage) and (CurrProfile EQ OrigQAProfile) and (CurrSlot EQ OrigQASlot) ) then
Found = True$
WOMatQARec<WO_MAT_QA_SLOT_TEST$,MetLine> = OrigQASlotTests<0, sPos>
WOMatQARec<WO_MAT_QA_RESULT$,MetLine> = OrigQAResults<0, sPos>
WOMatQARec<WO_MAT_QA_SIG$,MetLine> = OrigQASigs<0, sPos>
WOMatQARec<WO_MAT_QA_SIG_DTM$,MetLine> = OrigQASigDtms<0, sPos>
WOMatQARec<WO_MAT_QA_STD_RESULT$,MetLine> = OrigQAStdResults<0, sPos>
WOMatQARec<WO_MAT_QA_DATA_POINTS$,MetLine> = OrigQADataPoints<0, sPos>
WOMatQARec<WO_MAT_QA_MIN_RESULT$,MetLine> = OrigQAMinResults<0, sPos>
WOMatQARec<WO_MAT_QA_MAX_RESULT$,MetLine> = OrigQAMaxResults<0, sPos>
WOMatQARec<WO_MAT_QA_RANGE_PCT_RESULT$,MetLine> = OrigQARangeResults<0, sPos>
WOMatQARec<WO_MAT_QA_EDGE_MEAN_RESULT$,MetLine> = OrigQAEdgeResults<0, sPos>
WOMatQARec<WO_MAT_QA_5MM_PCT_RESULT$,MetLine> = OrigQA5mmResults<0, sPos>
WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$,MetLine> = OrigQAOutOfSpecs<0, sPos>
WOMatQARec<WO_MAT_QA_FAIL_REASON$,MetLine> = OrigQAFailReasons<0, sPos>
end
Until Found
Next OrigQAStage
end
end
MetLine += 1
END
END
NEXT StageNo
NEXT WOStepNo
Database_Services('WriteDataRow', 'WO_MAT_QA', WONo:'*':CassNo, WOMatQARec)
If ( (Interval NE '') and (Start NE '') ) then
// Add Work Order scheduled tests (i.e., not reactor scheduled tests)
If Not(ReactSched) then
If Interval = Start then
If ( Rem(CassNo, Interval) EQ 0 ) then TestFlag = True$
end else
If ( Abs( (Start + Int(CassNo / Interval)*Interval) - CassNo ) EQ 0) then TestFlag = True$
end
end else
Locate RDSNo in WOReactRDSNos using @VM setting TestSeq then
If ( Rem( (TestSeq - Start), Interval) EQ 0 ) then TestFlag = True$
end
end
If TestFlag then
WOMatQARec<WO_MAT_QA_PROFILE$,MetLine> = WOStepNo:MetTest
WOMatQARec<WO_MAT_QA_PROP$,MetLine> = QAMetData<COL$QA_MET_PROP,StageNo>
WOMatQARec<WO_MAT_QA_TOOL_CLASS$,MetLine> = QAMetData<COL$QA_MET_TOOL_CLASS,StageNo>
WOMatQARec<WO_MAT_QA_STAGE$,MetLine> = Stage
WOMatQARec<WO_MAT_QA_MIN$,MetLine> = QAMetData<COL$QA_MET_MIN,StageNo>
WOMatQARec<WO_MAT_QA_MAX$,MetLine> = QAMetData<COL$QA_MET_MAX,StageNo>
WOMatQARec<WO_MAT_QA_SLOT$,MetLine> = QAMetData<COL$QA_MET_SLOT,StageNo>
WOMatQARec<WO_MAT_QA_RECIPE$,MetLine> = QAMetData<COL$QA_MET_RECIPE,StageNo>
WOMatQARec<WO_MAT_QA_RECIPE_PATTERN$,MetLine> = QAMetData<COL$QA_MET_RECIPE_PATTERN,StageNo>
WOMatQARec<WO_MAT_QA_WFR_QTY$,MetLine> = QAMetData<COL$QA_MET_WFR_QTY,StageNo>
WOMatQARec<WO_MAT_QA_WFR_TYPE$,MetLine> = QAMetData<COL$QA_MET_WFR_TYPE,StageNo>
WOMatQARec<WO_MAT_QA_REACT_SCHED$,MetLine> = ReactSched
WOMatQARec<WO_MAT_QA_SHIP_DOC$,MetLine> = QAMetData<COL$QA_MET_SHIP_DOC,StageNo>
WOMatQARec<WO_MAT_QA_PHASE_MIN$,MetLine> = QAMetData<COL$QA_MET_PHASE_MIN,StageNo>
If OrigWOMatQARec NE '' then
CurrStage = QAMetData<COL$QA_MET_STAGE,StageNo>
CurrProfile = WOStepNo:MetTest
CurrSlot = QAMetData<COL$QA_MET_SLOT,StageNo>
// Copy any existing results from the original WO_MAT_QA record.
If OrigQAStages NE '' then
Found = False$
For each OrigQAStage in OrigQAStages using @VM setting sPos
OrigQAProfile = OrigQAProfiles<0, sPos>
OrigQASlot = OrigQASlots<0, sPos>
If ( (CurrStage EQ OrigQAStage) and (CurrProfile EQ OrigQAProfile) and (CurrSlot EQ OrigQASlot) ) then
Found = True$
WOMatQARec<WO_MAT_QA_SLOT_TEST$,MetLine> = OrigQASlotTests<0, sPos>
WOMatQARec<WO_MAT_QA_RESULT$,MetLine> = OrigQAResults<0, sPos>
WOMatQARec<WO_MAT_QA_SIG$,MetLine> = OrigQASigs<0, sPos>
WOMatQARec<WO_MAT_QA_SIG_DTM$,MetLine> = OrigQASigDtms<0, sPos>
WOMatQARec<WO_MAT_QA_STD_RESULT$,MetLine> = OrigQAStdResults<0, sPos>
WOMatQARec<WO_MAT_QA_DATA_POINTS$,MetLine> = OrigQADataPoints<0, sPos>
WOMatQARec<WO_MAT_QA_MIN_RESULT$,MetLine> = OrigQAMinResults<0, sPos>
WOMatQARec<WO_MAT_QA_MAX_RESULT$,MetLine> = OrigQAMaxResults<0, sPos>
WOMatQARec<WO_MAT_QA_RANGE_PCT_RESULT$,MetLine> = OrigQARangeResults<0, sPos>
WOMatQARec<WO_MAT_QA_EDGE_MEAN_RESULT$,MetLine> = OrigQAEdgeResults<0, sPos>
WOMatQARec<WO_MAT_QA_5MM_PCT_RESULT$,MetLine> = OrigQA5mmResults<0, sPos>
WOMatQARec<WO_MAT_QA_OUT_OF_SPEC$,MetLine> = OrigQAOutOfSpecs<0, sPos>
WOMatQARec<WO_MAT_QA_FAIL_REASON$,MetLine> = OrigQAFailReasons<0, sPos>
end
Until Found
Next OrigQAStage
end
end
MetLine += 1
end
end
Next StageNo
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
Until (ErrorMsg NE '')
Next WOStepNo
If (ErrorMsg EQ '') then
Database_Services('WriteDataRow', 'WO_MAT_QA', WONo:'*':CassNo, WOMatQARec)
If Error_Services('HasError') then ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end
end else
ErrorMsg = 'Error in ':Service:' service. Error message: ':Error_Services('GetMessage')
end
end else
ErrorMsg = 'Error in ':Service:' service. Null WOMatKey passed in.'
end
If ErrorMsg NE '' then
If (ErrorMsg NE '') then
Error_Services('Add', ErrorMsg)
end else
Response = WOMatQARec
@ -521,4 +561,3 @@ Service GetMUWaferQAComplete(WOMatKey)
end service