Function REACTOR_SERVICES_Dev(@Service, @Params) /*********************************************************************************************************************** This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written permission from SRP Computer Solutions, Inc. Name : Reactor_Services_Dev Description : Handler program for all module related services. Notes : The generic parameters should contain all the necessary information to process the services. Often this will be information like the data Record and Key ID. 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) 08/10/17 dmb Original programmer. Adapted from Scheduling_Services. - [IREPIOI-8] 01/08/18 dmb Update the CreatePerformanceTrackersDev service so the CreateWeeklyPerformanceReportDev is called on Friday mornings for the upcoming week rather than Monday mornings for the current week. - [IREPIOI-14] 02/17/18 dmb Add logging to track reactor performance activities. - [IREPIOI-14] 05/30/18 dmb Update various services to allow newer reactors to be used for reporting. - [IREPIOI-17] 06/21/18 dmb Update the path where templates and reports are stored. - [IREPIOI-33] 06/26/18 dmb Add logging to track when this service is being called. - [IREPIOI-56] 06/26/18 dmb Update logic on how reactors are selected for reporting. - [IREPIOI-56] 04/20/21 djs Added PickPlace to objReactor JSON object in GetReactorDev service. ***********************************************************************************************************************/ #pragma precomp SRP_PreCompiler $insert APP_INSERTS $insert SERVICE_SETUP $insert REACTOR_EQUATES $insert RDS_EQUATES $insert RLIST_EQUATES $insert SCHED_DET_NG_EQUATES Declare subroutine Error_Services, Reactor_Services_Dev, Memory_Services, RList, Database_Services, SRP_JSON Declare subroutine Excel_Services, Schedule_Services, Logging_Services, Set_Status, Schedule_Services Declare function SRP_Array, Reactor_Services_Dev, Memory_Services, Database_Services, SRP_Sort_Array, Excel_Services Declare function SRP_Math, SRP_Hash, SRP_JSON, Epi_Part_Services, Schedule_Services, Date_Services Declare function Logging_Services, GetCommandLine, Environment_Services, Schedule_Services // Report paths for various performance report services. TemplatesFolder = Environment_Services('GetApplicationRootPath') : '\Reports\SchedulerPro\Templates\' DailyReportsFolder = Environment_Services('GetApplicationRootPath') : '\Reports\SchedulerPro\Daily\' WeeklyReportsFolder = Environment_Services('GetApplicationRootPath') : '\Reports\SchedulerPro\Weekly\' CommandLine = GetCommandLine() Machine = Environment_Services('GetServer') LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\PerformanceReportsPro' LogDate = Oconv(Date(), 'D4/') LogTime = Oconv(Time(), 'MTS') LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Performance Reports Pro.csv' Headers = 'Logging DTM' : @FM : 'Machine' : @FM : 'Command Line' : @FM : 'Service Detail' ColumnWidths = 20 : @FM : 15 : @FM : 60 : @FM : 300 objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, False$, False$) LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM GoToService else Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.') LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Error_Services('GetMessage') Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end Return Response else '' //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Services //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------------------------------------------------- // GetReactorsDev // // Returns a JSON formatted array of reactor objects. Reactor number 0 will be ommitted. If the MatchType or MatchSize // arguments are populated, the array will be filterd accordingly. //---------------------------------------------------------------------------------------------------------------------- Service GetReactorsDev(MatchType, MatchSize) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' * Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) ServiceKeyID := '*' : MatchType : '*' : MatchSize Reactors = '' If Memory_Services('IsValueCurrent', ServiceKeyID, 3600, True$) then Reactors = Memory_Services('GetValue', ServiceKeyID) end else objReactors = '' If SRP_JSON(objReactors, 'NEW', 'OBJECT') then objReactorArray = '' If SRP_JSON(objReactorArray, 'NEW', 'ARRAY') then hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ Reactors = '' Loop Readnext ReactorNo else Done = True$ Until Done Reactor = Reactor_Services_Dev('GetReactorDev', ReactorNo) objReactor = '' If SRP_JSON(objReactor, 'PARSE', Reactor) EQ '' then ReactorType = SRP_JSON(objReactor, 'GETVALUE', 'Type') ReactorSize = SRP_JSON(objReactor, 'GETVALUE', 'SusceptorSize') IncludeReactor = True$ ; // Assume reactor will be included in the response. Begin Case Case ReactorNo EQ 0 // Reactor number 0 is not a real reactor. IncludeReactor = False$ Case MatchType NE '' Begin Case Case MatchType[1, 3] EQ 'ASM' AND Not((ReactorType[1, 3] EQ 'ASM' OR ReactorType EQ 'EPS')) IncludeReactor = False$ Case MatchType EQ 'EPS' AND Not((ReactorType[1, 3] EQ 'ASM' OR ReactorType EQ 'EPS')) IncludeReactor = False$ Case MatchType EQ 'EPP' AND Not((ReactorType EQ 'EPP' OR ReactorType EQ 'EpiPro')) IncludeReactor = False$ Case MatchType EQ 'EpiPro' AND Not((ReactorType EQ 'EPP' OR ReactorType EQ 'EpiPro')) IncludeReactor = False$ Case MatchType _EQC 'GAN' AND Not(ReactorType _EQC 'GAN') IncludeReactor = False$ Case MatchType NE ReactorType IncludeReactor = False$ End Case Case MatchSize NE '' If MatchSize NE ReactorSize then IncludeReactor = False$ End Case If IncludeReactor then SRP_JSON(objReactorArray, 'ADD', objReactor) end SRP_JSON(objReactor, 'RELEASE') end Repeat SRP_JSON(objReactors, 'SET', 'Reactors', objReactorArray) Reactors = SRP_JSON(objReactors, 'STRINGIFY', 'FAST') Memory_Services('SetValue', ServiceKeyID, Reactors) end SRP_JSON(objReactorArray, 'RELEASE') end else Error_Services('Add', 'Error creating objReactorArray in the ' : Service : ' service.') end SRP_JSON(objReactors, 'RELEASE') end else Error_Services('Add', 'Error creating objReactors in the ' : Service : ' service.') end end Response = Reactors LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' * Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // GetReactorNumbersDev // // Returns an @FM delimited list of Reactor Numbers. //---------------------------------------------------------------------------------------------------------------------- Service GetReactorNumbersDev(MatchType, MatchSize) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) ServiceKeyID := '*' : MatchType : '*' : MatchSize ReactorNumbers = '' If Memory_Services('IsValueCurrent', ServiceKeyID, 3600, True$) then ReactorNumbers = Memory_Services('GetValue', ServiceKeyID) end else hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ Reactors = '' Loop Readnext ReactorNo else Done = True$ Until Done Reactor = Reactor_Services_Dev('GetReactorDev', ReactorNo) If SRP_JSON(objReactor, 'PARSE', Reactor) EQ '' then ReactorType = SRP_JSON(objReactor, 'GETVALUE', 'Type') ReactorSize = SRP_JSON(objReactor, 'GETVALUE', 'SusceptorSize') IncludeReactor = True$ ; // Assume reactor will be included in the response. Begin Case Case ReactorNo EQ 0 // Reactor number 0 is not a real reactor. IncludeReactor = False$ Case MatchType NE '' Begin Case Case MatchType[1, 3] EQ 'ASM' AND Not((ReactorType[1, 3] EQ 'ASM' OR ReactorType EQ 'EPS')) IncludeReactor = False$ Case MatchType EQ 'EPS' AND Not((ReactorType[1, 3] EQ 'ASM' OR ReactorType EQ 'EPS')) IncludeReactor = False$ Case MatchType EQ 'EPP' AND Not((ReactorType EQ 'EPP' OR ReactorType EQ 'EpiPro')) IncludeReactor = False$ Case MatchType EQ 'EpiPro' AND Not((ReactorType EQ 'EPP' OR ReactorType EQ 'EpiPro')) IncludeReactor = False$ Case MatchType _EQC 'GAN' AND Not(ReactorType _EQC 'GAN') IncludeReactor = False$ Case MatchType NE ReactorType IncludeReactor = False$ End Case Case MatchSize NE '' If MatchSize NE ReactorSize then IncludeReactor = False$ End Case If IncludeReactor then ReactorNumbers := ReactorNo : @FM end end Repeat ReactorNumbers[-1, 1] = '' Memory_Services('SetValue', ServiceKeyID, ReactorNumbers) end end Response = ReactorNumbers LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // GetReactorDev // // Returns a JSON formatted object of information related to the indicated reactor number. //---------------------------------------------------------------------------------------------------------------------- Service GetReactorDev(ReactorNo) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' * Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) ServiceKeyID := '*' : ReactorNo Reactor = '' If Memory_Services('IsValueCurrent', ServiceKeyID, 3600, True$) then Reactor = Memory_Services('GetValue', ServiceKeyID) end else If (ReactorNo NE '') AND (ReactorNo NE 0) then ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo) If SRP_JSON(objReactor, 'NEW', 'OBJECT') then ReactorType = ReactorRow SRP_JSON(objReactor, 'SETVALUE', 'ReactorNumber', ReactorNo, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'Type', ReactorType, 'STRING') Begin Case Case ReactorType _EQC 'ASM' ; ReactorTypeVerbose = 'ASM' Case ReactorType _EQC 'ASM+'; ReactorTypeVerbose = 'ASM+' Case ReactorType _EQC 'EPP' ; ReactorTypeVerbose = 'EpiPro' Case ReactorType _EQC 'EPS' ; ReactorTypeVerbose = 'ASM' Case ReactorType _EQC 'HTR' ; ReactorTypeVerbose = 'HTR' Case ReactorType _EQC 'GAN' ; ReactorTypeVerbose = 'GaN' Case ReactorType _EQC '' ; ReactorTypeVerbose = '***' End Case SRP_JSON(objReactor, 'SETVALUE', 'TypeVerbose', ReactorTypeVerbose, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'AssignmentCode', ReactorRow, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'AssignmentDescription', Oconv(ReactorRow, '[REACT_ASSIGN_CONV]'), 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'Location', ReactorRow, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'SusceptorSize', ReactorRow, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'SecondChamber', ReactorRow, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'PickPlace', ReactorRow, 'STRING') SRP_JSON(objReactor, 'SETVALUE', 'NotRepairable', ReactorRow, 'STRING') Reactor = SRP_JSON(objReactor, 'STRINGIFY', 'FAST') Memory_Services('SetValue', ServiceKeyID, Reactor) SRP_JSON(objReactor, 'RELEASE') end else Error_Services('Add', 'Error creating objReactor in the ' : Service : ' service.') end end else Error_Services('Add', 'ReactorNo argument was missing from the ' : Service : ' service.') end end Response = Reactor LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' * Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // CreatePerformanceTrackersDev // // Creates performance tracking database rows in the REACTOR_PERFORMANCE_NG table. This creates a unique tracker for each // Reactor/Part pair based on the indicated dates scheduled work orders. //---------------------------------------------------------------------------------------------------------------------- Service CreatePerformanceTrackersDev(ScheduleDate, CreateReports) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) // Force the auto scheduler to run to make sure that all adjustments are being made to the scheduler. * Schedule_Services('AutoScheduler') If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() If CreateReports NE False$ then CreateReports = True$ // There will be two procedures. The first is a pass through the scheduled events to create the Reactor Performance // rows. The second is a pass through the recently created Reactor Performance records to adjust the expected // wafer count based part changes. // Get a list of all the scheduled events for the indicated schedule date. Note: this service expects to be ran // shortly after midnight for the indicated schedule date. ScheduleEvents = Schedule_Services('GetScheduleEventsNew', ScheduleDate, ScheduleDate, '', '', False$) If ScheduleEvents NE '' then PerfKeyIDs = '' For Each ScheduleEvent in ScheduleEvents using @FM setting fPos KeyID = ScheduleEvent<0, 2> EventRec = Database_Services('ReadDataRow', 'SCHED_DET_NG', KeyID) WorkOrderNo = EventRec EpiPartNo = Xlate('WO_LOG', WorkOrderNo, 'EPI_PART_NO', 'X') ReactorNo = EventRec * ScheduleDate = Field(EventRec, '.', 1, 1) If EpiPartNo NE '' then PartUsedKeyID = Service : '*' : ReactorNo : '*' : ScheduleDate : '*' : EpiPartNo If Memory_Services('KeyExists', PartUsedKeyID) EQ False$ then PartCountKeyID = Service : '*' : ReactorNo : '*' : ScheduleDate NumParts = Memory_Services('GetValue', PartCountKeyID) NumParts += 1 Memory_Services('SetValue', PartCountKeyID, NumParts) Memory_Services('SetValue', PartUsedKeyID, True$) end // This is a work order event rather than a block out event. ScheduleEventSummary = Schedule_Services('GetScheduleEventSummary', KeyID, True$) StartDate = Iconv(ScheduleEventSummary<6>, 'D') ReactorType = ScheduleEventSummary<1> EndDate = Iconv(ScheduleEventSummary<7>, 'D') TotalWafers = ScheduleEventSummary<9> Begin Case Case ReactorType _eqc 'ASM+' ; ReactorType = 'ASM+' Case ReactorType _eqc 'EPP' ; ReactorType = 'EpiPro' Case ReactorType _eqc 'EPS' ; ReactorType = 'ASM' Case ReactorType _eqc 'HTR' ; ReactorType = 'HTR' Case ReactorType _eqc 'GAN' ; ReactorType = 'GaN' Case ReactorType _eqc '' ; ReactorType = '***' End Case MinutesPerWafer = Epi_Part_Services('GetMinutesPerWaferScheduler', EpiPartNo, ReactorType) WafersPerDay = Epi_Part_Services('GetAdjustedWafersPerDayScheduler', EpiPartNo, ReactorType, MinutesPerWafer) If ScheduleDate LT EndDate then // The end date of this schedule event is still in the future. Therefore, the current event is expected // to run the whole day. Use the calculated wafers per day. WafersExpected = WafersPerDay end else // This is the end of the schedule event. Wafers expected will be the remaining total wafers after // all previous wafers per day have been deducted. TotalPreviousDays = EndDate - StartDate TotalPreviousWafers = TotalPreviousDays * WafersPerDay WafersExpected = TotalWafers - TotalPreviousWafers If WafersExpected GT WafersPerDay then WafersExpected = WafersPerDay ; // Cap to the wafers per day. end If WafersExpected LT 0 then WafersExpected = 0 // Full KeyID = {REACTOR_NO} * {EPI_PART_NO} * {WEEK_YEAR} * {WEEK_NO} * {SCHEDULE_DATE} WeekDate = Date_Services('GetISOWeekDate', ScheduleDate) WeekYear = WeekDate[1, '-'] WeekNo = WeekDate[Col2() + 1, '-'] PerfKeyID = ReactorNo : '*' : EpiPartNo : '*' : WeekYear : '*' : WeekNo : '*' : ScheduleDate PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) PerfRow<2> = PerfRow<2> + Iconv(WafersExpected, 'MD2') Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, PerfRow, True$, False$, True$) Locate PerfKeyID in PerfKeyIDs using @FM setting fPos else PerfKeyIDs := PerfKeyID : @FM end Next ScheduleEvent // Pass through each Reactor Performance row. For every part being run on a given reactor, the following // adjustment is required: // // 1. Total expected amount per part should be prorated by the number of parts. This accounts for the fact // that one reactor will be splitting its time for each part. For example, if Part A is normally estimated // to run 200 parts and Part B is normally estimated to run 300 parts, they will each be prorated by .5. // Thus, Part A will now be estimated to run 100 parts and Part B will be estimated to run 150 parts. // // 2. Since each part change requires an average of 6 hours of down time to prepare the reactor, the amount // per part should be prorated by the remaining hours in the day. For example, if there are two parts being // ran on the reactor, this only allows 18 hours (out of 24) to run parts, which is a prorated value of // .75. Using the above example, Part A would then have 100 parts prorated to 75 (100 * .75) and Part would // then have 150 parts prorated to 112.50 (150 * .75). If PerfKeyIDs NE '' then For Each PerfKeyID in PerfKeyIDs using @FM ReactorNo = PerfKeyID[1, '*'] EpiPartNo = PerfKeyID[Col2() + 1, '*'] WeekYear = PerfKeyID[Col2() + 1, '*'] WeekNo = PerfKeyID[Col2() + 1, '*'] ScheduleDate = PerfKeyID[Col2() + 1, '*'] PartCountKeyID = Service : '*' : ReactorNo : '*' : ScheduleDate NumParts = Memory_Services('GetValue', PartCountKeyID) If NumParts GT 1 then // Only prorate if there is more then one part. Prorate1 = 1 / NumParts ; // Adjust for the number of parts. Prorate2 = ((24 - ((NumParts - 1) * 6) ) / 24) ; // Adjust for the number of hours remaining in the day. Prorate = Prorate1 * Prorate2 PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) PerfRow<2> = PerfRow<2> * ProRate Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, PerfRow, True$, False$, True$) end Next PerfKeyID // Clear out all cached data. Memory_Services('ReleaseHashTable') end end If CreateReports then Reactor_Services_Dev('CreateDailyPerformanceReportDev', ScheduleDate) If Mod(ScheduleDate, 7) EQ 5 then // This is early Friday. Create the weekly performance report for the upcoming week. First, the // CreatePerformanceTrackersDev must be called for all days in the upcoming week. NextMonday = ScheduleDate + 3 NextSunday = ScheduleDate + 9 For ScheduleDate = NextMonday to NextSunday Reactor_Services_Dev('CreatePerformanceTrackersDev', ScheduleDate, False$) Next ScheduleDate // Create the weekly performance report based on the daily performance tracking data. YearWeekNo = Date_Services('GetISOWeekDate', NextMonday) YearWeekNo = Field(YearWeekNo, '-', 1, 2) Reactor_Services_Dev('CreateWeeklyPerformanceReportDev', YearWeekNo) // Clear the daily performance tracking data for the upcoming week since these will be recreated // automatically on the morning of each date. For ScheduleDate = NextMonday to NextSunday Reactor_Services_Dev('ClearWafersExpectedDev', ScheduleDate) Next ScheduleDate end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // UpdatePerformanceTrackersDev // // Updates the wafers processed column in the performance tracking database rows. //---------------------------------------------------------------------------------------------------------------------- Service UpdatePerformanceTrackersDev(ScheduleDate, CreateReports) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() If CreateReports NE False$ then CreateReports = True$ rv = Set_Status(0) Sentence = 'SELECT RDS WITH DATE_OUT EQ ' : Quote(Oconv(ScheduleDate, 'D4/')) RList(Sentence, 5, '', '', '') EOF = False$ Loop Readnext RDSID else EOF = True$ Until EOF RDSRow = Database_Services('ReadDataRow', 'RDS', RDSID) If Error_Services('NoError') then WeekDate = Date_Services('GetISOWeekDate', ScheduleDate) WeekYear = WeekDate[1, '-'] WeekNo = WeekDate[Col2() + 1, '-'] ReactorNo = RDSRow ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 60, False$) ReactorType = ReactorRow If ReactorType EQ 'EPP' then // This is an EpiPro reactor. Check to see if has a second chamber. If so, then this is the primary // reactor. If not, then check the previous reactor to see if it references this current reactor as its // second chamber. If so then use the previous reactor to track the wafers processed. SecondChamber = ReactorRow If SecondChamber EQ '' then CompareReactorNo = ReactorNo - 2 CompareReactorRow = Database_Services('ReadDataRow', 'REACTOR', CompareReactorNo, True$, 60, False$) CompareSecondChamber = CompareReactorRow If CompareSecondChamber EQ ReactorNo then Transfer CompareReactorNo to ReactorNo end end * EpiPartNo = RDSRow EpiPartNo = Xlate('RDS', RDSID, 'EPI_PART_NO', 'X') // Full KeyID = {REACTOR_NO} * {EPI_PART_NO} * {WEEK_YEAR} * {WEEK_NO} * {SCHEDULE_DATE} PerfKeyID = ReactorNo : '*' : EpiPartNo : '*' : WeekYear : '*' : WeekNo : '*' : ScheduleDate PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) If Error_Services('NoError') then WafersProcessed = RDSRow PerfRow<3> = PerfRow<3> + Iconv(WafersProcessed, 'MD2') Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, PerfRow, True$, False$, True$) end end Repeat If CreateReports then Reactor_Services_Dev('UpdateDailyPerformanceReportDev', ScheduleDate) If Mod(ScheduleDate, 7) EQ 0 then // This is a Sunday, which means the last day of a work week has been updated. Update the weekly performance // report but set the date to the previous Monday. YearWeekNo = Date_Services('GetISOWeekDate', ScheduleDate - 6) YearWeekNo = Field(YearWeekNo, '-', 1, 2) Reactor_Services_Dev('UpdateWeeklyPerformanceReportDev', ScheduleDate - 6) end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // ClearWafersExpectedDev // // Clears the expected wafers for all database rows the REACTOR_PERFORMANCE_NG table based on the indicated schedule date. //---------------------------------------------------------------------------------------------------------------------- Service ClearWafersExpectedDev(ScheduleDate) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ ReportData = '' Loop Readnext ReactorNo else Done = True$ Until Done ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 0) ReactorType = ReactorRow SecondChamber = ReactorRow @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If (((ReactorNo GT 0) AND (ReactorNo LE 79))) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) then * If (ReactorNo NE 0) AND (ReactorNo LE 74) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) AND (ReactorType NE 'GAN') then @ID = ReactorNo : '****' : ScheduleDate @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) If Error_Services('NoError') then DetailPerfKeyIDs = {ALL_DETAIL_CHILD_KEY_IDS} If DetailPerfKeyIDs NE '' then For Each PerfKeyID in DetailPerfKeyIDs using @VM PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) PerfRow<2> = '' Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, PerfRow, True$, False$, True$) Next DetailPerfKeyID end end end Repeat end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // ClearWafersProcessedDev // // Clears the processed wafers for all database rows the REACTOR_PERFORMANCE_NG table based on the indicated schedule date. //---------------------------------------------------------------------------------------------------------------------- Service ClearWafersProcessedDev(ScheduleDate) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ ReportData = '' Loop Readnext ReactorNo else Done = True$ Until Done ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 0) ReactorType = ReactorRow SecondChamber = ReactorRow @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If (((ReactorNo GT 0) AND (ReactorNo LE 79))) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) then * If (ReactorNo NE 0) AND (ReactorNo LE 74) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) AND (ReactorType NE 'GAN') then @ID = ReactorNo : '****' : ScheduleDate @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) If Error_Services('NoError') then DetailPerfKeyIDs = {ALL_DETAIL_CHILD_KEY_IDS} If DetailPerfKeyIDs NE '' then For Each PerfKeyID in DetailPerfKeyIDs using @VM PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) PerfRow<3> = '' Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, PerfRow, True$, False$, True$) Next DetailPerfKeyID end end end Repeat end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // CreateDailyPerformanceReportDev // // Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE_NG table. This creates an // Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template. //---------------------------------------------------------------------------------------------------------------------- Service CreateDailyPerformanceReportDev(ScheduleDate) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() DisplayDate = Oconv(ScheduleDate, 'D4/') XLSXTemplate = 'Fab Performance Daily Template.xlsx' objDocument = Excel_Services('OpenDocument', TemplatesFolder : XLSXTemplate) If Error_Services('NoError') then hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ ReportData = '' Loop Readnext ReactorNo else Done = True$ Until Done ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 0) ReactorType = ReactorRow SecondChamber = ReactorRow @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If (((ReactorNo GT 0) AND (ReactorNo LE 79))) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) then * If (ReactorNo NE 0) AND (ReactorNo LE 74) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) AND (ReactorType NE 'GAN') then PerfKeyID = ReactorNo : '****' : ScheduleDate PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) DetailPerfKeyIDs = PerfRow<1> If DetailPerfKeyIDs NE '' then For Each @ID in DetailPerfKeyIDs using @VM @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) ReactorName = {REACTOR_NAME} EpiPartNo = {EPI_PART_NO} WafersExpected = Oconv({TOTAL_WAFERS_EXPECTED}, 'MD2') WafersExpectedRounded = Oconv({TOTAL_WAFERS_EXPECTED_ROUNDED}, 'MD2') ReportData := ReactorType : @VM : ReactorName : @VM : DisplayDate : @VM : EpiPartNo : @VM : WafersExpected : @VM : WafersExpectedRounded : @VM : ReactorNo : @FM Next DetailPerfKeyID end else ReportData := ReactorType : @VM : ReactorNo : @VM : DisplayDate : @VM : '' : @VM : '' : @VM : '' : @VM : ReactorNo : @FM end end Repeat ReportData[-1, 1] = '' ; // Strip off the last @FM ReportData = SRP_Array('SortRows', ReportData, 'AR7' : @VM : 'AL4', 'LIST', @FM, @VM) CellRow = 1 ; // Initialize the cell row to start entering data into. If ReportData NE '' then For Each ReportRow in ReportData using @FM ReactorType = ReportRow[1, @VM] ReactorName = ReportRow[Col2() + 1, @VM] DisplayDate = ReportRow[Col2() + 1, @VM] EpiPartNo = ReportRow[Col2() + 1, @VM] WafersExpected = ReportRow[Col2() + 1, @VM] WafersExpectedRounded = ReportRow[Col2() + 1, @VM] CellRow += 1 Excel_Services('SetCellValue', objDocument, 'SSR', 'A', CellRow, ReactorType) Excel_Services('SetCellValue', objDocument, 'SSR', 'B', CellRow, ReactorName) Excel_Services('SetCellValue', objDocument, 'SSR', 'E', CellRow, DisplayDate) Excel_Services('SetCellValue', objDocument, 'SSR', 'F', CellRow, EpiPartNo) Excel_Services('SetCellValue', objDocument, 'SSR', 'G', CellRow, WafersExpected) Excel_Services('SetCellValue', objDocument, 'SSR', 'H', CellRow, WafersExpectedRounded) Next ReportRow end end NewDocument = DisplayDate[7, 4] : '-' : DisplayDate[1, 2] : '-' : DisplayDate[4, 2] : ' Fab Performance.xlsx' Excel_Services('SaveDocument', objDocument, DailyReportsFolder : NewDocument) If Error_Services('NoError') then * Call Send_SRP_Mail(DailyReportsFolder : NewDocument) rv = Set_Status(0) OSRead PerformanceReport from DailyReportsFolder : NewDocument then OSWrite PerformanceReport to DailyReportsFolder : NewDocument If Status() then Error_Services('Add', 'Error writing ' : DailyReportsFolder : NewDocument : ' in the ' : Service : ' service. Status: ' : Status()) end end else Error_Services('Add', 'Error reading ' : DailyReportsFolder : NewDocument : ' in the ' : Service : ' service. Status: ' : Status()) end end end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // UpdateDailyPerformanceReportDev // // Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE_NG table. This creates an // Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template. //---------------------------------------------------------------------------------------------------------------------- Service UpdateDailyPerformanceReportDev(ScheduleDate) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) If Num(ScheduleDate) else ScheduleDate = Iconv(ScheduleDate, 'D') If ScheduleDate EQ '' then ScheduleDate = Date() DisplayDate = Oconv(ScheduleDate, 'D4/') Document = DisplayDate[7, 4] : '-' : DisplayDate[1, 2] : '-' : DisplayDate[4, 2] : ' Fab Performance.xlsx' If Excel_Services('DocumentExists', DailyReportsFolder : Document) then objDocument = Excel_Services('OpenDocument', DailyReportsFolder : Document) end else Error_Services('Add', 'Unable to find ' : Document : ' in the ' : Service : ' service.') end If Error_Services('NoError') then @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If Error_Services('NoError') then CellRow = 1 ; // Initialize the cell row to start entering data into. Loop CellRow += 1 Date = Excel_Services('GetCellValue', objDocument, 'SSR', 'E', CellRow) Until Date EQ '' ReactorName = Excel_Services('GetCellValue', objDocument, 'SSR', 'B', CellRow) ReactorNo = ReactorName[1, 'F/'] EpiPartNo = Excel_Services('GetCellValue', objDocument, 'SSR', 'F', CellRow) WeekDate = Date_Services('GetISOWeekDate', ScheduleDate) WeekYear = WeekDate[1, '-'] WeekNo = WeekDate[Col2() + 1, '-'] // Full KeyID = {REACTOR_NO} * {EPI_PART_NO} * {WEEK_YEAR} * {WEEK_NO} * {SCHEDULE_DATE} @ID = ReactorNo : '*' : EpiPartNo : '*' : WeekYear : '*' : WeekNo : '*' : ScheduleDate @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) WafersProcessed = Oconv({TOTAL_WAFERS_PROCESSED}, 'MD2') WafersDelta = Oconv({TOTAL_WAFERS_DELTA}, 'MD2') WafersDeltaRounded = Oconv({TOTAL_WAFERS_DELTA_ROUNDED}, 'MD2') Excel_Services('SetCellValue', objDocument, 'SSR', 'I', CellRow, WafersProcessed) Excel_Services('SetCellValue', objDocument, 'SSR', 'K', CellRow, WafersDelta) Excel_Services('SetCellValue', objDocument, 'SSR', 'L', CellRow, WafersDeltaRounded) Repeat Excel_Services('SaveDocument', objDocument) If Error_Services('NoError') then * Call Send_SRP_Mail(DailyReportsFolder : Document) rv = Set_Status(0) OSRead PerformanceReport from DailyReportsFolder : Document then OSWrite PerformanceReport to DailyReportsFolder : Document If Status() then Error_Services('Add', 'Error writing ' : DailyReportsFolder : Document : ' in the ' : Service : ' service. Status: ' : Status()) end end else Error_Services('Add', 'Error reading ' : DailyReportsFolder : Document : ' in the ' : Service : ' service. Status: ' : Status()) end end else ErrorMessage = Error_Services('GetMessage') end end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // CreateWeeklyPerformanceReportDev // // Creates weekly performance tracking report using the database rows in the REACTOR_PERFORMANCE_NG table. This creates an // Excel spreadsheet using the "Fab Performance Weekly Template.xlsx" file as a template. //---------------------------------------------------------------------------------------------------------------------- Service CreateWeeklyPerformanceReportDev(YearWeekNo) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) // YearWeekNo looks like 2017-W44. For testing purposes it might be easier to pass in a date and the YearWeekNo // will be calculated. If (Num(Iconv(YearWeekNo, 'D')) AND (Iconv(YearWeekNo, 'D') NE '')) OR Num(YearWeekNo) then // A internal or external formatted date was passed in. YearWeekNo = Date_Services('GetISOWeekDate', YearWeekNo) YearWeekNo = Field(YearWeekNo, '-', 1, 2) end WeekYear = YearWeekNo[1, '-'] WeekNo = YearWeekNo[Col2() + 1, '-'] XLSXTemplate = 'Fab Performance Weekly Template.xlsx' objDocument = Excel_Services('OpenDocument', TemplatesFolder : XLSXTemplate) If Error_Services('NoError') then hReactors = Database_Services('GetTableHandle', 'REACTOR') If Error_Services('NoError') then If Error_Services('NoError') then rv = Set_Status(0) RList('SELECT REACTOR BY REACT_NO', 5, '', '', '') Done = False$ ReportData = '' Loop Readnext ReactorNo else Done = True$ Until Done ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 0) ReactorType = ReactorRow SecondChamber = ReactorRow @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If (((ReactorNo GT 0) AND (ReactorNo LE 79))) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) then * If (ReactorNo NE 0) AND (ReactorNo LE 74) AND ((ReactorType EQ 'EPP' AND SecondChamber NE '') OR (ReactorType NE 'EPP')) AND (ReactorType NE 'GAN') then PerfKeyID = ReactorNo : '**' : WeekYear : '*' : WeekNo : '*' PerfRow = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', PerfKeyID, True$, 0) DetailPerfKeyIDs = PerfRow<1> If DetailPerfKeyIDs NE '' then DetailPerfKeyIDs = SRP_Array('SortRows', DetailPerfKeyIDs, 'AL2', 'LIST', @VM, '*') PrevEpiPartNo = '' TotalWafersExpected = 0 TotalWafersExpectedRounded = 0 For Each @ID in DetailPerfKeyIDs using @VM @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) ReactorName = {REACTOR_NAME} EpiPartNo = {EPI_PART_NO} If (EpiPartNo NE PrevEpiPartNo) AND (PrevepiPartNo NE '') then // Epi Part No has changed. Add the current totals for the previous Epi Part No to // the report and reset the variables. ReportData := ReactorType : @VM : ReactorName : @VM : YearWeekNo : @VM : PrevEpiPartNo : @VM : TotalWafersExpected : @VM : TotalWafersExpectedRounded : @VM : ReactorNo : @FM TotalWafersExpected = 0 TotalWafersExpectedRounded = 0 end PrevEpiPartNo = EpiPartNo TotalWafersExpected += Oconv({TOTAL_WAFERS_EXPECTED}, 'MD2') TotalWafersExpectedRounded += Oconv({TOTAL_WAFERS_EXPECTED_ROUNDED}, 'MD2') Next DetailPerfKeyID // Add the final total values to the report. ReportData := ReactorType : @VM : ReactorName : @VM : YearWeekNo : @VM : PrevEpiPartNo : @VM : TotalWafersExpected : @VM : TotalWafersExpectedRounded : @VM : ReactorNo : @FM end else ReportData := ReactorType : @VM : ReactorNo : @VM : YearWeekNo : @VM : '' : @VM : '' : @VM : '' : @VM : ReactorNo : @FM end end Repeat ReportData[-1, 1] = '' ; // Strip off the last @FM ReportData = SRP_Array('SortRows', ReportData, 'AR7' : @VM : 'AL4', 'LIST', @FM, @VM) CellRow = 1 ; // Initialize the cell row to start entering data into. If ReportData NE '' then For Each ReportRow in ReportData using @FM ReactorType = ReportRow[1, @VM] ReactorName = ReportRow[Col2() + 1, @VM] YearWeekNo = ReportRow[Col2() + 1, @VM] EpiPartNo = ReportRow[Col2() + 1, @VM] WafersExpected = ReportRow[Col2() + 1, @VM] WafersExpectedRounded = ReportRow[Col2() + 1, @VM] CellRow += 1 Excel_Services('SetCellValue', objDocument, 'SSR', 'A', CellRow, ReactorType) Excel_Services('SetCellValue', objDocument, 'SSR', 'B', CellRow, ReactorName) Excel_Services('SetCellValue', objDocument, 'SSR', 'E', CellRow, YearWeekNo) Excel_Services('SetCellValue', objDocument, 'SSR', 'F', CellRow, EpiPartNo) Excel_Services('SetCellValue', objDocument, 'SSR', 'G', CellRow, WafersExpected) Excel_Services('SetCellValue', objDocument, 'SSR', 'H', CellRow, WafersExpectedRounded) Next ReportRow end end NewDocument = YearWeekNo : ' Fab Performance.xlsx' Excel_Services('SaveDocument', objDocument, WeeklyReportsFolder : NewDocument) If Error_Services('NoError') then * Call Send_SRP_Mail(WeeklyReportsFolder : NewDocument) rv = Set_Status(0) OSRead PerformanceReport from WeeklyReportsFolder : NewDocument then OSWrite PerformanceReport to WeeklyReportsFolder : NewDocument If Status() then Error_Services('Add', 'Error writing ' : WeeklyReportsFolder : NewDocument : ' in the ' : Service : ' service. Status: ' : Status()) end end else Error_Services('Add', 'Error reading ' : WeeklyReportsFolder : NewDocument : ' in the ' : Service : ' service. Status: ' : Status()) end end end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service //---------------------------------------------------------------------------------------------------------------------- // UpdateWeeklyPerformanceReportDev // // Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE_NG table. This creates an // Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template. //---------------------------------------------------------------------------------------------------------------------- Service UpdateWeeklyPerformanceReportDev(YearWeekNo) LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' begins.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) // YearWeekNo looks like 2017-W44. For testing purposes it might be easier to pass in a date and the YearWeekNo // will be calculated. If (Num(Iconv(YearWeekNo, 'D')) AND (Iconv(YearWeekNo, 'D') NE '')) OR Num(YearWeekNo) then // A internal or external formatted date was passed in. YearWeekNo = Date_Services('GetISOWeekDate', YearWeekNo) YearWeekNo = Field(YearWeekNo, '-', 1, 2) end WeekYear = YearWeekNo[1, '-'] WeekNo = YearWeekNo[Col2() + 1, '-'] Document = YearWeekNo : ' Fab Performance.xlsx' If Excel_Services('DocumentExists', WeeklyReportsFolder : Document) then objDocument = Excel_Services('OpenDocument', WeeklyReportsFolder : Document) end else Error_Services('Add', 'Unable to find ' : Document : ' in the ' : Service : ' service.') end If Error_Services('NoError') then @DICT = Database_Services('GetTableHandle', 'DICT.REACTOR_PERFORMANCE_NG') If Error_Services('NoError') then CellRow = 1 ; // Initialize the cell row to start entering data into. Loop CellRow += 1 Date = Excel_Services('GetCellValue', objDocument, 'SSR', 'E', CellRow) Until Date EQ '' ReactorName = Excel_Services('GetCellValue', objDocument, 'SSR', 'B', CellRow) ReactorNo = ReactorName[1, 'F/'] EpiPartNo = Excel_Services('GetCellValue', objDocument, 'SSR', 'F', CellRow) // Full KeyID = {REACTOR_NO} * {EPI_PART_NO} * {WEEK_YEAR} * {WEEK_NO} * {SCHEDULE_DATE} @ID = ReactorNo : '*' : EpiPartNo : '*' : WeekYear : '*' : WeekNo : '*' @RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE_NG', @ID, True$, 0) WafersProcessed = Oconv({TOTAL_WAFERS_PROCESSED}, 'MD2') WafersDelta = Oconv({TOTAL_WAFERS_DELTA}, 'MD2') WafersDeltaRounded = Oconv({TOTAL_WAFERS_DELTA_ROUNDED}, 'MD2') Excel_Services('SetCellValue', objDocument, 'SSR', 'J', CellRow, WafersDelta) Excel_Services('SetCellValue', objDocument, 'SSR', 'K', CellRow, WafersDeltaRounded) Repeat Excel_Services('SaveDocument', objDocument) If Error_Services('NoError') then * Call Send_SRP_Mail(WeeklyReportsFolder : Document) rv = Set_Status(0) OSRead PerformanceReport from WeeklyReportsFolder : Document then OSWrite PerformanceReport to WeeklyReportsFolder : Document If Status() then Error_Services('Add', 'Error writing ' : WeeklyReportsFolder : Document : ' in the ' : Service : ' service. Status: ' : Status()) end end else Error_Services('Add', 'Error reading ' : WeeklyReportsFolder : Document : ' in the ' : Service : ' service. Status: ' : Status()) end end end end LogData = LoggingDTM : @FM : Machine : @FM : CommandLine : @FM : Service : ' ends.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end service Service GetReactModeHistoryDev(ReactNo, DaysToReport) Response = '' If ( (ReactNo NE '') and (DaysToReport NE '') ) then Open 'REACT_MODE' to ReactModeTable then OPEN 'DICT.REACT_MODE' TO @DICT then StartDt = Date() - DaysToReport StartDt = OCONV(StartDt,'D4/') SelectSent = 'SELECT REACT_MODE WITH REACT_NO = ':QUOTE(ReactNo):' AND WITH START_DT > ':QUOTE(StartDt):' BY-DSND START_DTM ' Set_Status(0) errCode = '' RList(SelectSent, TARGET_ACTIVELIST$, "", "", "") If Not(Get_Status(errCode)) then @RecCount = 0 EOF = False$ Loop Readnext @ID else EOF = True$ While EOF EQ False$ READO @RECORD FROM ReactModeTable,@ID then @RecCount += 1 StartDTM = OCONV({START_DTM},'DT2/^HS') StopDTM = OCONV({STOP_DTM},'DT2/^HS') ElapsedHrs = OCONV({ELAP_HRS},'MD2,') Mode = OCONV({MODE},'[REACT_MODE_CONV]') StartRLID = {START_RL_ID} ProbCatIDs = {PROB_CAT_ID} ProbCatDescs = {PROB_CAT_DESC} ServIDs = {SERV_ID} ServDescs = {SERV_DESC} StartUser = {START_USER} StopUser = {STOP_USER} Notes = {START_NOTES} * SWAP ' ' WITH CRLF$ IN StartDTM * SWAP ' ' WITH CRLF$ IN StopDTM FOR I = 1 TO COUNT(ProbCatIDs,@VM) + (ProbCatIDs NE '') ProbCatDescs<1,I> = ProbCatIDs<1,I>:' - ':ProbCatDescs<1,I> NEXT I FOR I = 1 TO COUNT(ServIDs,@VM) + (ServIDs NE '') ServDescs<1,I> = ServIDs<1,I>:' - ':ServDescs<1,I> NEXT I SWAP @VM WITH CRLF$ IN ProbCatDescs SWAP @VM WITH CRLF$ IN ServDescs Response<@RecCount, 1> = StartDTM Response<@RecCount, 2> = ElapsedHrs Response<@RecCount, 3> = Mode Response<@RecCount, 4> = Notes Response<@RecCount, 5> = StartRLID Response<@RecCount, 6> = ProbCatDescs Response<@RecCount, 7> = ServDescs Response<@RecCount, 8> = StartUser end Repeat end else ErrMsg = 'Error in service ':Service:'. Error code: ':errCode:'.' Error_Services('Add', ErrorMsg) end end else ErrorMsg = 'Unable to Open "DICT.REACT_MODE" table!' Error_Services('Add', ErrorMsg) end end else ErrorMsg = 'Unable to Open "REACT_MODE" table!' Error_Services('Add', ErrorMsg) end end end service //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Internal GoSubs ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////