2355 lines
92 KiB
Plaintext
2355 lines
92 KiB
Plaintext
Compile function Report_Services(@Service, @Params)
|
|
/***********************************************************************************************************************
|
|
|
|
Name : Report_Services
|
|
|
|
Description : Handler program for all Report 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)
|
|
10/30/20 djs Original programmer.
|
|
|
|
|
|
***********************************************************************************************************************/
|
|
#pragma precomp SRP_PreCompiler
|
|
|
|
$Insert SERVICE_SETUP
|
|
$Insert LOGICAL
|
|
$Insert OIPRINT_EQUATES
|
|
$Insert SCHED_DET_EQUATES
|
|
$Insert WO_LOG_EQUATES
|
|
$Insert APPCOLORS
|
|
$Insert MSG_EQUATES
|
|
$Insert SCHEDULE_EQU
|
|
$Insert LOCATION_EQUATES
|
|
$Insert RLIST_EQUATES
|
|
$Insert DICT_EQUATES
|
|
$Insert DAILY_METRICS_EQUATES
|
|
$Insert RDS_EQUATES
|
|
$Insert DAILY_PERFORMANCE_EQUATES
|
|
$Insert DAILY_PERFORMANCE_REPORT_EQUATES
|
|
$Insert SCHED_DET_NG_EQUATES
|
|
$Insert MAKEUP_WAFERS_EQUATES
|
|
$Insert REACTOR_EQUATES
|
|
$Insert WAFER_COUNTER_EQUATES
|
|
$Insert REACTOR_DAILY_UPTIME_EQUATES
|
|
$Insert MATERIAL_REPORT_EQUATES
|
|
|
|
// Reduce modes (for Select statement)
|
|
Equ NEW_EXIST$ To 0
|
|
Equ NEXT_CUR$ To 1
|
|
Equ ADD_EXIST$ To 2
|
|
|
|
Declare subroutine Utility, ErrMsg, Set_Status, Set_Printer, RList, SRP_Stopwatch, Btree.Extract, Error_Services, V119
|
|
Declare subroutine Push.Select, Pop.Select, Database_Services, SRP_JSON, Logging_Services, Reduce, FSMsg
|
|
Declare subroutine Report_Services, Make.List, Update_Index
|
|
Declare function Set_Printer, Get_Printer, Msg, Get_Status, Printer_Select, obj_Install, Dialog_Box, obj_Location
|
|
Declare function Schedule_Services, Error_Services, Location_Services, SRP_Array, Signature_Services, obj_RDS_Test
|
|
Declare function Epi_Part_Services, SRP_Math, Database_Services, SRP_JSON, Reactor_Services, SRP_Datetime
|
|
Declare function SRP_Array, Environment_Services, Logging_Services, Datetime, Select_Into, Wafer_Counter_Services
|
|
Declare function Lot_Services, Test_Run_Services
|
|
|
|
Equ TAB TO \09\
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\RDS'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' WAFERS_IN.csv'
|
|
Headers = 'Logging DTM' : @FM : 'RDS Key ID' : @FM : 'WAFERS_IN'
|
|
objWafersLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\Report_Services'
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' CalcDailyPerformanceData.csv'
|
|
Headers = 'Logging DTM' : @FM : 'Service Step' : @FM : 'Service Notes'
|
|
objReportsLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)
|
|
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
GoToService
|
|
|
|
Return Response or ""
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Service Parameter Options
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
Options BOOLEAN = True$, False$
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Services
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Service GetMakeupInventoryReportJSON()
|
|
|
|
clearselect
|
|
Statement1 = 'LIST MAKEUP_WAFERS WO_NO CASS_NO CUST_NO CUST_PART_NO EPI_PART_NO PROD_ORD_NO PROD_VER_NO PS_NO RDS_NO REACT_TYPE SAP_BATCH_NO UNLOAD_DTM WAFER_SIZE WM_OUT_NO WFR_QTY EXPIRED BY WAFER_SIZE BY PS_NO'
|
|
MUInv = Select_Into(Statement1, 'EDT')
|
|
|
|
If Error_Services('NoError') then
|
|
MUInvJSON = ''
|
|
objJSON = ''
|
|
If SRP_JSON(objJSON, 'New', 'Object') then
|
|
objReactArray = ''
|
|
If SRP_JSON(objReactArray, 'New', 'Array') then
|
|
For each Row in MUInv using @FM setting fPos
|
|
objRow = ''
|
|
If SRP_JSON(objRow, 'New', 'Object') then
|
|
SRP_JSON(objRow, 'SetValue', 'workOrderNo', Row<0, 2>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'cassNo', Row<0, 3>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'custNo', Row<0, 4>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'custPartNo', Row<0, 5>)
|
|
SRP_JSON(objRow, 'SetValue', 'epiPartNo', Row<0, 6>)
|
|
SRP_JSON(objRow, 'SetValue', 'prodOrderNo', Row<0, 7>)
|
|
SRP_JSON(objRow, 'SetValue', 'prodVerNo', Row<0, 8>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'prodSpecNo', Row<0, 9>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'rdsNo', Row<0, 10>, 'number')
|
|
SRP_JSON(objRow, 'SetValue', 'reactType', Row<0, 11>)
|
|
SRP_JSON(objRow, 'SetValue', 'sapBatchNo', Row<0, 12>)
|
|
SRP_JSON(objRow, 'SetValue', 'unloadDtm', Row<0, 13>)
|
|
SRP_JSON(objRow, 'SetValue', 'wfrSize', Row<0, 14>)
|
|
SRP_JSON(objRow, 'SetValue', 'wmOutNo', Row<0, 15>)
|
|
SRP_JSON(objRow, 'SetValue', 'wfrQty', Row<0, 16>, 'number')
|
|
|
|
ReactType = Xlate('WO_MAT', Row<0, 2>:'*':Row<0, 3>, 'REACTOR_TYPE', 'X')
|
|
If ReactType NE 'EPP' then
|
|
LotID = Row<0, 10>
|
|
end else
|
|
LotID = Row<0, 2>:'*1*':Row<0, 3>
|
|
end
|
|
WcRec = Wafer_Counter_Services('GetLastScan', LotID, 'MU')
|
|
WcQty = WcRec<WAFER_COUNTER.SCAN_QTY$>
|
|
WcDtm = WcRec<WAFER_COUNTER.SCAN_DTM$>
|
|
|
|
SRP_JSON(objRow, 'SetValue', 'muWaferCounterQty', WcQty)
|
|
SRP_JSON(objRow, 'SetValue', 'muWaferCounterDtm', WcDtm)
|
|
|
|
SRP_JSON(objRow, 'SetValue', 'expired', IConv(Row<0, 17>, 'B'), 'Boolean')
|
|
|
|
SRP_JSON(objReactArray, 'Add', objRow)
|
|
SRP_JSON(objRow, 'Release')
|
|
end
|
|
Next Row
|
|
SRP_JSON(objJSON, 'Set', 'MUInvReport', objReactArray)
|
|
SRP_JSON(objReactArray, 'Release')
|
|
end
|
|
Response = SRP_JSON(objJSON, 'Stringify', 'Styled')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end
|
|
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GenerateEPPMetReport(DateFrom, DateTo, EpiPartNo, ExportDir)
|
|
|
|
ReportData = ''
|
|
ErrorMsg = ''
|
|
If ( (DateFrom NE '') and (EpiPartNo NE '') and (ExportDir NE '') ) then
|
|
If DateTo EQ '' then
|
|
DateTo = Date()
|
|
end else
|
|
If Not(Num(DateTo)) then DateTo = IConv(DateTo, 'D')
|
|
end
|
|
If Not(Num(DateFrom)) then DateFrom = IConv(DateFrom, 'D')
|
|
// Select WM_OUT keys
|
|
WMOList = ''
|
|
Query = 'SELECT WM_OUT WITH PART_NO EQ ':Quote(EpiPartNo)
|
|
GoSub ClearCursors
|
|
Set_Status(0)
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
If Get_Status(ErrCode) then
|
|
ErrorMsg = 'Error in ':Service:' service. RList failed! Error code: ':ErrCode:'.'
|
|
end
|
|
If ErrorMsg EQ '' then
|
|
Def = ""
|
|
Def<MCAPTION$> = "Selecting WM_OUT records..."
|
|
Def<MTYPE$> = "GC"
|
|
Def<MEXTENT$> = @RecCount
|
|
Def<MTEXTWIDTH$> = 600
|
|
MsgUp = Msg(@WINDOW, Def) ;* Start gas guage message
|
|
Counter = 0
|
|
EOF = False$
|
|
Loop
|
|
Counter += 1
|
|
Running = Msg(@WINDOW, MsgUp, Counter, MSGINSTUPDATE$) ;* Update message
|
|
ReadNext WMOKey else EOF = True$
|
|
Until EOF
|
|
WMOList<-1> = WMOKey
|
|
Repeat
|
|
Msg(@WINDOW,MsgUp)
|
|
|
|
// Filter on RDS {DATE_OUT}
|
|
RDSList = ''
|
|
FilterWMOList = ''
|
|
NumWMO = DCount(WMOList, @FM)
|
|
|
|
Def = ""
|
|
Def<MCAPTION$> = "Filtering on dates..."
|
|
Def<MTYPE$> = "GC"
|
|
Def<MEXTENT$> = NumWMO
|
|
Def<MTEXTWIDTH$> = 600
|
|
MsgUp = Msg(@WINDOW, Def) ;* Start gas guage message
|
|
Counter = 0
|
|
|
|
For WMOIndex = 1 to NumWMO
|
|
Running = Msg(@WINDOW, MsgUp, WMOIndex, MSGINSTUPDATE$) ;* Update message
|
|
Done = False$
|
|
WMOKey = WMOList<WMOIndex>
|
|
ThisRDSList = Xlate('WM_OUT', WMOKey, 'RDS', 'X')
|
|
ThisRDSList = SRP_Array('Clean', ThisRDSList, 'TrimAndMakeUnique', @VM)
|
|
For each RDSNo in ThisRDSList using @VM
|
|
DateOut = Xlate('RDS', RDSNo, 'DATE_OUT', 'X')
|
|
If ( (DateOut GE DateFrom) and (DateOut LE DateTo) ) then
|
|
FilterWMOList<-1> = WMOKey
|
|
Done = True$
|
|
end
|
|
Until Done
|
|
Next RDSNo
|
|
Next WMOIndex
|
|
Msg(@WINDOW,MsgUp)
|
|
|
|
// Build the report
|
|
ReportData = ''
|
|
Headers = Database_Services('ReadDataRow', 'SYSLISTS', 'EPP_METROLOGY_HEADERS')
|
|
Columns = Xlate('EXPORTS', 'EPIPRO_METOROLGY', 'COLUMNS', 'X')
|
|
Swap @FM with @VM in Headers
|
|
ReportData<1> = Headers
|
|
|
|
RDSFields = Database_Services('ReadDataRow', 'DICT.RDS', '%FIELDS%')
|
|
RDSColumns = RDSFields<DICT_DISPLAY$>
|
|
RDSConvs = RDSFields<DICT_GENERIC_TYPE$>
|
|
NumWMO = DCount(FilterWMOList, @FM)
|
|
|
|
Def = ""
|
|
Def<MCAPTION$> = "Building report..."
|
|
Def<MTYPE$> = "GC"
|
|
Def<MEXTENT$> = NumWMO
|
|
Def<MTEXTWIDTH$> = 600
|
|
MsgUp = Msg(@WINDOW, Def) ;* Start gas guage message
|
|
|
|
If NumWMO GT 0 then
|
|
For each WMOKey in FilterWMOList using @FM setting fPos
|
|
Running = Msg(@WINDOW, MsgUp, fPos, MSGINSTUPDATE$) ;* Update message
|
|
RowIndex = fPos + 1
|
|
ThisRDSList = Xlate('WM_OUT', WMOKey, 'RDS', 'X')
|
|
Zones = Xlate('WM_OUT', WMOKey, 'ZONE', 'X')
|
|
Pockets = Xlate('WM_OUT', WMOKey, 'POCKET', 'X')
|
|
SAPBatchNo = Xlate('WM_OUT', WMOKey, 'SAP_BATCH_NO', 'X')
|
|
InCassNos = Xlate('WM_OUT', WMOKey, 'IN_CASS_NO', 'X')
|
|
WONo = Field(WMOKey, '*', 1)
|
|
PrevRDSNo = ''
|
|
For each RDSNo in ThisRDSList using @VM setting SlotNo
|
|
If RDSNo NE '' then
|
|
If RDSNo NE PrevRDSNo then Database_Services('ActivateRecord', 'RDS', RDSNo)
|
|
ReportRow = ''
|
|
For each Column in Columns using @VM setting cPos
|
|
Locate Column in RDSColumns using @VM setting ConvPos then
|
|
Conv = RDSConvs<0, ConvPos>
|
|
Begin Case
|
|
Case Column EQ 'WO'
|
|
ReportRow<0, cPos> = Field(WMOKey, '*', 1)
|
|
Case Column EQ 'SEQ'
|
|
ReportRow<0, cPos> = RDSNo
|
|
Case Column EQ 'ZONE'
|
|
ReportRow<0, cPos> = Zones<0, SlotNo>
|
|
Case Column EQ 'POCKET'
|
|
ReportRow<0, cPos> = Pockets<0, SlotNo>
|
|
Case Column EQ 'WM_OUT_KEY'
|
|
ReportRow<0, cPos> = WMOKey
|
|
Case Column EQ 'OUT_CASS_NO'
|
|
ReportRow<0, cPos> = Field(WMOKey, '*', 3)
|
|
Case Column EQ 'OUT_SLOT_NO'
|
|
ReportRow<0, cPos> = SlotNo
|
|
Case Column EQ 'SAP_BATCH_NO'
|
|
ReportRow<0, cPos> = SAPBatchNo
|
|
Case Column EQ 'LOT_NUM'
|
|
ReportRow<0, cPos> = Xlate('WO_MAT', WONo:'*':InCassNos<0, SlotNo>, 'LOT_NO', 'X')
|
|
Case Otherwise$
|
|
If Conv EQ '' then
|
|
ReportRow<0, cPos> = Calculate(Column)
|
|
end else
|
|
ReportRow<0, cPos> = OConv(Calculate(Column), Conv)
|
|
end
|
|
End Case
|
|
end
|
|
Next Column
|
|
PrevRDSNo = RDSNo
|
|
ReportData<-1> = ReportRow
|
|
end
|
|
Next RDSNo
|
|
|
|
Next WMOKey
|
|
end
|
|
Msg(@WINDOW,MsgUp)
|
|
Swap @VM with ',' in ReportData
|
|
Swap @FM with CRLF$ in ReportData
|
|
Set_Status(0)
|
|
OSWrite ReportData on ExportDir
|
|
ErrCode = ''
|
|
If Get_Status(ErrCode) then
|
|
ErrorMsg = 'Error in ':Service:' service. OSWrite failed! Error code: ':ErrCode:'.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null DateFrom or EpiPartNo passed in!'
|
|
end
|
|
If ErrorMsg EQ '' then
|
|
Response = ReportData
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service UpdateDailyMetrics(ReportDate)
|
|
|
|
If ReportDate NE '' then
|
|
If Not(Num(ReportDate)) then ReportDate = IConv(ReportDate, 'D')
|
|
// Get daily target
|
|
CurrDate = Date()
|
|
DailyTarget = 0
|
|
Query = 'SELECT FISCAL_QTR WITH FISCAL_YR EQ 2022 AND WITH START_DT LT ':Quote(OConv(ReportDate + 1, 'D4/'))
|
|
Query := ' AND WITH END_DT GT ':Quote(OConv(ReportDate - 1, 'D4/'))
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
If Not(Get_Status(ErrCode)) then
|
|
ReadNext FiscalQtrKey then
|
|
WorkingDays = Xlate('FISCAL_QTR', FiscalQtrKey, 'PLAN_WORKING_DAYS', 'X')
|
|
Targets = Xlate('FISCAL_QTR', FiscalQtrKey, 'THRU_TARGET', 'X')
|
|
Qtys = Xlate('FISCAL_QTR', FiscalQtrKey, 'THRU_QTY', 'X')
|
|
Locate 'Yield_Outs' in Targets using @VM setting vPos then
|
|
QtrTarget = Qtys<0, vPos>
|
|
DailyTarget = QtrTarget / WorkingDays
|
|
DailyTarget = OConv(IConv(DailyTarget, 'MD0'), 'MD0')
|
|
end
|
|
end
|
|
end
|
|
|
|
GoSub ClearCursors
|
|
|
|
// Calculate the metrics for the ReportDate
|
|
OPEN 'DICT.RDS' TO @DICT then
|
|
OPEN 'RDS' TO RDSTable then
|
|
|
|
TotalThickness24 = 0
|
|
TotalYield24 = 0
|
|
|
|
|
|
Dates = ''
|
|
CurrTime = Time()
|
|
If CurrTime LT 3600 then
|
|
// 3600 is 1:00 am -> update yesterday's metrics as well
|
|
Dates<-1> = ReportDate - 1
|
|
end
|
|
Dates<-1> = ReportDate
|
|
For each Date in Dates using @FM
|
|
|
|
TotalThickness = 0
|
|
WafersOutTotal = 0
|
|
YieldTotal = 0
|
|
ScrapTotal = 0
|
|
ProdTestTotal = 0
|
|
ProjectedYield = 0
|
|
YieldPercent = '0.00'
|
|
ThickWaferRatio = 0
|
|
|
|
SearchString = 'DATE_OUT':@VM:OConv(Date, 'D4/')
|
|
RDSKeys = ''
|
|
Option = ''
|
|
Flag = ''
|
|
Set_Status(0)
|
|
Btree.Extract(SearchString, 'RDS', @DICT, RDSKeys, Option, Flag)
|
|
IF Not(Get_Status(errCode)) then
|
|
IF RDSKeys NE '' THEN
|
|
RDSCnt = COUNT(RDSKeys,@VM) + (RDSKeys NE '')
|
|
LOOP
|
|
@ID = RDSKeys[1,@VM]
|
|
RDSKeys[1,COL2()] = ''
|
|
READ @RECORD FROM RDSTable, @ID THEN
|
|
ReactorsOut = {WAFERS_IN}
|
|
If Not(Num(ReactorsOut)) then
|
|
// Log the WafersIn value
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = @ID
|
|
LogData<3> = ReactorsOut
|
|
Logging_Services('AppendLog', objWafersLog, LogData, @RM, @FM)
|
|
ReactorsOut = ReactorsOut<1, 1, 1>
|
|
end
|
|
|
|
CustScrap = {CUST_TOT_REJ}
|
|
IFXEpiScrap = {LSL_TOT_REJ}
|
|
TestKeys = XLATE('RDS_LAYER', @RECORD<RDS_RDS_LAYER_KEYS$>, 3, 'X')
|
|
TWProd = obj_RDS_Test('ProdTestCount',TestKeys)
|
|
Reactor = @RECORD<RDS_REACTOR$>
|
|
ReactorType = XLATE('REACTOR', Reactor, REACTOR_REACT_TYPE$, 'X')
|
|
Scrap = CustScrap + IFXEpiScrap
|
|
Yield = ReactorsOut - Scrap - TWProd
|
|
WafersOutTotal += ReactorsOut
|
|
YieldTotal += Yield
|
|
ScrapTotal += Scrap
|
|
ProdTestTotal += TWProd
|
|
ThickTarget = OConv({THICK_TARGET_TOT}, 'MD3')
|
|
TotalThickness += (ReactorsOut * ThickTarget)
|
|
end
|
|
UNTIL RDSKeys = ''
|
|
REPEAT
|
|
TotalThickness = TotalThickness[1, 'F.']
|
|
end
|
|
end
|
|
|
|
If Date EQ CurrDate then
|
|
// Calculate projected yield and projected thickness
|
|
Date = Date()
|
|
CurrTime = Time()
|
|
SearchString = 'DATE_OUT':@VM:OConv((Date - 1), 'D4/'):@FM:'TIME_OUT':@VM:'>':CurrTime
|
|
YesterdayRDSKeys = ''
|
|
Option = ''
|
|
Flag = ''
|
|
Set_Status(0)
|
|
Btree.Extract(SearchString, 'RDS', @DICT, YesterdayRDSKeys, Option, Flag)
|
|
If Not(Get_Status(errCode)) then
|
|
SearchString = 'DATE_OUT':@VM:Date
|
|
TodayRDSKeys = ''
|
|
Option = ''
|
|
Flag = ''
|
|
Set_Status(0)
|
|
Btree.Extract(SearchString, 'RDS', @DICT, TodayRDSKeys, Option, Flag)
|
|
If Not(Get_Status(errCode)) then
|
|
TotalRDSKeys = SRP_Array('Join', YesterdayRDSKeys, TodayRDSKeys, 'OR', @VM)
|
|
For each RDS in TotalRDSKeys using @VM
|
|
Database_Services('ActivateRecord', 'RDS', RDS)
|
|
ReactorsOut = {WAFERS_IN}
|
|
If Not(Num(ReactorsOut)) then
|
|
// Log the WafersIn value
|
|
LogData = ''
|
|
LogData<1> = LoggingDTM
|
|
LogData<2> = RDS
|
|
LogData<3> = ReactorsOut
|
|
Logging_Services('AppendLog', objWafersLog, LogData, @RM, @FM)
|
|
ReactorsOut = ReactorsOut<1, 1, 1>
|
|
end
|
|
CustScrap = {CUST_TOT_REJ}
|
|
IFXEpiScrap = {LSL_TOT_REJ}
|
|
TestKeys = XLATE('RDS_LAYER', @RECORD<RDS_RDS_LAYER_KEYS$>, 3, 'X')
|
|
TWProd = obj_RDS_Test('ProdTestCount',TestKeys)
|
|
Reactor = @RECORD<RDS_REACTOR$>
|
|
ReactorType = XLATE('REACTOR', Reactor, REACTOR_REACT_TYPE$, 'X')
|
|
Scrap = CustScrap + IFXEpiScrap
|
|
Yield = ReactorsOut - Scrap - TWProd
|
|
TotalYield24 += Yield
|
|
TargetThick = OConv({THICK_TARGET_TOT}, 'MD3')
|
|
TotalThickness24 += TargetThick * ReactorsOut
|
|
Next RDS
|
|
TotalThickness24 = TotalThickness24[1, 'F.']
|
|
end
|
|
end
|
|
end
|
|
|
|
If WafersOutTotal GT 0 then
|
|
ThickWaferRatio = TotalThickness / WafersOutTotal
|
|
// Round to one decimal
|
|
ThickWaferRatio = OConv(IConv(ThickWaferRatio, 'MD1'), 'MD1')
|
|
// Round to two decimals
|
|
YieldPercent = (YieldTotal / WafersOutTotal) * 100
|
|
YieldPercent = OConv(IConv(YieldPercent, 'MD2'), 'MD2')
|
|
end
|
|
|
|
If WafersOutTotal EQ 0 then WafersOutTotal = ''
|
|
If YieldTotal EQ 0 then YieldTotal = ''
|
|
If TotalYield24 EQ 0 then TotalYield24 = ''
|
|
If TotalThickness EQ 0 then TotalThickness = ''
|
|
If TotalThickness24 EQ 0 then TotalThickness24 = ''
|
|
|
|
MetricsRec = ''
|
|
MetricsRec<DAILY_METRICS.WAFERS_OUT$> = WafersOutTotal
|
|
MetricsRec<DAILY_METRICS.YIELD$> = YieldTotal
|
|
MetricsRec<DAILY_METRICS.PROJECTED$> = TotalYield24
|
|
MetricsRec<DAILY_METRICS.SCRAP$> = ScrapTotal
|
|
MetricsRec<DAILY_METRICS.PROD_TEST$> = ProdTestTotal
|
|
MetricsRec<DAILY_METRICS.TARGET$> = DailyTarget
|
|
MetricsRec<DAILY_METRICS.TOTAL_THICKNESS$> = TotalThickness
|
|
MetricsRec<DAILY_METRICS.PROJECTED_THICKNESS$> = TotalThickness24
|
|
MetricsRec<DAILY_METRICS.THICKNESS_WAFER_RATIO$> = ThickWaferRatio
|
|
MetricsRec<DAILY_METRICS.YIELD_PERCENT$> = YieldPercent
|
|
Database_Services('WriteDataRow', 'DAILY_METRICS', Date, MetricsRec)
|
|
|
|
Next Date
|
|
end
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetMetricsJSON(Date)
|
|
|
|
// Get a week's worth of metrics and return them as JSON
|
|
StartDate = Date() - 6
|
|
EndDate = Date()
|
|
|
|
JSON = ''
|
|
hMetricsObj = ''
|
|
hMetricsArray = ''
|
|
hDayMetricsObj = ''
|
|
hStatusObj = ''
|
|
If SRP_JSON(hMetricsObj, 'NEW', 'OBJECT') then
|
|
If SRP_JSON(hMetricsArray, 'NEW', 'ARRAY') then
|
|
DateIndex = 1
|
|
For Date = StartDate to EndDate
|
|
MetricsRec = Database_Services('ReadDataRow', 'DAILY_METRICS', Date)
|
|
// Create new date object
|
|
SRP_JSON(hDayMetricsObj, 'NEW', 'OBJECT')
|
|
// Add values
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'date', OConv(Date, 'D4/'))
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'target', MetricsRec<DAILY_METRICS.TARGET$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'reactorOut', MetricsRec<DAILY_METRICS.WAFERS_OUT$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'yieldOut', MetricsRec<DAILY_METRICS.YIELD$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'projected', MetricsRec<DAILY_METRICS.PROJECTED$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'yieldPercent', MetricsRec<DAILY_METRICS.YIELD_PERCENT$>, 'String')
|
|
// Add object to metrics array
|
|
SRP_JSON(hMetricsArray, 'ADD', hDayMetricsObj)
|
|
SRP_JSON(hDayMetricsObj, 'RELEASE')
|
|
Next Date
|
|
end
|
|
SRP_JSON(hMetricsObj, 'SET', 'dailyMetrics', hMetricsArray)
|
|
JSON = SRP_JSON(hMetricsObj, 'STRINGIFY', 'FAST')
|
|
SRP_JSON(hMetricsArray, 'RELEASE')
|
|
SRP_JSON(hStatusObj, 'RELEASE')
|
|
end else
|
|
Error_Services('Add', 'Error creating the metrics JSON object.')
|
|
end
|
|
|
|
Response = JSON
|
|
|
|
end service
|
|
|
|
|
|
Service GetThickMetricsJSON(Date)
|
|
|
|
// Get a week's worth of metrics and return them as JSON
|
|
StartDate = Date() - 6
|
|
EndDate = Date()
|
|
|
|
JSON = ''
|
|
hMetricsObj = ''
|
|
hMetricsArray = ''
|
|
hDayMetricsObj = ''
|
|
If SRP_JSON(hMetricsObj, 'NEW', 'OBJECT') then
|
|
If SRP_JSON(hMetricsArray, 'NEW', 'ARRAY') then
|
|
DateIndex = 1
|
|
For Date = StartDate to EndDate
|
|
MetricsRec = Database_Services('ReadDataRow', 'DAILY_METRICS', Date)
|
|
// Create new date object
|
|
SRP_JSON(hDayMetricsObj, 'NEW', 'OBJECT')
|
|
// Add values
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'date', OConv(Date, 'D4/'))
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'thickness', MetricsRec<DAILY_METRICS.TOTAL_THICKNESS$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'projectedThickness', MetricsRec<DAILY_METRICS.PROJECTED_THICKNESS$>)
|
|
SRP_JSON(hDayMetricsObj, 'SETVALUE', 'thicknessWaferRatio', MetricsRec<DAILY_METRICS.THICKNESS_WAFER_RATIO$>)
|
|
// Add object to metrics array
|
|
SRP_JSON(hMetricsArray, 'ADD', hDayMetricsObj)
|
|
SRP_JSON(hDayMetricsObj, 'RELEASE')
|
|
Next Date
|
|
end
|
|
SRP_JSON(hMetricsObj, 'SET', 'dailyMetrics', hMetricsArray)
|
|
JSON = SRP_JSON(hMetricsObj, 'STRINGIFY', 'FAST')
|
|
SRP_JSON(hMetricsArray, 'RELEASE')
|
|
SRP_JSON(hStatusObj, 'RELEASE')
|
|
end else
|
|
Error_Services('Add', 'Error creating the metrics JSON object.')
|
|
end
|
|
|
|
Response = JSON
|
|
|
|
end service
|
|
|
|
|
|
Service GetMaterialTrackJSON()
|
|
|
|
ErrCode = ''
|
|
KeyList = ''
|
|
Query = 'SELECT MATERIAL_REPORT BY REACT_NO BY WO_NO'
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
If Not(Get_Status(ErrCode)) then
|
|
EOF = False$
|
|
Loop
|
|
ReadNext KeyId else EOF = True$
|
|
Until EOF
|
|
KeyList<-1> = KeyId
|
|
Repeat
|
|
If KeyList NE '' then
|
|
MatRepJSON = ''
|
|
If SRP_JSON(objJSON, 'New', 'Object') then
|
|
If SRP_JSON(objReactArray, 'New', 'Array') then
|
|
For each KeyId in KeyList using @FM setting fPos
|
|
Row = Database_Services('ReadDataRow', 'MATERIAL_REPORT', KeyId)
|
|
If Error_Services('NoError') then
|
|
KitRunOrder = Row<MATERIAL_REPORT.KIT_RO$>
|
|
PTIRunOrder = Row<MATERIAL_REPORT.PTI_RO$>
|
|
LoadRunOrder = Row<MATERIAL_REPORT.LOAD_RO$>
|
|
If KitRunOrder NE '' or PTIRunOrder NE '' or LoadRunOrder NE '' then
|
|
If SRP_JSON(objRow, 'New', 'Object') then
|
|
SRP_JSON(objRow, 'SetValue', 'KeyId', KeyId)
|
|
SRP_JSON(objRow, 'SetValue', 'ReactorNo', Row<MATERIAL_REPORT.REACT_NO$>)
|
|
SRP_JSON(objRow, 'SetValue', 'ReactorType', Row<MATERIAL_REPORT.REACT_TYPE$>)
|
|
SRP_JSON(objRow, 'SetValue', 'WorkOrderNo', Row<MATERIAL_REPORT.WO_NO$>)
|
|
SRP_JSON(objRow, 'SetValue', 'SapProdNo', Row<MATERIAL_REPORT.PROD_ORD_NO$>)
|
|
SRP_JSON(objRow, 'SetValue', 'SubPartNo', Row<MATERIAL_REPORT.SUB_PART_NO$>)
|
|
SRP_JSON(objRow, 'SetValue', 'EpiPartNo', Row<MATERIAL_REPORT.EPI_PART_NO$>)
|
|
WOQty = Row<MATERIAL_REPORT.WO_QTY$>
|
|
Swap ',' with '' in WOQty
|
|
SRP_JSON(objRow, 'SetValue', 'WoQty', WOQty)
|
|
RxQty = Row<MATERIAL_REPORT.WO_RX_QTY$>
|
|
Swap ',' with '' in RxQty
|
|
SRP_JSON(objRow, 'SetValue', 'RxQty', RxQty)
|
|
UnRelQty = Row<MATERIAL_REPORT.WO_UNREL_QTY$>
|
|
Swap ',' with '' in UnRelQty
|
|
SRP_JSON(objRow, 'SetValue', 'UnRelQty', UnRelQty)
|
|
SRP_JSON(objRow, 'SetValue', 'KitLoc', Row<MATERIAL_REPORT.KIT_LOCATION$>)
|
|
KitQty = Row<MATERIAL_REPORT.KIT_QTY$>
|
|
Swap ',' with '' in KitQty
|
|
SRP_JSON(objRow, 'SetValue', 'KitQty', KitQty)
|
|
SRP_JSON(objRow, 'SetValue', 'CassDelta', Row<MATERIAL_REPORT.CASS_DELTA$>)
|
|
Swap ',' with ', ' in KitRunOrder
|
|
SRP_JSON(objRow, 'SetValue', 'KitRunOrder', KitRunOrder)
|
|
SRP_JSON(objRow, 'SetValue', 'KitDemand', Row<MATERIAL_REPORT.KIT_DEMAND$>)
|
|
Swap ',' with ', ' in PTIRunOrder
|
|
SRP_JSON(objRow, 'SetValue', 'PtiRunOrder', PTIRunOrder)
|
|
Swap ',' with ', ' in LoadRunOrder
|
|
SRP_JSON(objRow, 'SetValue', 'LoadRunOrder', LoadRunOrder)
|
|
SRP_JSON(objRow, 'SetValue', 'Comments', Row<MATERIAL_REPORT.COMMENTS$>)
|
|
SRP_JSON(objReactArray, 'Add', objRow)
|
|
SRP_JSON(objRow, 'Release')
|
|
end
|
|
end
|
|
end
|
|
Next KeyId
|
|
SRP_JSON(objJSON, 'Set', 'MaterialReport', objReactArray)
|
|
SRP_JSON(objReactArray, 'Release')
|
|
end
|
|
Response = SRP_JSON(objJSON, 'Stringify', 'Styled')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. No rows returned.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Error calling RList. Error message: ':ErrCode)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service CalcDailyPerformanceData(DateOut)
|
|
|
|
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
|
|
Lock hSysLists, ServiceKeyID then
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '1'
|
|
LogData<3> = 'Begin service.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
Response = ''
|
|
CurrDate = Date()
|
|
CurrDTM = Datetime()
|
|
ReportDate = IConv(DateOut, 'D')
|
|
ReportData = ''
|
|
|
|
// Clear out previous daily_performance metrics
|
|
table_name = "DAILY_PERFORMANCE"
|
|
flag = ""
|
|
done = False$
|
|
CursorVar = ""
|
|
|
|
For counter = 0 To 8
|
|
ClearSelect counter
|
|
Next counter
|
|
|
|
sort_list = "DATE_OUT"
|
|
Reduce_Script = "WITH {DATE_OUT} EQ '":OConv(ReportDate, 'D4/'):"'"
|
|
mode = NEXT_CUR$
|
|
DeleteKeyList = ''
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '2'
|
|
LogData<3> = 'Calling Reduce with query "':Reduce_Script:'" using next available cursor.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
Reduce(reduce_script, sort_list, mode, table_name, Cursorvar, flag)
|
|
If flag then
|
|
Select table_name By sort_list Using Cursorvar then
|
|
Open table_name To file_var then
|
|
Loop
|
|
ReadNext KeyID Using Cursorvar By AT Else done = TRUE$
|
|
Until done
|
|
DeleteKeyList<-1> = KeyID
|
|
Repeat
|
|
End
|
|
end
|
|
End
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '3'
|
|
LogData<3> = 'Deleting selected records.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
If DeleteKeyList NE '' then
|
|
For each KeyID in DeleteKeyList using @FM
|
|
Database_Services('DeleteDataRow', 'DAILY_PERFORMANCE', KeyID, True$, False$)
|
|
Next KeyID
|
|
end
|
|
|
|
// Begin by building DAILY_PERFORMANCE data from RDS table. We will need to supplement this below
|
|
// for work orders / parts that do not have any cassettes unloaded yet.
|
|
Query = 'SELECT RDS WITH DATE_OUT EQ ':Quote(OConv(ReportDate, 'D4/')): ' BY REACTOR'
|
|
EOF = False$
|
|
ErrCode = ''
|
|
ReportData = ''
|
|
RawData = ''
|
|
|
|
// Clear cursors for good measure
|
|
For counter = 0 To 8
|
|
ClearSelect counter
|
|
Next counter
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '4'
|
|
LogData<3> = 'Selecting RDS records using query "':Query:'".'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
RowIndex = 0
|
|
If Not(Get_Status(ErrCode)) then
|
|
Loop
|
|
ReadNext KeyID else EOF = True$
|
|
Until EOF
|
|
RowIndex += 1
|
|
Database_Services('ActivateRecord', 'RDS', KeyID)
|
|
If Error_Services('NoError') then
|
|
Reactor = {REACTOR}
|
|
PSN = {PROD_SPEC_ID}
|
|
DateOut = {DATE_OUT}
|
|
PartNo = {PART_NUM}
|
|
WafersOut = {WAFERS_IN}
|
|
DtmIn = {DTM_IN}
|
|
DtmOut = {DTM_OUT}
|
|
ReportKey = DateOut:'*':Reactor:'*':PSN:'*':PartNo
|
|
ReportRow = Database_Services('ReadDataRow', 'DAILY_PERFORMANCE', ReportKey)
|
|
RepWafersOut = ReportRow<DAILY_PERFORMANCE.WAFERS_OUT$>
|
|
RepWafersOut += WafersOut
|
|
ReportRow<DAILY_PERFORMANCE.WAFERS_OUT$> = RepWafersOut
|
|
Database_Services('WriteDataRow', 'DAILY_PERFORMANCE', ReportKey, ReportRow)
|
|
end
|
|
Repeat
|
|
end
|
|
|
|
Reactors = Reactor_Services('GetReactorNumbers')
|
|
RowIndex = 0
|
|
For each ReactorNo in Reactors using @FM setting RIndex
|
|
ReactorAssign = Xlate('REACTOR', ReactorNo, 'REACT_ASSIGNMENT', 'X')
|
|
// Only report reactors that are not out of service.
|
|
If ReactorAssign NE 'O' then
|
|
KeyList = ''
|
|
ReportRow = ''
|
|
ReportRow<0, 1> = ReactorNo
|
|
|
|
// Supplement DAILY_PERFORMANCE data for work orders / parts that do not have any cassettes unloaded yet.
|
|
// Get the scheduled PSN, PartNo, and ReactType
|
|
SchedWONos = ''
|
|
SchedPSNs = ''
|
|
SchedEpiParts = ''
|
|
SchedDetKeyIDs = ''
|
|
// The below EpiPro reactors are scheduled via a "sister" reactor (e.g. 44 for 46)
|
|
If ( (ReactorNo EQ 42) or (ReactorNo EQ 46) or (ReactorNo EQ 50) or (ReactorNo EQ 54) ) then
|
|
QueryReactorNo = ReactorNo - 2
|
|
end else
|
|
QueryReactorNo = ReactorNo
|
|
end
|
|
Query = "SELECT SCHED_DET_NG WITH REACT_NO EQ ":QueryReactorNo:" AND WITH BLOCK_OUT NE 1 AND WITH START_DTM LT '":OConv(ReportDate + 1, 'DT2/^H'):"' AND WITH STOP_DTM GT '":OConv(ReportDate, 'DT2/^H'):"'"
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '5.':RIndex:'.1'
|
|
LogData<3> = 'Selecting SCHED_DET_NG records for reactor ':ReactorNo:' using query "':Query:'".'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
// Clear cursors for good measure.
|
|
For counter = 0 To 8
|
|
ClearSelect counter
|
|
Next counter
|
|
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
If Not(Get_Status(ErrCode)) then
|
|
EOF = False$
|
|
Loop
|
|
ReadNext SchedKeyID else EOF = True$
|
|
Until EOF
|
|
SchedDetKeyIDs<0, -1> = SchedKeyID
|
|
Repeat
|
|
end
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '5.':RIndex:'.2'
|
|
LogData<3> = 'Reading SCHED_DET_NG records for reactor ':ReactorNo:'.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
If SchedDetKeyIDs NE '' then
|
|
If Error_Services('NoError') then
|
|
HoursUp = ''
|
|
SchedKeys = ''
|
|
For Each SchedDetKeyID in SchedDetKeyIDs using @VM setting vPos
|
|
SchedDetRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', SchedDetKeyID)
|
|
SchedWONo = SchedDetRec<SCHED_DET_NG.WO_NO$>
|
|
SchedStartDtm = SchedDetRec<SCHED_DET_NG.START_DTM$>
|
|
SchedStopDtm = SchedDetRec<SCHED_DET_NG.STOP_DTM$>
|
|
SchedStartDt = SchedStartDTM[1, 'F.']
|
|
SchedStopDt = SchedStopDTM[1, 'F.']
|
|
Begin Case
|
|
Case SchedStopDt EQ ReportDate
|
|
// This scheduled part is ending
|
|
If SchedStopDtm GT CurrDtm then
|
|
HoursUp<0, vPos> = (CurrDtm - ReportDate) * 24
|
|
end else
|
|
HoursUp<0, vPos> = (SchedStopDtm - ReportDate) * 24
|
|
end
|
|
Case SchedStartDt EQ ReportDate
|
|
// This scheduled part is starting on the day of the report
|
|
Begin Case
|
|
Case SchedStartDtm GT CurrDtm
|
|
TempHours = 0
|
|
Case ReportDate EQ CurrDate
|
|
TempHours = ( ( CurrDtm - SchedStartDtm) * 24 )
|
|
Case Otherwise$
|
|
TempHours = ( ( (ReportDate + 1) - SchedStartDtm) * 24 )
|
|
End Case
|
|
If TempHours LT 0 then TempHours = 0
|
|
HoursUp<0, vPos> = TempHours
|
|
Case ReportDate EQ CurrDate
|
|
// Part is still running. Calculate how long it has been up today.
|
|
HoursUp<0, vPos> = (CurrDtm - ReportDate) * 24
|
|
Case Otherwise$
|
|
HoursUp<0, vPos> = 24
|
|
End Case
|
|
SchedWONos<0, -1> = SchedWONo
|
|
SchedPSN = Xlate('WO_LOG', SchedWONo, 'PS_NO', 'X')
|
|
SchedPSNs<0, -1> = SchedPSN
|
|
SchedEpiParts<0, -1> = Xlate('WO_LOG', SchedWONo, 'EPI_PART_NO', 'X')
|
|
|
|
SchedKeys<0, -1> = SchedDetKeyID
|
|
Next SchedDetKeyID
|
|
end
|
|
end
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '5.':RIndex:'.3'
|
|
LogData<3> = 'Writing new DAILY_PERFORMANCE records reactor ':ReactorNo:'.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
RepEpiParts = SRP_Array('Clean', SchedEpiParts, 'TrimAndMakeUnique', @VM)
|
|
If RepEpiParts NE '' then
|
|
For each SchedEpiPart in RepEpiParts using @VM setting vPos
|
|
If SchedEpiPart NE '' then
|
|
Locate SchedEpiPart in SchedEpiParts using @VM setting sPos then
|
|
SchedPSN = SchedPSNs<0, sPos>
|
|
end
|
|
end else
|
|
SchedPSN = ''
|
|
end
|
|
PSN = SchedPSN
|
|
PartNo = SchedEpiPart
|
|
PerfKey = DateOut:'*':ReactorNo:'*':PSN:'*':PartNo
|
|
PerfRow = Database_Services('ReadDataRow', 'DAILY_PERFORMANCE', PerfKey)
|
|
RepWafersOut = PerfRow<DAILY_PERFORMANCE.WAFERS_OUT$>
|
|
If RepWafersOut EQ '' then RepWafersOut = 0
|
|
PerfRow<DAILY_PERFORMANCE.WAFERS_OUT$> = RepWafersOut
|
|
PerfRow<DAILY_PERFORMANCE.HOURS_ON_PART$> = OConv(IConv(HoursUp<0, vPos>, 'MD2'), 'MD2')
|
|
PerfRow<DAILY_PERFORMANCE.SCHED_DET_KEY_IDS$> = SchedKeys<0, vPos>
|
|
Database_Services('WriteDataRow', 'DAILY_PERFORMANCE', PerfKey, PerfRow)
|
|
Next SchedEpiPart
|
|
end
|
|
// Merge in Changeover data and build the report row from the DAILY_PERFORMANCE data generated above.
|
|
|
|
table_name = "DAILY_PERFORMANCE"
|
|
flag = ""
|
|
done = False$
|
|
CursorVar = ""
|
|
|
|
* Clears all cursors
|
|
For counter = 0 To 8
|
|
ClearSelect counter
|
|
Next counter
|
|
|
|
sort_list = "DATE_OUT"
|
|
Reduce_Script = "WITH {REACTOR} EQ '":ReactorNo:"' AND WITH {DATE_OUT} EQ '":OConv(ReportDate, 'D4/'):"'"
|
|
mode = NEXT_CUR$
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '5.':RIndex:'.4'
|
|
LogData<3> = 'Selecting new DAILY_PERFORMANCE records for reactor ':ReactorNo:' using query "':Reduce_Script:'" via Reduce.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
Reduce(reduce_script, sort_list, mode, table_name, Cursorvar, flag)
|
|
If flag then
|
|
Select table_name By sort_list Using Cursorvar then
|
|
Open table_name To file_var then
|
|
Loop
|
|
ReadNext KeyID Using Cursorvar By AT Else done = TRUE$
|
|
Until done
|
|
KeyList<-1> = KeyID
|
|
Repeat
|
|
End
|
|
end
|
|
End
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '5.':RIndex:'.5'
|
|
LogData<3> = 'Updating new DAILY_PERFORMANCE records for reactor ':ReactorNo:'.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
If KeyList NE '' then
|
|
// Build the final report row with data compiled above.
|
|
For each KeyID in KeyList using @FM setting fPos
|
|
WafersOut = Xlate('DAILY_PERFORMANCE', KeyID, 'WAFERS_OUT', 'X')
|
|
PSN = Field(KeyID, '*', 3)
|
|
PartNo = Field(KeyID, '*', 4)
|
|
ReactType = Xlate('REACTOR', ReactorNo, 'REACT_TYPE', 'X')
|
|
If ReactType EQ 'EPP' then ReactType = 'EPIPRO'
|
|
ReportRow<0, 2, -1> = PSN
|
|
ReportRow<0, 3, -1> = PartNo
|
|
HoursOnPart = Xlate('DAILY_PERFORMANCE', KeyID, 'HOURS_ON_PART', 'X')
|
|
ReportRow<0, 4, -1> = OConv(IConv(HoursOnPart, 'MD2'), 'MD2')
|
|
ReportRow<0, 5, -1> = WafersOut ; // ActualOuts
|
|
ReportRow<0, 6, -1> = XLATE('DAILY_PERFORMANCE', KeyID, DAILY_PERFORMANCE.SCHED_DET_KEY_IDS$, 'X')
|
|
ReportRow<0, 7> = ReactorNo
|
|
Next KeyID
|
|
ReportData<-1> = ReportRow
|
|
end
|
|
end
|
|
|
|
Next ReactorNo
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '6'
|
|
LogData<3> = 'Begin building DAILY_PERFORMANCE_REPORT rows.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
ReportKeys = ''
|
|
For each Row in ReportData using @FM setting fPos
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '6.':fPos
|
|
LogData<3> = 'Building DAILY_PERFORMANCE_REPORT row ':fPos:'.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
PSNs = Row<0, 2>
|
|
NumPSNs = DCount(Row<0, 2>, @SVM)
|
|
If NumPSNs GT 0 then
|
|
For PSNIndex = 1 to NumPSNs
|
|
KeyID = ReportDate:'*':Row<0, 1>:'*':Row<0, 2, PSNIndex>:'*':Row<0, 3, PSNIndex>
|
|
ReportKeys<0, -1> = KeyID
|
|
If RowExists('DAILY_PERFORMANCE_REPORT', KeyID) then
|
|
Rec = Database_Services('ReadDataRow', 'DAILY_PERFORMANCE_REPORT', KeyID)
|
|
end else
|
|
Rec = ''
|
|
end
|
|
Rec<DAILY_PERFORMANCE_REPORT.HOURS_ON_PART$> = Row<0, 4, PSNIndex>
|
|
Rec<DAILY_PERFORMANCE_REPORT.ACTUAL_OUT$> = Row<0, 5, PSNIndex>
|
|
ActualStartDTM = ''
|
|
ActualStopDTM = ''
|
|
SchedDetRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', Row<0, 6, PSNIndex>)
|
|
SchedDetStartDTM = SchedDetRec<SCHED_DET_NG.START_DTM$>
|
|
SchedDetStopDTM = SchedDetRec<SCHED_DET_NG.STOP_DTM$>
|
|
If SchedDetStartDTM LT ReportDate then
|
|
ActualStartDTM = ReportDate
|
|
end else
|
|
ActualStartDTM = SchedDetStartDTM
|
|
end
|
|
If SchedDetStopDTM GT ReportDate + 1 then
|
|
ActualStopDTM = ReportDate + 1
|
|
end else
|
|
ActualStopDTM = SchedDetStopDTM
|
|
end
|
|
Rec<DAILY_PERFORMANCE_REPORT.START_DTM$> = ActualStartDTM
|
|
Rec<DAILY_PERFORMANCE_REPORT.STOP_DTM$> = ActualStopDTM
|
|
|
|
//Get Mode Metric here
|
|
EQU PRODUCTIVE$ To 1
|
|
EQU UNSCHED$ to 2
|
|
EQU SCHED$ to 3
|
|
TotalReactorData = Reactor_Services('GetReactorUptimeMetricsByTimeSpan', Row<0, 7> , ActualStartDTM, ActualStopDTM)
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_PROD_PERCENT$> = TotalReactorData<1, PRODUCTIVE$>
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_PROD_MIN$> = TotalReactorData<2, PRODUCTIVE$>
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_UNSCHED_PERCENT$> = TotalReactorData<1, UNSCHED$>
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_UNSCHED_MIN$> = TotalReactorData<2, UNSCHED$>
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_SCHED_MIN$> = TotalReactorData<2, SCHED$>
|
|
Rec<DAILY_PERFORMANCE_REPORT.TOTAL_SCHED_PERCENT$> = TotalReactorData<1, SCHED$>
|
|
|
|
Database_Services('WriteDataRow', 'DAILY_PERFORMANCE_REPORT', KeyID, Rec)
|
|
Next PSNIndex
|
|
end else
|
|
// Nothing ran or is scheduled on this reactor
|
|
KeyID = ReportDate:'*':Row<0, 1>:'*':Row<0, 2, PSNIndex>:'*':Row<0, 3, PSNIndex>
|
|
ReportKeys<0, -1> = KeyID
|
|
If RowExists('DAILY_PERFORMANCE_REPORT', KeyID) then
|
|
Rec = Database_Services('ReadDataRow', 'DAILY_PERFORMANCE_REPORT', KeyID)
|
|
end else
|
|
Rec = ''
|
|
end
|
|
Rec<DAILY_PERFORMANCE_REPORT.HOURS_ON_PART$> = 0
|
|
Rec<DAILY_PERFORMANCE_REPORT.ACTUAL_OUT$> = 0
|
|
Database_Services('WriteDataRow', 'DAILY_PERFORMANCE_REPORT', KeyID, Rec)
|
|
end
|
|
Next Row
|
|
|
|
// Clean out any rows that weren't just generated.
|
|
table_name = "DAILY_PERFORMANCE_REPORT"
|
|
flag = ""
|
|
done = False$
|
|
CursorVar = ""
|
|
* Clears all cursors
|
|
For counter = 0 To 8
|
|
ClearSelect counter
|
|
Next counter
|
|
sort_list = "DATE_OUT"
|
|
Reduce_Script = "WITH {DATE_OUT} EQ '":OConv(ReportDate, 'D4/'):"'"
|
|
mode = NEXT_CUR$
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '7'
|
|
LogData<3> = 'Selecing DAILY_PERFORMANCE_REPORT rows to delete using query "':Reduce_Script:'" via Reduce.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
Reduce(reduce_script, sort_list, mode, table_name, Cursorvar, flag)
|
|
If flag then
|
|
Select table_name By sort_list Using Cursorvar then
|
|
Open table_name To file_var then
|
|
Loop
|
|
ReadNext KeyID Using Cursorvar By AT Else done = TRUE$
|
|
Until done
|
|
Locate KeyID in ReportKeys using @VM setting vPos else
|
|
Database_Services('DeleteDataRow', 'DAILY_PERFORMANCE_REPORT', KeyID)
|
|
end
|
|
Repeat
|
|
End
|
|
end
|
|
end
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = '8'
|
|
LogData<3> = 'End service.'
|
|
Logging_Services('AppendLog', objReportsLog, LogData, @RM, @FM)
|
|
|
|
Unlock hSysLists, ServiceKeyID else Null
|
|
end
|
|
|
|
end service
|
|
|
|
Service GenerateOrUpdateDailyReactorUptimeData()
|
|
//Generates new or updates existing Reactor uptime data for all reactors in the current day.
|
|
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
|
|
Lock hSysLists, ServiceKeyID then
|
|
Today = Date()
|
|
DataArray = ''
|
|
//ASM Reactors
|
|
ASMRecordKey = 'ASM*': Today
|
|
ASMUptimeRec = Reactor_Services('GetReactorUptimeMetricsByTypeAndTimeSpan', Today, Today + 1, 'ASM')
|
|
Database_Services('WriteDataRow', 'REACTOR_DAILY_UPTIME', ASMRecordKey, ASMUptimeRec, True$, False$, True$)
|
|
//HTR Reactors
|
|
HTRRecordKey = 'HTR*': Today
|
|
HTRUptimeRec = Reactor_Services('GetReactorUptimeMetricsByTypeAndTimeSpan', Today, Today + 1, 'HTR')
|
|
Database_Services('WriteDataRow', 'REACTOR_DAILY_UPTIME', HTRRecordKey, HTRUptimeRec, True$, False$, True$)
|
|
//EPP Reactors
|
|
EPPRecordKey = 'EPP*': Today
|
|
EPPUptimeRec = Reactor_Services('GetReactorUptimeMetricsByTypeAndTimeSpan', Today, Today + 1, 'EPP')
|
|
Database_Services('WriteDataRow', 'REACTOR_DAILY_UPTIME', EPPRecordKey, EPPUptimeRec, True$, False$, True$)
|
|
//All Reactors
|
|
ALLRecordKey = 'ALL*': Today
|
|
ALLUptimeRec = Reactor_Services('GetReactorUptimeMetricsByTypeAndTimeSpan', Today, Today + 1, 'ALL')
|
|
Database_Services('WriteDataRow', 'REACTOR_DAILY_UPTIME', ALLRecordKey, ALLUptimeRec, True$, False$, True$)
|
|
Unlock hSysLists, ServiceKeyID else Null
|
|
end
|
|
end service
|
|
|
|
Service GetDailyReactorUptimeDataJSON(ReportStartDt, ReportEndDt)
|
|
Response = ''
|
|
Begin Case
|
|
Case ReportStartDt EQ ''
|
|
Error_Services('Add', 'Start Date was not provided.')
|
|
Case ReportEndDt EQ ''
|
|
Error_Services('Add', 'End Date was not provided.')
|
|
End Case
|
|
ReportStartDT = IConv(ReportStartDt, 'D4/H')
|
|
ReportEndDt = IConv(ReportEndDt, 'D4/H')
|
|
//Calculate Days to include
|
|
FirstDay = SRP_Datetime('Date', ReportStartDt)
|
|
LastDay = SRP_Datetime('Date', ReportEndDt) - 1
|
|
DataArray = ''
|
|
ASMPeriodUptimeMinutes = 0
|
|
ASMPeriodAvailMinutes = 0
|
|
HTRPeriodUptimeMinutes = 0
|
|
HTRPeriodAvailMinutes = 0
|
|
EPPPeriodUptimeMinutes = 0
|
|
EPPPeriodAvailMinutes = 0
|
|
AllPeriodUptimeMinutes = 0
|
|
AllPeriodAvailMinutes = 0
|
|
ReactorUptimeJson = ''
|
|
//Create Root Object
|
|
If SRP_Json(ReactorUptimeJson, 'New') then
|
|
//Create an Array of days
|
|
ReactorUptimeDaysJson = ''
|
|
If SRP_Json(ReactorUptimeDaysJson, 'New', 'Array') then
|
|
//For each day create a daily uptime object
|
|
for day = FirstDay to LastDay
|
|
//Single Day Object
|
|
ASMUptimeKey = 'ASM*':day
|
|
HTRUptimeKey = 'HTR*':day
|
|
EPPUptimeKey = 'EPP*':day
|
|
AllUptimeKey = 'ALL*':day
|
|
ReactorUptimeDayJson = ''
|
|
If SRP_Json(ReactorUptimeDayJson, 'New') then
|
|
ASMUptime = 0
|
|
HTRUptime = 0
|
|
EPPUptime = 0
|
|
AllUptime = 0
|
|
If RowExists('REACTOR_DAILY_UPTIME', ASMUptimeKey) then
|
|
ASMUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', ASMUptimeKey, True$, 0)
|
|
ASMUptime = ASMUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_PERCENTAGE$>
|
|
ASMUptime = SRP_Math('ROUND', ASMUptime * 100, 2)
|
|
ASMUptimeMinutes = ASMUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_MINUTES$>
|
|
ASMAvailMinutes = ASMUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_AVAIL_MINUTES$>
|
|
ASMPeriodUptimeMinutes += ASMUptimeMinutes
|
|
ASMPeriodAvailMinutes += ASMAvailMinutes
|
|
end
|
|
If RowExists('REACTOR_DAILY_UPTIME', HTRUptimeKey) then
|
|
HTRUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', HTRUptimeKey, True$, 0)
|
|
HTRUptime = HTRUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_PERCENTAGE$>
|
|
HTRUptime = SRP_Math('ROUND', HTRUptime * 100, 2)
|
|
HTRUptimeMinutes = HTRUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_MINUTES$>
|
|
HTRAvailMinutes = HTRUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_AVAIL_MINUTES$>
|
|
HTRPeriodUptimeMinutes += HTRUptimeMinutes
|
|
HTRPeriodAvailMinutes += HTRAvailMinutes
|
|
end
|
|
If RowExists('REACTOR_DAILY_UPTIME', EPPUptimeKey) then
|
|
EPPUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', EPPUptimeKey, True$, 0)
|
|
EPPUptime = EPPUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_PERCENTAGE$>
|
|
EPPUptime = SRP_Math('ROUND', EPPUptime * 100, 2)
|
|
EPPUptimeMinutes = EPPUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_MINUTES$>
|
|
EPPAvailMinutes = EPPUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_AVAIL_MINUTES$>
|
|
EPPPeriodUptimeMinutes += EPPUptimeMinutes
|
|
EPPPeriodAvailMinutes += EPPAvailMinutes
|
|
end
|
|
If RowExists('REACTOR_DAILY_UPTIME', AllUptimeKey) then
|
|
AllUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', AllUptimeKey, True$, 0)
|
|
AllUptime = AllUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_PERCENTAGE$>
|
|
AllUptime = SRP_Math('ROUND', AllUptime * 100, 2)
|
|
AllUptimeMinutes = AllUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_MINUTES$>
|
|
AllAvailMinutes = AllUptimeRec<REACTOR_DAILY_UPTIME_TOTAL_AVAIL_MINUTES$>
|
|
AllPeriodUptimeMinutes += AllUptimeMinutes
|
|
AllPeriodAvailMinutes += AllAvailMinutes
|
|
end
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "ReportDate", Oconv(day, 'DT4/H'))
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "ASMUptime", ASMUptime)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "ASMUptimeMinutes", ASMUptimeMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "ASMAvailMinutes", ASMAvailMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "HTRUptime", HTRUptime)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "HTRUptimeMinutes", HTRUptimeMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "HTRAvailMinutes", HTRAvailMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "EPPUptime", EPPUptime)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "EPPUptimeMinutes", EPPUptimeMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "EPPAvailMinutes", EPPAvailMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "AllUptime", AllUptime)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "AllUptimeMinutes", ALLUptimeMinutes)
|
|
SRP_Json(ReactorUptimeDayJson, "SetValue", "AllAvailMinutes", ALLAvailMinutes)
|
|
SRP_Json(ReactorUptimeDaysJson, "Add", ReactorUptimeDayJson)
|
|
//Release it
|
|
SRP_Json(ReactorUptimeDayJson, "Release")
|
|
|
|
|
|
end
|
|
Next day
|
|
//Add array to root object
|
|
SRP_Json(ReactorUptimeJson, 'Set', 'Days', ReactorUptimeDaysJson)
|
|
//Close out array
|
|
SRP_Json(ReactorUptimeDaysJson, 'Release')
|
|
|
|
end
|
|
ReactorUptimeWTDJson = ''
|
|
If SRP_Json(ReactorUptimeWTDJson, 'New') then
|
|
If ASMPeriodAvailMinutes GT 0 then
|
|
ASMWTDUptimePercent = SRP_Math('ROUND', (ASMPeriodUptimeMinutes / ASMPeriodAvailMinutes) * 100, 2)
|
|
end else
|
|
ASMWTDUptimePercent = 0
|
|
end
|
|
If HTRPeriodAvailMinutes GT 0 then
|
|
HTRWTDUptimePercent = SRP_Math('ROUND', (HTRPeriodUptimeMinutes / HTRPeriodAvailMinutes) * 100, 2)
|
|
end else
|
|
HTRWTDUptimePercent = 0
|
|
end
|
|
If EPPPeriodAvailMinutes GT 0 then
|
|
EPPWTDUptimePercent = SRP_Math('ROUND', (EPPPeriodUptimeMinutes / EPPPeriodAvailMinutes) * 100, 2)
|
|
end else
|
|
EPPWTDUptimePercent = 0
|
|
end
|
|
If ALLPeriodAvailMinutes GT 0 then
|
|
ALLWTDUptimePercent = SRP_Math('ROUND', (ALLPeriodUptimeMinutes / ALLPeriodAvailMinutes) * 100, 2)
|
|
end else
|
|
ALLWTDUptimePercent = 0
|
|
end
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ASMWtdUptimeMinutes", ASMPeriodUptimeMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ASMWTDAvailMinutes", ASMPeriodAvailMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ASMWTDUptimePercent", ASMWTDUptimePercent)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "HTRWTDUptimeMinutes", HTRPeriodUptimeMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "HTRWTDAvailMinutes", HTRPeriodAvailMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "HTRWTDUptimePercent", HTRWTDUptimePercent)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "EPPWTDUptimeMinutes", EPPPeriodUptimeMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "EPPWTDAvailMinutes", EPPPeriodAvailMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "EPPWTDUptimePercent", EPPWTDUptimePercent)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ALLWTDUptimeMinutes", ALLPeriodUptimeMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ALLWTDAvailMinutes", ALLPeriodAvailMinutes)
|
|
SRP_Json(ReactorUptimeWTDJson, "SetValue", "ALLWTDUptimePercent", ALLWTDUptimePercent)
|
|
SRP_Json(ReactorUptimeJson, 'Set', 'WTDMetrics', ReactorUptimeWTDJson)
|
|
SRP_Json(ReactorUptimeWTDJson, 'Release')
|
|
end
|
|
// Now get the actual JSON
|
|
ResponseJson = SRP_Json(ReactorUptimeJson, "Stringify", "STYLED")
|
|
|
|
// All done with the root object
|
|
SRP_Json(ReactorUptimeJson, "Release")
|
|
Response = ResponseJson
|
|
end
|
|
end service
|
|
|
|
Service GetDailyPerformanceDataJSON(DateOut)
|
|
|
|
Response = ''
|
|
ReportDate = IConv(DateOut, 'D')
|
|
ReportData = ''
|
|
|
|
Query = "SELECT DAILY_PERFORMANCE_REPORT WITH DATE_OUT EQ '":DateOut:"' BY REACTOR"
|
|
RList(Query, TARGET_ACTIVELIST$, '', '', '')
|
|
If Not(Get_Status(ErrCode)) then
|
|
EOF = False$
|
|
If SRP_JSON(objJSON, 'New', 'Object') then
|
|
If SRP_JSON(objReactArray, 'New', 'Array') then
|
|
Loop
|
|
ReadNext KeyID else EOF = True$
|
|
Until EOF
|
|
Database_Services('ActivateRecord', 'DAILY_PERFORMANCE_REPORT', KeyID)
|
|
If SRP_JSON(objRow, 'New', 'Object') then
|
|
|
|
ReactorNo = Field(KeyID, '*', 2)
|
|
SRP_JSON(objRow, 'SetValue', 'reactorNo', ReactorNo)
|
|
CurrModeKeys = Xlate('REACTOR_CHILD_KEY_IDS_NG', ReactorNo, 'REACT_MODE_KEY_IDS', 'X')
|
|
CurrModeKey = CurrModeKeys<0, 1>
|
|
CurrMode = Xlate('REACT_MODE_NG', CurrModeKey, 'MODE', 'X')
|
|
SRP_JSON(objRow, 'SetValue', 'reactorType', {REACTOR_TYPE})
|
|
SRP_JSON(objRow, 'SetValue', 'currMode', CurrMode)
|
|
SRP_JSON(objRow, 'SetValue', 'psn', Field(KeyID, '*', 3))
|
|
SRP_JSON(objRow, 'SetValue', 'partNo', Field(KeyID, '*', 4))
|
|
SRP_JSON(objRow, 'SetValue', 'upHours', {HOURS_ON_PART})
|
|
SRP_JSON(objRow, 'SetValue', 'uptimePercent', {PERCENT_ON_PART})
|
|
SRP_JSON(objRow, 'SetValue', 'minutesPerWafer', {MIN_PER_WAFER})
|
|
SRP_JSON(objRow, 'SetValue', 'wafersPerDay', {WAFERS_PER_DAY})
|
|
SRP_JSON(objRow, 'SetValue', 'oee', {OEE})
|
|
SRP_JSON(objRow, 'SetValue', 'projOut', {PROJECTED_OUT})
|
|
SRP_JSON(objRow, 'SetValue', 'oeeCalculation', {OEE_CALCULATION})
|
|
SRP_JSON(objRow, 'SetValue', 'timeAdjProjOut', {TIME_ADJ_PROJECTED_OUT})
|
|
SRP_JSON(objRow, 'SetValue', 'actualOut', {ACTUAL_OUT}, 'Number')
|
|
SRP_JSON(objRow, 'SetValue', 'totalDelta', {TOTAL_DELTA})
|
|
SRP_JSON(objRow, 'SetValue', 'totalDeltaAlt', {TOTAL_DELTA_ALT})
|
|
SRP_JSON(objRow, 'SetValue', 'comments', {COMMENTS})
|
|
SRP_JSON(objRow, 'SetValue', 'projOutAlt', {PROJECTED_OUT_ALT})
|
|
SRP_JSON(objRow, 'SetValue', 'toolProdPecent', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_PROD_PERCENT$, 'X'), 2))
|
|
SRP_JSON(objRow, 'SetValue', 'toolUnschedPecent', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_UNSCHED_PERCENT$, 'X'), 2))
|
|
SRP_JSON(objRow, 'SetValue', 'toolSchedPecent', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_SCHED_PERCENT$, 'X'), 2))
|
|
SRP_JSON(objRow, 'SetValue', 'toolProdMin', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_PROD_MIN$, 'X'), 2))
|
|
SRP_JSON(objRow, 'SetValue', 'toolUnschedMin', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_UNSCHED_MIN$, 'X'), 2))
|
|
SRP_JSON(objRow, 'SetValue', 'toolSchedMin', SRP_MATH('ROUND',Xlate('DAILY_PERFORMANCE_REPORT', @ID, DAILY_PERFORMANCE_REPORT.TOTAL_SCHED_MIN$, 'X'), 2))
|
|
SRP_JSON(objReactArray, 'Add', objRow)
|
|
SRP_JSON(objRow, 'Release')
|
|
end
|
|
Repeat
|
|
SRP_JSON(objJSON, 'Set', 'performanceReport', objReactArray)
|
|
SRP_JSON(objReactArray, 'Release')
|
|
end
|
|
end
|
|
Response = SRP_JSON(objJSON, 'Stringify', 'Styled')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service UpdateDailyPerformanceData(RepDate, RepJSON)
|
|
|
|
If ( (RepDate NE '') and (RepJSON NE '') ) then
|
|
If (SRP_JSON(objJSON, 'Parse', RepJSON) EQ '') then
|
|
objArray = SRP_JSON(objJSON, 'Get', 'performanceReport')
|
|
ArrayCount = SRP_JSON(objArray, 'GetCount')
|
|
For ArrayIndex = 1 to ArrayCount
|
|
objRow = SRP_JSON(objArray, 'Get', '[':ArrayIndex:']')
|
|
ReactorNo = SRP_JSON(objRow, 'GetValue', 'reactorNo')
|
|
PSNo = SRP_JSON(objRow, 'GetValue', 'psn')
|
|
PartNo = SRP_JSON(objRow, 'GetValue', 'partNo')
|
|
Comments = SRP_JSON(objRow, 'GetValue', 'comments', '')
|
|
RepKey = IConv(RepDate, 'D'):'*':ReactorNo:'*':PSNo:'*':PartNo
|
|
RepRec = Database_Services('ReadDataRow', 'DAILY_PERFORMANCE_REPORT', RepKey)
|
|
If Error_Services('NoError') then
|
|
RepRec<DAILY_PERFORMANCE_REPORT.COMMENTS$> = Comments
|
|
Database_Services('WriteDataRow', 'DAILY_PERFORMANCE_REPORT', RepKey, RepRec)
|
|
end
|
|
SRP_JSON(objRow, 'Release')
|
|
Next ArrayIndex
|
|
SRP_JSON(objArray, 'Release')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
// Calculate the last month's worth of performance data one day at a time.
|
|
Service CalcInProcessDailyPerformanceData()
|
|
|
|
ReportDate = Database_Services('ReadDataRow', 'APP_INFO', 'PERFORMANCE_REPORT_DATE')
|
|
Report_Services('CalcDailyPerformanceData', ReportDate)
|
|
ReportDate = IConv(ReportDate, 'D')
|
|
ReportDate -= 1
|
|
If ReportDate LT Date() - 2 then ReportDate = Date()
|
|
ReportDate = OConv(ReportDate, 'D2/')
|
|
Database_Services('WriteDataRow', 'APP_INFO', 'PERFORMANCE_REPORT_DATE', ReportDate)
|
|
|
|
end service
|
|
|
|
|
|
Service GetOpenTestWaferLotWIPReportJson()
|
|
|
|
ErrorMessage = ''
|
|
JSONCollection = ''
|
|
TestWaferLots = Test_Run_Services('GetTestWaferLots', True$)
|
|
hJSONCollection = ''
|
|
If SRP_JSON(hJSONCollection, 'New', 'Object') then
|
|
hTWLotArray = ''
|
|
If SRP_JSON(hTWLotArray, 'New', 'Array') then
|
|
Abort = False$
|
|
for each TestWaferLotId in TestWaferLots using @VM
|
|
ThisLotJson = Lot_Services('ConvertLotRecordToJson', TestWaferLotId, '', '', False$)
|
|
If Error_Services('NoError') then
|
|
hTWLot = ''
|
|
If (SRP_JSON(hTWLot, 'Parse', ThisLotJson) EQ '') then
|
|
SRP_JSON(hTWLotArray, 'Add', hTWLot)
|
|
SRP_JSON(hTWLot, 'Release')
|
|
end
|
|
end else
|
|
Abort = True$
|
|
end
|
|
Until Abort
|
|
Next TestWaferLotId
|
|
If Abort EQ False$ then
|
|
SRP_JSON(hJSONCollection, 'Set', 'Lots', hTWLotArray)
|
|
end
|
|
SRP_JSON(hTWLotArray, 'Release')
|
|
end else
|
|
ErrorMessage = 'Error creating test wafer Json array.'
|
|
end
|
|
JSONCollection = SRP_JSON(hJSONCollection, 'Stringify', 'Styled')
|
|
SRP_JSON(hJSONCollection, 'Release')
|
|
end else
|
|
ErrorMessage = 'Error creating test wafer Json Collection'
|
|
end
|
|
If ErrorMessage NE '' then
|
|
Error_Services('Add', ErrorMessage)
|
|
end
|
|
Response = JSONCollection
|
|
|
|
end service
|
|
|
|
|
|
Service GenerateMaterialTrackRows()
|
|
|
|
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
|
|
Lock hSysLists, ServiceKeyID then
|
|
|
|
Abort = False$
|
|
NoMatFlag = True$
|
|
|
|
LocationFilter = ''
|
|
LocationFilter<1, 1> = 'SR*KTR]'
|
|
LocationFilter<1, 2> = '1K*PTI'
|
|
LocationFilter<1, 3> = 'CR*BE'
|
|
LocationFilter<1, 4> = 'CR*BO'
|
|
LocationFilter<1, 5> = 'CR*TUN'
|
|
LocationFilter<1, 6> = 'CR*EPR'
|
|
LocationFilter<1, 7> = 'CR*FE'
|
|
LocationFilter<1, 8> = 'CR*FEH'
|
|
LocationFilter<1, 9> = 'CR*FO'
|
|
LocationFilter<1, 10> = 'CR*FOH'
|
|
|
|
// All Possible Report Columns
|
|
AllRptColumns = ''
|
|
AllRptColumns<1, 1> = 'React No'
|
|
AllRptColumns<1, 2> = 'React Type'
|
|
AllRptColumns<1, 3> = 'WO No'
|
|
AllRptColumns<1, 4> = 'SAP Prod No'
|
|
AllRptColumns<1, 5> = 'Sub Part No'
|
|
AllRptColumns<1, 6> = 'Epi Part No'
|
|
AllRptColumns<1, 7> = 'WO Qty'
|
|
AllRptColumns<1, 8> = 'RX Qty'
|
|
AllRptColumns<1, 9> = 'UnRel Qty'
|
|
AllRptColumns<1, 10> = 'Kit Location'
|
|
AllRptColumns<1, 11> = 'Kit Qty'
|
|
AllRptColumns<1, 12> = '+/-'
|
|
AllRptColumns<1, 13> = 'Kit RO'
|
|
AllRptColumns<1, 14> = 'PTI RO'
|
|
AllRptColumns<1, 15> = 'Load'
|
|
AllRptColumns<1, 16> = 'Comments'
|
|
|
|
RptColumns = AllRptColumns
|
|
|
|
ErrorTitle = 'Error in service ':Service
|
|
ErrCode = ''
|
|
ErrorMsg = ''
|
|
|
|
OPEN 'SCHED_DET_NG' TO SchedDetTable then
|
|
OPEN 'DICT.SCHED_DET_NG' TO @DICT then
|
|
Today = Datetime()
|
|
|
|
ReactList = ''
|
|
WOList = ''
|
|
SchedDetKeys = ''
|
|
PrevReactNo = ''
|
|
PrevWO = ''
|
|
|
|
SelectSent = 'SELECT SCHED_DET_NG WITH STOP_DTM GE "':OCONV(Today, 'DT'):'" BY REACT_NO'
|
|
|
|
RList(SelectSent,TARGET_ACTIVELIST$,'','','')
|
|
IF Get_Status(errCode) THEN
|
|
ErrMsg(errCode)
|
|
Unlock hSysLists, ServiceKeyID else Null
|
|
RETURN
|
|
END
|
|
|
|
Done = 0
|
|
@ID = ''
|
|
LOOP
|
|
PrevSchedDetKey = @ID
|
|
READNEXT @ID ELSE Done = 1
|
|
UNTIL Done
|
|
READ SchedDetRec FROM SchedDetTable,@ID THEN
|
|
ReactNo = SchedDetRec<SCHED_DET_NG.REACT_NO$>
|
|
WONo = SchedDetRec<SCHED_DET_NG.WO_NO$>
|
|
If ReactNo NE '' then
|
|
LOCATE ReactNo IN ReactList BY 'AR' USING @FM SETTING Pos ELSE
|
|
ReactList = INSERT(ReactList,Pos,0,0,ReactNo)
|
|
END
|
|
END
|
|
If WONo NE '' then
|
|
LOCATE WONo IN WOList<Pos> USING @VM SETTING WPos ELSE
|
|
WOList = INSERT(WOList,Pos,-1,0,WONo)
|
|
SchedDetKeys = INSERT(SchedDetKeys,-1,0,0,@ID)
|
|
END
|
|
END
|
|
END
|
|
|
|
REPEAT
|
|
|
|
CALL Make.List(0,SchedDetKeys,SchedDetTable,@DICT)
|
|
|
|
DateRange = 'Effective ':OCONV(Date(),'D4')
|
|
|
|
RowIndex = 0
|
|
AllReportData = ''
|
|
@RECCOUNT = 0
|
|
FirstPass = 1
|
|
LastRecord = 0
|
|
FirstLine = 1
|
|
fontSpacing = 100
|
|
|
|
* Zero Accumulators For Each Break
|
|
|
|
Prev.ReactNo = ''
|
|
Last.ReactNo.Break = 1
|
|
|
|
Loop
|
|
|
|
ReactNo.Break = 0
|
|
|
|
READNEXT @ID, Which.Value ELSE
|
|
LastRecord = 1
|
|
ReactNo.Break = 1
|
|
ReactNo = Prev.ReactNo
|
|
END
|
|
|
|
S.ATID = @ID
|
|
Abort = (FirstPass and LastRecord)
|
|
If Not(Abort) then
|
|
|
|
If Not(LastRecord) then
|
|
|
|
READO @RECORD FROM SchedDetTable,@ID then
|
|
|
|
// GOTO ReadRecord
|
|
@RECCOUNT += 1
|
|
|
|
* Calculate Value(s) For Column(s)
|
|
|
|
S.ATID = {@ID}
|
|
I.ATID = S.ATID
|
|
S.ReactNo = {REACT_NO}
|
|
I.ReactNo = S.ReactNo
|
|
S.WoNo = {WO_NO}
|
|
I.WoNo = S.WoNo
|
|
S.SubPartNo = XLATE('WO_LOG', S.WoNo, 'ORD_SUB_PART_NO', 'X')
|
|
I.SubPartNo = S.SubPartNo
|
|
S.EpiPartNo = XLATE('WO_LOG', S.WoNo, WO_LOG_EPI_PART_NO$, 'X')
|
|
I.EpiPartNo = S.EpiPartNo
|
|
S.WO_Qty = Xlate('WO_LOG', {WO_NO}, WO_LOG_WO_QTY$, 'X')
|
|
I.WO_Qty = S.WO_Qty
|
|
S.WO_RX_Qty = Xlate('WO_LOG', {WO_NO}, 'RX_QTY', 'X')
|
|
I.WO_RX_Qty = S.WO_RX_Qty
|
|
S.WO_UnRel_QTY = Xlate('WO_LOG', {WO_NO}, 'UNREL_QTY', 'X')
|
|
I.WO_UnRel_QTY = S.WO_UnRel_QTY
|
|
S.REACT_TYPE = Xlate('WO_LOG', {WO_NO}, 'REACT_TYPE', 'X')
|
|
S.ProdOrdNo = Xlate('WO_LOG', {WO_NO}, 'PROD_ORD_NO', 'X')
|
|
|
|
Locate 'SR*KTR]' in LocationFilter using @VM setting vPos then
|
|
KitData = Location_Services('GetLocationCassInfo', S.WONo, 'SR*KTR]')
|
|
SWAP CRLF$ WITH @VM IN KitData
|
|
end else
|
|
KitData = ''
|
|
end
|
|
|
|
KitCassList = KitData<3>
|
|
NewKitData = ''
|
|
|
|
Swap ',' with @VM in KitData
|
|
|
|
// Filter out cassettes on hold
|
|
NewKitData<1> = KitData<1>
|
|
Swap @VM with ',' in KitCassList
|
|
For each Cass in KitCassList using ',' setting cPos
|
|
Key = S.WONo:'*':Cass
|
|
OnHold = Xlate('WO_MAT', Key, 'HOLD', 'X')
|
|
If OnHold NE True$ then
|
|
NewKitData<3, -1> = KitData<3, cPos>
|
|
end
|
|
Next Cass
|
|
|
|
LocInfo = ''
|
|
LocInfo<1> = NewKitData<1>
|
|
LocInfo<2> = DCount(NewKitData<3>, @VM)
|
|
LocInfo<3> = NewKitData<3>
|
|
Database_Services('WriteDataRow', 'WO_LOC', S.WONo:'*':'SR*KTR]', LocInfo)
|
|
|
|
NewKitData<2> = DCount(NewKitData<3>, @VM) ; // Update cassette count
|
|
KitData = NewKitData
|
|
|
|
Swap @VM with ',' in KitData
|
|
|
|
S.KitLocation = KitData<1>
|
|
I.KitLocation = S.KitLocation
|
|
|
|
S.KitCassCnt = COUNT(KitData<3>,',') + (KitData<3> NE '')
|
|
I.KitCassCnt = S.KitCassCnt
|
|
|
|
KitCassList = KitData<3>
|
|
S.KitQty = 0
|
|
For each CassNo in KitCassList using ','
|
|
S.KitQty += Xlate('WO_MAT', S.WONo:'*':CassNo, 'WAFER_QTY', 'X')
|
|
Next CassNo
|
|
I.KitQty = S.KitQty
|
|
|
|
Locate '1K*PTI' in LocationFilter using @VM setting vPos then
|
|
PTIData = Location_Services('GetLocationCassInfo', S.WONo, '1K*PTI')
|
|
SWAP CRLF$ WITH @VM IN PTIData
|
|
end else
|
|
PTIData = ''
|
|
end
|
|
PTICassList = PTIData<3>
|
|
NewPTIData = ''
|
|
|
|
Swap ',' with @VM in PTIData
|
|
// Filter out cassettes on hold
|
|
NewPTIData<1> = PTIData<1>
|
|
Swap @VM with ',' in PTICassList
|
|
For each Cass in PTICassList using ',' setting cPos
|
|
Key = S.WONo:'*':Cass
|
|
OnHold = Xlate('WO_MAT', Key, 'HOLD', 'X')
|
|
If OnHold NE True$ then
|
|
NewPTIData<3, -1> = PTIData<3, cPos>
|
|
end
|
|
Next Cass
|
|
|
|
LocInfo = ''
|
|
LocInfo<1> = '1K*PTI'
|
|
LocInfo<2> = DCount(NewPTIData<3>, @VM)
|
|
LocInfo<3> = NewPTIData<3>
|
|
Database_Services('WriteDataRow', 'WO_LOC', S.WONo:'*':'1K*PTI', LocInfo)
|
|
|
|
NewPTIData<2> = DCount(NewPTIData<3>, @VM) ; // Update cassette count
|
|
PTIData = NewPTIData
|
|
|
|
Swap @VM with ',' in PTIData
|
|
PTICassList = PTIData<3>
|
|
|
|
CRLocs = ''
|
|
CRLocs<0, -1> = 'CR*BE'
|
|
CRLocs<0, -1> = 'CR*BO'
|
|
CRLocs<0, -1> = 'CR*TUN'
|
|
CRLocs<0, -1> = 'CR*EPR'
|
|
CRLocs<0, -1> = 'CR*FE'
|
|
CRLocs<0, -1> = 'CR*FEH'
|
|
CRLocs<0, -1> = 'CR*FO'
|
|
CRLocs<0, -1> = 'CR*FOH'
|
|
|
|
LoadedData = ''
|
|
LocQueryList = ''
|
|
For each Loc in CRLocs using @VM setting crPos
|
|
Locate Loc in LocationFilter using @VM setting vPos then
|
|
LocQueryList<0, -1> = Loc
|
|
end
|
|
Next Loc
|
|
LoadedCassList = ''
|
|
ReactType = Xlate('WO_LOG', S.WONo, 'REACT_TYPE', 'X')
|
|
|
|
If ReactType NE 'EPP' then
|
|
If LocQueryList NE '' then
|
|
For each CRLoc in LocQueryList using @VM
|
|
CRLocCassList = ''
|
|
LoadedData = Location_Services('GetLocationCassInfo', S.WONo, CRLoc)
|
|
Swap CRLF$ with @VM in LoadedData
|
|
CassList = LoadedData<3>
|
|
Swap @VM with ',' in CassList
|
|
For each CassNo in CassList using ','
|
|
If ( (S.WONo NE '') and (CassNo NE '') ) then
|
|
WOMatKey = S.WONo:'*':CassNo
|
|
UnloadSigComp = Signature_Services('CheckSignature', WOMatKey, 'UNLOAD')
|
|
OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X')
|
|
CurrStatus = Xlate('WO_MAT', WOMatKey, 'CURR_STATUS', 'X')
|
|
If Not(UnloadSigComp or OnHold or (CurrStatus EQ 'REJ') ) then
|
|
CRLocCassList<0, -1> = CassNo
|
|
Locate CassNo in LoadedCassList using @VM setting vPos else
|
|
LoadedCassList<0, -1> = CassNo
|
|
end
|
|
end
|
|
end
|
|
Next CassNo
|
|
LocInfo = ''
|
|
LocInfo<3> = CRLocCassList
|
|
Database_Services('WriteDataRow', 'WO_LOC', S.WONo:'*':CRLoc, LocInfo)
|
|
Next CRLoc
|
|
end
|
|
end
|
|
|
|
* TEST FOR CONTROL BREAK(S)
|
|
|
|
IF (S.ReactNo NE Prev.ReactNo) OR ReactNo.Break THEN
|
|
ReactNo = Prev.ReactNo
|
|
Prev.ReactNo = S.ReactNo
|
|
ReactNo.Break += 1
|
|
END
|
|
|
|
IF FirstPass THEN FirstPass = False$
|
|
|
|
* Do Conversion If Any
|
|
|
|
IF S.REACTNO NE "" THEN S.REACTNO = OCONV(S.REACTNO,"MD0,")
|
|
IF S.WONO NE "" THEN S.WONO = OCONV(S.WONO,"MD0")
|
|
IF S.WO_QTY NE "" THEN S.WO_QTY = OCONV(S.WO_QTY,"MD0,")
|
|
IF S.WO_RX_QTY NE "" THEN S.WO_RX_QTY = OCONV(S.WO_RX_QTY,"MD0,")
|
|
IF S.WO_UNREL_QTY NE "" THEN S.WO_UNREL_QTY = OCONV(S.WO_UNREL_QTY,"MD0,")
|
|
|
|
* PRINT DETAIL LINE
|
|
|
|
COLDATA = ''
|
|
RowNumber = 0
|
|
|
|
/* ascending sort */
|
|
Convert @VM to ',' in KitCassList
|
|
Convert @VM to ',' in PTICassList
|
|
Convert @VM to ',' in LoadedCassList
|
|
KitCassList = SRP_Array('SortSimpleList', KitCassList, 'AscendingNumbers', ',')
|
|
PTICassList = SRP_Array('SortSimpleList', PTICassList, 'AscendingNumbers', ',')
|
|
LoadedCassList = SRP_Array('SortSimpleList', LoadedCassList, 'AscendingNumbers', ',')
|
|
|
|
CassNeeded = ''
|
|
EpiPartNo = Xlate('WO_LOG', S.WONo, 'EPI_PART_NO', 'X')
|
|
If EpiPartNo NE '' then
|
|
WPDAdjusted = Epi_Part_Services('GetAdjustedWafersPerDayScheduler', EpiPartNo, S.React_Type)
|
|
If WPDAdjusted NE '' then
|
|
CPDAdjusted = SRP_Math('CEILING', (WPDAdjusted/25) )
|
|
CassInCR = DCount(KitCassList, ',') + DCount(PTICassList, ',') + DCount(LoadedCassList, ',')
|
|
CassNeeded = CassInCR - CPDAdjusted
|
|
end
|
|
end
|
|
|
|
RowIndex += 1
|
|
Swap '.1' with '' in S.ProdOrdNo
|
|
|
|
AllReportData<RowIndex, 1> = S.ReactNo
|
|
AllReportData<RowIndex, 2> = S.React_Type
|
|
AllReportData<RowIndex, 3> = S.WONo
|
|
AllReportData<RowIndex, 4> = S.ProdOrdNo
|
|
AllReportData<RowIndex, 5> = S.SubPartNo
|
|
AllReportData<RowIndex, 6> = S.EpiPartNo
|
|
AllReportData<RowIndex, 7> = S.WO_Qty
|
|
AllReportData<RowIndex, 8> = S.WO_RX_Qty
|
|
AllReportData<RowIndex, 9> = S.WO_UnRel_Qty
|
|
AllReportData<RowIndex, 10> = S.KitLocation
|
|
AllReportData<RowIndex, 11> = S.KitQty
|
|
AllReportData<RowIndex, 12> = CassNeeded
|
|
AllReportData<RowIndex, 13> = KitCassList ; // Skip field 14, it is populated by users
|
|
AllReportData<RowIndex, 15> = PTICassList
|
|
AllReportData<RowIndex, 16> = LoadedCassList ; // Skip field 17, it is populated by users
|
|
|
|
end
|
|
end else
|
|
// Last record -> write data
|
|
|
|
Database_Services('WriteDataRow', 'SYSLISTS', 'MAT_REPORT', AllReportData)
|
|
|
|
If AllReportData NE '' then
|
|
KeyList = ''
|
|
For each Row in AllReportData using @FM setting fPos
|
|
Key = Row<0, 1> : '*': Row<0, 3> ; // Key = ReactNo * WONo
|
|
KeyList<0, -1> = Key
|
|
Convert @VM to @FM in Row
|
|
If RowExists('MATERIAL_TRACK', Key) then
|
|
// Update it
|
|
Rec = Database_Services('ReadDataRow', 'MATERIAL_REPORT', Key)
|
|
If Error_Services('NoError') then
|
|
// Preserve user input fields
|
|
Row<MATERIAL_REPORT.KIT_DEMAND$> = Rec<MATERIAL_REPORT.KIT_DEMAND$>
|
|
Row<MATERIAL_REPORT.COMMENTS$> = Rec<MATERIAL_REPORT.COMMENTS$>
|
|
Database_Services('WriteDataRow', 'MATERIAL_REPORT', Key, Row)
|
|
end
|
|
end else
|
|
// New record -> Just write it
|
|
Database_Services('WriteDataRow', 'MATERIAL_REPORT', Key, Row)
|
|
end
|
|
Next Row
|
|
|
|
// Remove rows no longer current
|
|
Open "MATERIAL_REPORT" To hTable then
|
|
Select hTable
|
|
EOF = False$
|
|
Loop
|
|
ReadNext Key else EOF = True$
|
|
Until EOF
|
|
If Not(InList(KeyList, Key, @VM)) then
|
|
Database_Services('DeleteDataRow', 'MATERIAL_REPORT', Key, True$, False$)
|
|
end
|
|
Repeat
|
|
End else
|
|
// Open table failed
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'No records selected!'
|
|
end
|
|
Until (LastRecord or Abort)
|
|
Repeat
|
|
end else
|
|
ErrorMsg = 'Unable to open "SCHED_DET_NG" table.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to open "SCHED_DET_NG" table.'
|
|
end
|
|
Unlock hSysLists, ServiceKeyID else Null
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service UpdateMaterialTrackData(MaterialTrackJSON)
|
|
|
|
If MaterialTrackJSON NE '' then
|
|
If (SRP_JSON(objJSON, 'Parse', MaterialTrackJSON) EQ '') then
|
|
objArray = SRP_JSON(objJSON, 'Get', 'MaterialReport')
|
|
ArrayCount = SRP_JSON(objArray, 'GetCount')
|
|
For ArrayIndex = 1 to ArrayCount
|
|
objRow = SRP_JSON(objArray, 'Get', '[':ArrayIndex:']')
|
|
KeyId = SRP_JSON(objRow, 'GetValue', 'KeyId')
|
|
KitDemand = SRP_JSON(objRow, 'GetValue', 'KitDemand', '')
|
|
Comments = SRP_JSON(objRow, 'GetValue', 'Comments', '')
|
|
HaveLock = Database_Services('GetKeyIDLock', 'MATERIAL_REPORT', KeyId, True$)
|
|
If HaveLock then
|
|
MatRepRec = Database_Services('ReadDataRow', 'MATERIAL_REPORT', KeyId)
|
|
If Error_Services('NoError') then
|
|
MatRepRec<MATERIAL_REPORT.KIT_DEMAND$> = KitDemand
|
|
MatRepRec<MATERIAL_REPORT.COMMENTS$> = Comments
|
|
Database_Services('WriteDataRow', 'MATERIAL_REPORT', KeyId, MatRepRec, True$, False$, False$)
|
|
end
|
|
end
|
|
SRP_JSON(objRow, 'Release')
|
|
Next ArrayIndex
|
|
SRP_JSON(objArray, 'Release')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Error parsing MaterialTrackJSON.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Empty MaterialTrackJSON passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service PrintMaterialTrackReport(RptColumns, LocationFilter, NoMatFlag, OldReport=BOOLEAN)
|
|
|
|
If OldReport EQ '' then OldReport = False$
|
|
Abort = False$
|
|
// All Possible Report Columns
|
|
AllRptColumns = ''
|
|
AllRptColumns<1, 1> = 'React No'
|
|
AllRptColumns<1, 2> = 'React Type'
|
|
AllRptColumns<1, 3> = 'WO No'
|
|
AllRptColumns<1, 4> = 'SAP Prod No'
|
|
AllRptColumns<1, 5> = 'Sub Part No'
|
|
AllRptColumns<1, 6> = 'Epi Part No'
|
|
AllRptColumns<1, 7> = 'WO Qty'
|
|
AllRptColumns<1, 8> = 'RX Qty'
|
|
AllRptColumns<1, 9> = 'UnRel Qty'
|
|
AllRptColumns<1, 10> = 'Kit Location'
|
|
AllRptColumns<1, 11> = 'Kit Qty'
|
|
AllRptColumns<1, 12> = '+/-'
|
|
AllRptColumns<1, 13> = 'Kit RO'
|
|
AllRptColumns<1, 14> = 'PTI RO'
|
|
AllRptColumns<1, 15> = 'Load'
|
|
AllRptColumns<1, 16> = 'Comments'
|
|
|
|
If Index(RptColumns, 'Comments', 1) then
|
|
AllColFmt = ''
|
|
AllColFmt<1, 1> = '+^720'
|
|
AllColFmt<1, 2> = '+<720'
|
|
AllColFmt<1, 3> = '+^1000'
|
|
AllColFmt<1, 4> = '+^1100'
|
|
AllColFmt<1, 5> = '+^1300'
|
|
AllColFmt<1, 6> = '+^1200'
|
|
AllColFmt<1, 7> = '+>720'
|
|
AllColFmt<1, 8> = '+>720'
|
|
AllColFmt<1, 9> = '+>720'
|
|
AllColFmt<1, 10> = '+^1260'
|
|
AllColFmt<1, 11> = '+^720'
|
|
AllColFmt<1, 12> = '+^500'
|
|
AllColFmt<1, 13> = '+^1300'
|
|
AllColFmt<1, 14> = '+^1300'
|
|
AllColFmt<1, 15> = '+^700'
|
|
AllColFmt<1, 16> = '+^1300'
|
|
end else
|
|
AllColFmt = ''
|
|
AllColFmt<1, 1> = '+^720'
|
|
AllColFmt<1, 2> = '+<720'
|
|
AllColFmt<1, 3> = '+^1000'
|
|
AllColFmt<1, 4> = '+^1100'
|
|
AllColFmt<1, 5> = '+^1300'
|
|
AllColFmt<1, 6> = '+^1200'
|
|
AllColFmt<1, 7> = '+>720'
|
|
AllColFmt<1, 8> = '+>720'
|
|
AllColFmt<1, 9> = '+>720'
|
|
AllColFmt<1, 10> = '+^1260'
|
|
AllColFmt<1, 11> = '+^720'
|
|
AllColFmt<1, 12> = '+^500'
|
|
AllColFmt<1, 13> = '+^1800'
|
|
AllColFmt<1, 14> = '+^1800'
|
|
AllColFmt<1, 15> = '+^1100'
|
|
AllColFmt<1, 16> = ''
|
|
end
|
|
|
|
ErrorTitle = 'Error in service ':Service
|
|
ErrCode = ''
|
|
ErrorMsg = ''
|
|
|
|
OPEN 'SCHED_DET_NG' TO SchedDetTable then
|
|
OPEN 'DICT.SCHED_DET_NG' TO @DICT then
|
|
Today = Datetime()
|
|
|
|
ReactList = ''
|
|
WOList = ''
|
|
SchedDetKeys = ''
|
|
PrevReactNo = ''
|
|
PrevWO = ''
|
|
|
|
If OldReport then
|
|
SelectSent = 'SELECT SCHED_DET_NG WITH STOP_DTM GE ':Today:' BY REACT_NO'
|
|
end else
|
|
SelectSent = 'SELECT SCHED_DET_NG WITH STOP_DTM GE "':OCONV(Today, 'DT'):'" BY REACT_NO'
|
|
end
|
|
|
|
RList(SelectSent,TARGET_ACTIVELIST$,'','','')
|
|
IF Get_Status(errCode) THEN
|
|
ErrMsg(errCode)
|
|
RETURN
|
|
END
|
|
|
|
Done = 0
|
|
@ID = ''
|
|
LOOP
|
|
PrevSchedDetKey = @ID
|
|
READNEXT @ID ELSE Done = 1
|
|
UNTIL Done
|
|
READ SchedDetRec FROM SchedDetTable,@ID THEN
|
|
ReactNo = SchedDetRec<SCHED_DET_NG.REACT_NO$>
|
|
WONo = SchedDetRec<SCHED_DET_NG.WO_NO$>
|
|
If ReactNo NE '' then
|
|
LOCATE ReactNo IN ReactList BY 'AR' USING @FM SETTING Pos ELSE
|
|
ReactList = INSERT(ReactList,Pos,0,0,ReactNo)
|
|
END
|
|
END
|
|
If WONo NE '' then
|
|
LOCATE WONo IN WOList<Pos> USING @VM SETTING WPos ELSE
|
|
WOList = INSERT(WOList,Pos,-1,0,WONo)
|
|
SchedDetKeys = INSERT(SchedDetKeys,-1,0,0,@ID)
|
|
END
|
|
END
|
|
END
|
|
|
|
REPEAT
|
|
|
|
CALL Make.List(0,SchedDetKeys,SchedDetTable,@DICT)
|
|
|
|
Header = "'D'":@VM:obj_Install('Get_Prop','CompTitle'):' Material Tracking by Reactor':@VM:"Page 'P'"
|
|
MinDemand = 0
|
|
Set_Status(0)
|
|
|
|
* Start of printing process
|
|
FileName = 'Print Material Demand'
|
|
Title = 'Printing Material Demand'
|
|
|
|
TopMargin = 1.0
|
|
BottomMargin = 0.75
|
|
LeftMargin = 0.25
|
|
RightMargin = 0.25
|
|
|
|
Margins = LeftMargin:@FM:TopMargin:@FM:RightMargin:@FM:BottomMargin
|
|
|
|
PageSetup = '1' ;* LandScape
|
|
PrintSetup = '2' ;* Preview Normal
|
|
PrintSetup<1,2> = '0' ;* All buttons
|
|
PrintSetup<1,5> = '1' ;* Page Range
|
|
PrintSetup<1,6> = 7 ;* full mouse and keyboard support
|
|
|
|
PrintPath = ''
|
|
stat = Set_Printer('INIT',FileName,Title,Margins,PageSetup,PrintSetup,PrintPath)
|
|
|
|
If Stat GE 0 THEN
|
|
DateRange = 'Effective ':OCONV(Date(),'D4')
|
|
|
|
Header<-1> = "'T'"
|
|
Header<-1> = '' ;* Blank line following heading
|
|
|
|
font = 'Arial'
|
|
font<2> = '10'
|
|
font<4> = '0' ;* Bold
|
|
|
|
stat = Set_Printer('FONTHEADFOOT',font)
|
|
If Stat GE 0 then
|
|
stat = Set_Printer('HEADER',Header)
|
|
If Stat GE 0 then
|
|
Footer = " 'D' 'T'":@VM:@VM:"Page: 'P'"
|
|
stat = Set_Printer('FOOTER',Footer)
|
|
If Stat GE 0 then
|
|
@RECCOUNT = 0
|
|
FirstPass = 1
|
|
LastRecord = 0
|
|
FirstLine = 1
|
|
fontSpacing = 100
|
|
|
|
* Make Column Heading
|
|
ColHead = ''
|
|
ColFmt = ''
|
|
|
|
For each Column in RptColumns using @VM setting rcPos
|
|
Locate Column in AllRptColumns using @VM setting dataPos then
|
|
ColHead<0, -1> = Column
|
|
ColFmt<0, -1> = AllColFmt<0, dataPos>
|
|
end
|
|
Next Column
|
|
|
|
* Zero Accumulators For Each Break
|
|
|
|
Prev.ReactNo = ''
|
|
Last.ReactNo.Break = 1
|
|
|
|
Loop
|
|
|
|
* Zero Break Flags To False
|
|
|
|
ReactNo.Break = 0
|
|
|
|
READNEXT @ID, Which.Value ELSE
|
|
LastRecord = 1
|
|
ReactNo.Break = 1
|
|
ReactNo = Prev.ReactNo
|
|
END
|
|
|
|
S.ATID = @ID
|
|
Abort = (FirstPass AND LastRecord)
|
|
IF Not(Abort) THEN
|
|
|
|
IF Not(LastRecord) then
|
|
READO @RECORD FROM SchedDetTable,@ID then
|
|
|
|
@RECCOUNT += 1
|
|
|
|
* Calculate Value(s) For Column(s)
|
|
|
|
S.ATID = {@ID}
|
|
I.ATID = S.ATID
|
|
S.ReactNo = {REACT_NO}
|
|
I.ReactNo = S.ReactNo
|
|
S.WoNo = {WO_NO}
|
|
I.WoNo = S.WoNo
|
|
S.SubPartNo = XLATE('WO_LOG', S.WoNo, 'ORD_SUB_PART_NO', 'X')
|
|
I.SubPartNo = S.SubPartNo
|
|
S.EpiPartNo = XLATE('WO_LOG', S.WoNo, WO_LOG_EPI_PART_NO$, 'X')
|
|
I.EpiPartNo = S.EpiPartNo
|
|
S.WO_Qty = Xlate('WO_LOG', {WO_NO}, WO_LOG_WO_QTY$, 'X')
|
|
I.WO_Qty = S.WO_Qty
|
|
S.WO_RX_Qty = Xlate('WO_LOG', {WO_NO}, 'RX_QTY', 'X')
|
|
I.WO_RX_Qty = S.WO_RX_Qty
|
|
S.WO_UnRel_QTY = Xlate('WO_LOG', {WO_NO}, 'UNREL_QTY', 'X')
|
|
I.WO_UnRel_QTY = S.WO_UnRel_QTY
|
|
S.REACT_TYPE = Xlate('WO_LOG', {WO_NO}, 'REACT_TYPE', 'X')
|
|
S.ProdOrdNo = Xlate('WO_LOG', {WO_NO}, 'PROD_ORD_NO', 'X')
|
|
|
|
|
|
If OldReport then
|
|
|
|
Locate 'SR*KTR]' in LocationFilter using @VM setting vPos then
|
|
KitData = Location_Services('GetLocationCassInfo', S.WONo, 'SR*KTR]')
|
|
SWAP CRLF$ WITH @VM IN KitData
|
|
end else
|
|
KitData = ''
|
|
end
|
|
|
|
S.KitLocation = KitData<1>
|
|
I.KitLocation = S.KitLocation
|
|
|
|
S.KitQty = OCONV(SUM(KitData<2>) * 25,'MD0,Z')
|
|
I.KitQty = S.KitQty
|
|
|
|
S.KitCassCnt = COUNT(KitData<3>,',') + (KitData<3> NE '')
|
|
I.KitCassCnt = S.KitCassCnt
|
|
|
|
KitCassList = KitData<3>
|
|
|
|
Locate '1K*PTI' in LocationFilter using @VM setting vPos then
|
|
PTIData = Location_Services('GetLocationCassInfo', S.WONo, '1K*PTI')
|
|
SWAP CRLF$ WITH @VM IN PTIData
|
|
end else
|
|
PTIData = ''
|
|
end
|
|
|
|
end else
|
|
|
|
Locate 'SR*KTR]' in LocationFilter using @VM setting vPos then
|
|
KitData = Database_Services('ReadDataRow', 'WO_LOC', S.WONo:'*':'SR*KTR]')
|
|
end else
|
|
KitData = ''
|
|
end
|
|
|
|
Swap @VM with ',' in KitData
|
|
|
|
S.KitLocation = KitData<1>
|
|
I.KitLocation = S.KitLocation
|
|
|
|
S.KitCassCnt = COUNT(KitData<3>,',') + (KitData<3> NE '')
|
|
I.KitCassCnt = S.KitCassCnt
|
|
|
|
KitCassList = KitData<3>
|
|
S.KitQty = 0
|
|
For each CassNo in KitCassList using ','
|
|
S.KitQty += Xlate('WO_MAT', S.WONo:'*':CassNo, 'WAFER_QTY', 'X')
|
|
Next CassNo
|
|
I.KitQty = S.KitQty
|
|
|
|
Locate '1K*PTI' in LocationFilter using @VM setting vPos then
|
|
PTIData = Database_Services('ReadDataRow', 'WO_LOC', S.WONo:'*':'1K*PTI')
|
|
end else
|
|
PTIData = ''
|
|
end
|
|
PTICassList = PTIData<3>
|
|
|
|
Swap @VM with ',' in PTIData
|
|
|
|
end
|
|
|
|
PTICassList = PTIData<3>
|
|
|
|
CRLocs = ''
|
|
CRLocs<0, -1> = 'CR*BE'
|
|
CRLocs<0, -1> = 'CR*BO'
|
|
CRLocs<0, -1> = 'CR*TUN'
|
|
CRLocs<0, -1> = 'CR*EPR'
|
|
CRLocs<0, -1> = 'CR*FE'
|
|
CRLocs<0, -1> = 'CR*FEH'
|
|
CRLocs<0, -1> = 'CR*FO'
|
|
CRLocs<0, -1> = 'CR*FOH'
|
|
|
|
LoadedData = ''
|
|
LocQueryList = ''
|
|
For each Loc in CRLocs using @VM setting crPos
|
|
Locate Loc in LocationFilter using @VM setting vPos then
|
|
LocQueryList<0, -1> = Loc
|
|
end
|
|
Next Loc
|
|
LoadedCassList = ''
|
|
ReactType = Xlate('WO_LOG', S.WONo, 'REACT_TYPE', 'X')
|
|
If ReactType NE 'EPP' then
|
|
If LocQueryList NE '' then
|
|
If OldReport then
|
|
LoadedData = Location_Services('GetLocationCassInfo', S.WONo, LocQueryList)
|
|
Swap CRLF$ with @VM in LoadedData
|
|
CassList = LoadedData<3>
|
|
Swap @VM with ',' in CassList
|
|
For each CassNo in CassList using ','
|
|
If ( (S.WONo NE '') and (CassNo NE '') ) then
|
|
WOMatKey = S.WONo:'*':CassNo
|
|
UnloadSigComp = Signature_Services('CheckSignature', WOMatKey, 'UNLOAD')
|
|
OnHold = Xlate('WO_MAT', WOMatKey, 'HOLD', 'X')
|
|
CurrStatus = Xlate('WO_MAT', WOMatKey, 'CURR_STATUS', 'X')
|
|
If Not(UnloadSigComp or OnHold or (CurrStatus EQ 'REJ') ) then
|
|
LoadedCassList<0, -1> = CassNo
|
|
end
|
|
end
|
|
Next CassNo
|
|
end else
|
|
For each CRLoc in LocQueryList using @VM
|
|
CRLocInfo = Database_Services('ReadDataRow', 'WO_LOC', S.WONo:'*':CRLoc)
|
|
CRLocCassList = CRLocInfo<3>
|
|
LoadedCassList = SRP_Array('Join', LoadedCassList, CRLocCassList, 'OR', @VM)
|
|
Next CRLoc
|
|
end
|
|
end
|
|
end
|
|
|
|
If Not(OldReport) then LoadedCassList = SRP_Array('Clean', LoadedCassList, 'TrimAndMakeUnique', @VM)
|
|
* TEST FOR CONTROL BREAK(S)
|
|
|
|
IF (S.ReactNo NE Prev.ReactNo) OR ReactNo.Break THEN
|
|
ReactNo = Prev.ReactNo
|
|
Prev.ReactNo = S.ReactNo
|
|
ReactNo.Break += 1
|
|
END
|
|
|
|
IF ReactNo.Break THEN stat = Set_Printer('TEXT')
|
|
|
|
IF FirstPass THEN FirstPass = False$
|
|
|
|
* Do Conversion If Any
|
|
|
|
IF S.REACTNO NE "" THEN S.REACTNO = OCONV(S.REACTNO,"MD0,")
|
|
IF S.WONO NE "" THEN S.WONO = OCONV(S.WONO,"MD0")
|
|
IF S.WO_QTY NE "" THEN S.WO_QTY = OCONV(S.WO_QTY,"MD0,")
|
|
IF S.WO_RX_QTY NE "" THEN S.WO_RX_QTY = OCONV(S.WO_RX_QTY,"MD0,")
|
|
IF S.WO_UNREL_QTY NE "" THEN S.WO_UNREL_QTY = OCONV(S.WO_UNREL_QTY,"MD0,")
|
|
|
|
* PRINT DETAIL LINE
|
|
|
|
COLDATA = ''
|
|
RowNumber = 0
|
|
|
|
/* ascending sort */
|
|
Convert @VM to ',' in KitCassList
|
|
Convert @VM to ',' in PTICassList
|
|
Convert @VM to ',' in LoadedCassList
|
|
KitCassList = SRP_Array('SortSimpleList', KitCassList, 'AscendingNumbers', ',')
|
|
PTICassList = SRP_Array('SortSimpleList', PTICassList, 'AscendingNumbers', ',')
|
|
LoadedCassList = SRP_Array('SortSimpleList', LoadedCassList, 'AscendingNumbers', ',')
|
|
|
|
Convert ',' to @VM in KitCassList
|
|
Convert ',' to @VM in PTICassList
|
|
Convert ',' to @VM in LoadedCassList
|
|
|
|
NumKitCass = DCount(KitCassList, @VM)
|
|
If NumKitCass GT 4 then
|
|
For CassIndex = 4 to NumKitCass Step 4
|
|
CassNo = KitCassList<0, CassIndex>
|
|
CassNo := CRLF$
|
|
KitCassList<0, CassIndex> = CassNo
|
|
Next CassIndex
|
|
end
|
|
NumPTICass = DCount(PTICassList, @VM)
|
|
If NumPTICass GT 4 then
|
|
For CassIndex = 4 to NumPTICass Step 4
|
|
CassNo = PTICassList<0, CassIndex>
|
|
CassNo := CRLF$
|
|
PTICassList<0, CassIndex> = CassNo
|
|
Next CassIndex
|
|
end
|
|
NumLoadedCass = DCount(LoadedCassList, @VM)
|
|
If NumLoadedCass GT 2 then
|
|
For CassIndex = 2 to NumLoadedCass Step 2
|
|
CassNo = LoadedCassList<0, CassIndex>
|
|
CassNo := CRLF$
|
|
LoadedCassList<0, CassIndex> = CassNo
|
|
Next CassIndex
|
|
end
|
|
Convert @VM to ',' in KitCassList
|
|
Convert @VM to ',' in PTICassList
|
|
Convert @VM to ',' in LoadedCassList
|
|
|
|
CassNeeded = ''
|
|
EpiPartNo = Xlate('WO_LOG', S.WONo, 'EPI_PART_NO', 'X')
|
|
If EpiPartNo NE '' then
|
|
WPDAdjusted = Epi_Part_Services('GetAdjustedWafersPerDayScheduler', EpiPartNo, S.React_Type)
|
|
If WPDAdjusted NE '' then
|
|
CPDAdjusted = SRP_Math('CEILING', (WPDAdjusted/25) )
|
|
CassInCR = DCount(KitCassList, ',') + DCount(PTICassList, ',') + DCount(LoadedCassList, ',')
|
|
CassNeeded = CassInCR - CPDAdjusted
|
|
end
|
|
end
|
|
|
|
Swap '.1' with '' in S.ProdOrdNo
|
|
AllReportData = ''
|
|
AllReportData<1> = S.ReactNo
|
|
AllReportData<2> = S.React_Type
|
|
AllReportData<3> = S.WONo
|
|
AllReportData<4> = S.ProdOrdNo
|
|
AllReportData<5> = S.SubPartNo
|
|
AllReportData<6> = S.EpiPartNo
|
|
AllReportData<7> = S.WO_Qty
|
|
AllReportData<8> = S.WO_RX_Qty
|
|
AllReportData<9> = S.WO_UnRel_Qty
|
|
AllReportData<10> = S.KitLocation
|
|
AllReportData<11> = S.KitQty
|
|
AllReportData<12> = CassNeeded
|
|
AllReportData<13> = KitCassList
|
|
AllReportData<14> = PTICassList
|
|
AllReportData<15> = LoadedCassList
|
|
AllReportData<16> = ''
|
|
|
|
If ( (KitCassList NE '') or (PTICassList NE '') or (LoadedCassList NE '') or (NoMatFlag EQ True$) ) then
|
|
RowNumber += 1
|
|
For each RptColumn in RptColumns using @VM setting rcPos
|
|
Locate RptColumn in AllRptColumns using @VM setting dataPos then
|
|
COLDATA<RowNumber,rcPos> = AllReportData<dataPos>
|
|
end
|
|
Next RptColumn
|
|
If COLDATA NE '' then
|
|
// Print the data
|
|
PageHeight = Get_Printer('PAGESIZE')<2>
|
|
PrintableHeight = PageHeight - TopMargin - BottomMargin
|
|
PrinterHeight = Get_Printer('POS')<2>
|
|
stat = Set_Printer('CALCTABLE',ColFmt:@FM:ColData)
|
|
TableSize = Get_Printer('CALCTABLE')
|
|
TableHeight = TableSize<2>
|
|
fontSpacing = 120
|
|
|
|
IF ( TableHeight + PrinterHeight >= PrintableHeight ) OR FirstLine THEN
|
|
IF NOT(FirstLine) THEN
|
|
stat = Set_Printer('PAGEBREAK')
|
|
END
|
|
FirstLine = 0
|
|
font<2> = 10
|
|
font<4> = 1 ;* Bold
|
|
stat = Set_Printer('FONT',font,'100')
|
|
stat = Set_Printer('ADDTABLE',colFmt,colHead,'',LTGREY$,'',0,TB_ALL)
|
|
font<4> = 0
|
|
stat = Set_Printer('FONT',font,fontSpacing)
|
|
stat = Set_Printer('ADDTABLE',colFmt,'',colData,LTGREY$,'',0,7)
|
|
END ELSE
|
|
font<2> = 10
|
|
font<4> = 0
|
|
stat = Set_Printer('FONT',font,fontSpacing)
|
|
stat = Set_Printer('ADDTABLE',colFmt,'',colData,LTGREY$,'',1,TB_ALL)
|
|
END
|
|
end
|
|
END
|
|
end
|
|
end else
|
|
// Last record -> Finish printing
|
|
colData = ''
|
|
stat = Set_Printer('TERM',1)
|
|
end
|
|
END else
|
|
// No records selected -> Bail
|
|
stat = Set_Printer('TERM',1)
|
|
end
|
|
Until (LastRecord or Abort)
|
|
Repeat
|
|
end else
|
|
GoSub OipiPrintError
|
|
end
|
|
end else
|
|
GoSub OipiPrintError
|
|
end
|
|
end else
|
|
GoSub OipiPrintError
|
|
end
|
|
end else
|
|
ErrorMsg = 'Stat = ' : Stat : ', PrintPath = ' : PrintPath
|
|
GoSub OipiPrintError
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to open "SCHED_DET_NG" table.'
|
|
ErrMsg(ErrorTitle:@SVM:ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to open "SCHED_DET_NG" table.'
|
|
ErrMsg(ErrorTitle:@SVM:ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Internal GoSubs
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ClearCursors:
|
|
|
|
For counter = 0 to 8
|
|
ClearSelect counter
|
|
Next counter
|
|
|
|
return
|
|
|
|
|
|
OipiPrintError:
|
|
|
|
ErrMsg(ErrorTitle:@SVM:ErrorMsg)
|
|
ErrMsg(ErrorTitle:@SVM:'Set_Printer returned errorcode ':stat)
|
|
stat = Set_Printer('TERM',1)
|
|
|
|
return
|
|
|