open-insight/LSL2/STPROC/REACTOR_SERVICES_DEV.txt
Infineon\StieberD 7762b129af pre cutover push
2024-09-04 20:33:41 -07:00

1049 lines
61 KiB
Plaintext

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<REACTOR_REACT_TYPE$>
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<REACTOR_REACT_ASSIGNMENT$>, 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'AssignmentDescription', Oconv(ReactorRow<REACTOR_REACT_ASSIGNMENT$>, '[REACT_ASSIGN_CONV]'), 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'Location', ReactorRow<REACTOR_LOCATIONX$>, 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'SusceptorSize', ReactorRow<REACTOR_SUSC_POCKET_SIZE$>, 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'SecondChamber', ReactorRow<REACTOR_SECOND_CHAMBER$>, 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'PickPlace', ReactorRow<REACTOR_PICK_PLACE$>, 'STRING')
SRP_JSON(objReactor, 'SETVALUE', 'NotRepairable', ReactorRow<REACTOR_NOT_REPAIRABLE$>, '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<SCHED_DET_NG.WO_NO$>
EpiPartNo = Xlate('WO_LOG', WorkOrderNo, 'EPI_PART_NO', 'X')
ReactorNo = EventRec<SCHED_DET_NG.REACT_NO$>
* ScheduleDate = Field(EventRec<SCHED_DET_NG.START_DTM$>, '.', 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<RDS_REACTOR$>
ReactorRow = Database_Services('ReadDataRow', 'REACTOR', ReactorNo, True$, 60, False$)
ReactorType = ReactorRow<REACTOR_REACT_TYPE$>
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<REACTOR_SECOND_CHAMBER$>
If SecondChamber EQ '' then
CompareReactorNo = ReactorNo - 2
CompareReactorRow = Database_Services('ReadDataRow', 'REACTOR', CompareReactorNo, True$, 60, False$)
CompareSecondChamber = CompareReactorRow<REACTOR_SECOND_CHAMBER$>
If CompareSecondChamber EQ ReactorNo then Transfer CompareReactorNo to ReactorNo
end
end
* EpiPartNo = RDSRow<RDS_PART_NUM$>
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<RDS_WAFERS_IN$>
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<REACTOR_REACT_TYPE$>
SecondChamber = ReactorRow<REACTOR_SECOND_CHAMBER$>
@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<REACTOR_REACT_TYPE$>
SecondChamber = ReactorRow<REACTOR_SECOND_CHAMBER$>
@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<REACTOR_REACT_TYPE$>
SecondChamber = ReactorRow<REACTOR_SECOND_CHAMBER$>
@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<REACTOR_REACT_TYPE$>
SecondChamber = ReactorRow<REACTOR_SECOND_CHAMBER$>
@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
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////