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, NCR_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 WcDtm = WcRec 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 = "Selecting WM_OUT records..." Def = "GC" Def = @RecCount Def = 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 = "Filtering on dates..." Def = "GC" Def = NumWMO Def = 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 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 RDSConvs = RDSFields NumWMO = DCount(FilterWMOList, @FM) Def = "" Def = "Building report..." Def = "GC" Def = NumWMO Def = 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, 3, 'X') TWProd = obj_RDS_Test('ProdTestCount',TestKeys) Reactor = @RECORD 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, 3, 'X') TWProd = obj_RDS_Test('ProdTestCount',TestKeys) Reactor = @RECORD 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 = WafersOutTotal MetricsRec = YieldTotal MetricsRec = TotalYield24 MetricsRec = ScrapTotal MetricsRec = ProdTestTotal MetricsRec = DailyTarget MetricsRec = TotalThickness MetricsRec = TotalThickness24 MetricsRec = ThickWaferRatio MetricsRec = 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) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'reactorOut', MetricsRec) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'yieldOut', MetricsRec) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'projected', MetricsRec) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'yieldPercent', MetricsRec, '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) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'projectedThickness', MetricsRec) SRP_JSON(hDayMetricsObj, 'SETVALUE', 'thicknessWaferRatio', MetricsRec) // 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 PTIRunOrder = Row LoadRunOrder = Row 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) SRP_JSON(objRow, 'SetValue', 'ReactorType', Row) SRP_JSON(objRow, 'SetValue', 'WorkOrderNo', Row) SRP_JSON(objRow, 'SetValue', 'SapProdNo', Row) SRP_JSON(objRow, 'SetValue', 'SubPartNo', Row) SRP_JSON(objRow, 'SetValue', 'EpiPartNo', Row) WOQty = Row Swap ',' with '' in WOQty SRP_JSON(objRow, 'SetValue', 'WoQty', WOQty) RxQty = Row Swap ',' with '' in RxQty SRP_JSON(objRow, 'SetValue', 'RxQty', RxQty) UnRelQty = Row Swap ',' with '' in UnRelQty SRP_JSON(objRow, 'SetValue', 'UnRelQty', UnRelQty) SRP_JSON(objRow, 'SetValue', 'KitLoc', Row) KitQty = Row Swap ',' with '' in KitQty SRP_JSON(objRow, 'SetValue', 'KitQty', KitQty) SRP_JSON(objRow, 'SetValue', 'CassDelta', Row) Swap ',' with ', ' in KitRunOrder SRP_JSON(objRow, 'SetValue', 'KitRunOrder', KitRunOrder) SRP_JSON(objRow, 'SetValue', 'KitDemand', Row) 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) 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 RepWafersOut += WafersOut ReportRow = 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 SchedStartDtm = SchedDetRec SchedStopDtm = SchedDetRec 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 If RepWafersOut EQ '' then RepWafersOut = 0 PerfRow = RepWafersOut PerfRow = OConv(IConv(HoursUp<0, vPos>, 'MD2'), 'MD2') PerfRow = 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 = Row<0, 4, PSNIndex> Rec = Row<0, 5, PSNIndex> ActualStartDTM = '' ActualStopDTM = '' SchedDetRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', Row<0, 6, PSNIndex>) SchedDetStartDTM = SchedDetRec SchedDetStopDTM = SchedDetRec 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 = ActualStartDTM Rec = 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 = TotalReactorData<1, PRODUCTIVE$> Rec = TotalReactorData<2, PRODUCTIVE$> Rec = TotalReactorData<1, UNSCHED$> Rec = TotalReactorData<2, UNSCHED$> Rec = TotalReactorData<2, SCHED$> Rec = 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 = 0 Rec = 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 ASMUptime = SRP_Math('ROUND', ASMUptime * 100, 2) ASMUptimeMinutes = ASMUptimeRec ASMAvailMinutes = ASMUptimeRec ASMPeriodUptimeMinutes += ASMUptimeMinutes ASMPeriodAvailMinutes += ASMAvailMinutes end If RowExists('REACTOR_DAILY_UPTIME', HTRUptimeKey) then HTRUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', HTRUptimeKey, True$, 0) HTRUptime = HTRUptimeRec HTRUptime = SRP_Math('ROUND', HTRUptime * 100, 2) HTRUptimeMinutes = HTRUptimeRec HTRAvailMinutes = HTRUptimeRec HTRPeriodUptimeMinutes += HTRUptimeMinutes HTRPeriodAvailMinutes += HTRAvailMinutes end If RowExists('REACTOR_DAILY_UPTIME', EPPUptimeKey) then EPPUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', EPPUptimeKey, True$, 0) EPPUptime = EPPUptimeRec EPPUptime = SRP_Math('ROUND', EPPUptime * 100, 2) EPPUptimeMinutes = EPPUptimeRec EPPAvailMinutes = EPPUptimeRec EPPPeriodUptimeMinutes += EPPUptimeMinutes EPPPeriodAvailMinutes += EPPAvailMinutes end If RowExists('REACTOR_DAILY_UPTIME', AllUptimeKey) then AllUptimeRec = Database_Services('ReadDataRow', 'REACTOR_DAILY_UPTIME', AllUptimeKey, True$, 0) AllUptime = AllUptimeRec AllUptime = SRP_Math('ROUND', AllUptime * 100, 2) AllUptimeMinutes = AllUptimeRec AllAvailMinutes = AllUptimeRec 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 = 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 WONo = SchedDetRec 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 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 = S.ReactNo AllReportData = S.React_Type AllReportData = S.WONo AllReportData = S.ProdOrdNo AllReportData = S.SubPartNo AllReportData = S.EpiPartNo AllReportData = S.WO_Qty AllReportData = S.WO_RX_Qty AllReportData = S.WO_UnRel_Qty AllReportData = S.KitLocation AllReportData = S.KitQty AllReportData = CassNeeded AllReportData = KitCassList ; // Skip field 14, it is populated by users AllReportData = PTICassList AllReportData = 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 = Rec Row = Rec 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 = KitDemand MatRepRec = 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 WONo = SchedDetRec 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 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 = AllReportData 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 Service GetOpenNCRReportJson() ErrorMessage = '' OpenNCRReportJson = '' OpenNCRKeyList = NCR_Services('GetOpenNCRKeys') objJson = '' If SRP_Json(objJson, 'New') then objOpenNCRJsonArray = '' If SRP_Json(objOpenNCRJsonArray, 'New', 'Array') then for each NCRKey in OpenNCRKeyList using @VM ThisNCRJsonString = NCR_Services('ConvertRecordToJson', NCRKey) ThisNCRJsonObj = '' ParseResult = SRP_Json(ThisNCRJsonObj, 'Parse', ThisNCRJsonString) If ParseResult EQ '' then SRP_Json(objOpenNCRJsonArray, 'Add', ThisNCRJsonObj) SRP_Json(ThisNCRJsonObj, 'Release') end else SRP_Json(ThisNCRJsonObj, 'Release') end Next NCRKey SRP_Json(objJson, 'Set', 'OpenNCRReport', objOpenNCRJsonArray) SRP_Json(objOpenNCRJsonArray, 'Release') end else ErrorMessage = 'Error creating Open NCR JSON Array.' end OpenNCRReportJson = SRP_JSON(objJSON, 'Stringify', 'Styled') SRP_JSON(objJSON, 'Release') end else ErrorMessage = 'Error creating root JSON object.' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end Response = OpenNCRReportJson 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