updated headers for nica order request Added reactor type support to nica checklists. Refactored flow logic to just use NICA_CHECKLISTS table. added feature flag support gated Feature Flags menu item to supervisors removed debug added auto comment for intr maint flows on reactor log, intr maint flow id to react servs form, and cancel order on unsign reactor log added exceptions for lamp and tc services, added control to edit flow id on react servs form, added auto-reactor log comment, added cancel order on unsign event removed debug modified NicaOrdersServices to use env variables for group resource name added logic to filter out service flow ids for servics with is_intrusive set to false, modified security group for feature flag menu, added ability to clear intr main flow id to react serv form removed unused equates
3722 lines
189 KiB
Plaintext
3722 lines
189 KiB
Plaintext
Function Reactor_Services(@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
|
|
|
|
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 CreatePerformanceTrackers service so the CreateWeeklyPerformanceReport 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 GetReactor service.
|
|
12/06/23 djm Add MD3 conversion to TargetThickness in metric increment and decrement services.
|
|
|
|
***********************************************************************************************************************/
|
|
#pragma precomp SRP_PreCompiler
|
|
|
|
$insert APP_INSERTS
|
|
$insert SERVICE_SETUP
|
|
$insert REACTOR_EQUATES
|
|
$insert RDS_EQUATES
|
|
$insert RLIST_EQUATES
|
|
$insert TOOL_EQUATES
|
|
$Insert REACTOR_LOG_EQUATES
|
|
$Insert REACTOR_CHILD_KEY_IDS_EQUATES
|
|
$Insert REACTOR_MODES_EQUATES
|
|
$Insert REACT_MODE_EQU ;* THESE ARE NOT THE SAME jch, Update 9/15/21. These are the equates for the CONFIG records
|
|
$Insert REACT_MODE_NG_EQUATES
|
|
$Insert REACT_UTIL_EQU
|
|
$Insert SCHED_DET_NG_EQUATES
|
|
$Insert REACT_STATUS_EQUATES
|
|
$Insert WO_LOG_EQUATES
|
|
$Insert REACTOR_DAILY_UPTIME_EQUATES
|
|
$Insert REACT_LL_EQUATES
|
|
$Insert IQS_VIOL_DATA_EQUATES
|
|
$Insert FEATURE_FLAGS_EQUATES
|
|
|
|
Equ WOCust$ to 2
|
|
|
|
// Uptime Percentage Equates
|
|
Equ PRODUCTIVE$ to 1
|
|
Equ UNSCHED$ to 2
|
|
Equ SCHED$ to 3
|
|
Equ NONSCHED$ to 4
|
|
Equ ENG$ to 5
|
|
|
|
Declare subroutine Error_Services, Reactor_Services, Memory_Services, RList, Database_Services, SRP_JSON
|
|
Declare subroutine Excel_Services, Schedule_Services, Logging_Services, Set_Status, obj_React_Status, Errmsg
|
|
Declare subroutine Obj_Notes, Btree.Extract, SRP_Fastarray, Delay, Mona_Services, SRP_List, Msg, Rds_Services
|
|
Declare subroutine React_Assign_Conv, Nica_Orders_Services, obj_React_Mode
|
|
Declare function SRP_Array, Reactor_Services, Memory_Services, Database_Services, SRP_Sort_Array, Excel_Services
|
|
Declare function SRP_Math, SRP_Hash, SRP_JSON, Epi_Part_Services, Schedule_Services, Date_Services, Environment_Services
|
|
Declare function Logging_Services, GetCommandLine, NextKey, Reactor_Log_Services, SRP_DateTime, ole_getwebpage
|
|
Declare function Datetime, Reactor_Modes_Services, Work_Order_Services, React_Mode_NG_Services, Lsl_Users_Services
|
|
Declare function SRP_Time, Rds_Services, SRP_Fastarray, Httpclient_Services, SRP_List, Utility, Memberof, Error_Services
|
|
Declare function Nica_Orders_Services
|
|
|
|
// Report paths for various performance report services.
|
|
TemplatesFolder = Environment_Services('GetApplicationRootPath') : '\Reports\Scheduler\Templates\'
|
|
DailyReportsFolder = Environment_Services('GetApplicationRootPath') : '\Reports\Scheduler\Daily\'
|
|
WeeklyReportsFolder = Environment_Services('GetApplicationRootPath') : '\Reports\Scheduler\Weekly\'
|
|
|
|
CommandLine = GetCommandLine()
|
|
Machine = Environment_Services('GetServer')
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
GoToService else
|
|
|
|
end
|
|
|
|
Return Response else ''
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Service Parameter Options
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
Options BOOLEAN = True$, False$
|
|
Options REACTORMETRIC = 'TUBE_BELL_JAR_THK', 'TUBE_BELL_JAR_WFR_CNT', 'SUSC_THK', 'SUSC_WFR_CNT', 'LOWER_QUARTZ_THK', 'LOWER_QUARTZ_WFR', 'ARMS_WFR_CNT'
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Services
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// IncrementWfrMetrics
|
|
//
|
|
// RDSNo. - [Required]
|
|
//
|
|
// Increment the REACTOR wafer count and thickness when RDS unload is signed.
|
|
//
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service IncrementWfrMetrics(RDSNo)
|
|
|
|
// Get Reactor and run count details
|
|
RDSRec = Xlate('RDS', RDSNo, '', 'X', '')
|
|
TargetThickness = Xlate('RDS', RDSNo, 'THICK_TARGET_TOT', 'X', '')
|
|
TargetThickness = OConv(TargetThickness, 'MD3')
|
|
WaferCount = RDSRec<RDS_WAFERS_IN$>
|
|
ReactorNo = RDSRec<RDS_REACTOR$>
|
|
OldReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
|
|
NewReactorRec = OldReactorRec
|
|
ReactorType = OldReactorRec<REACTOR_REACT_TYPE$>
|
|
SusceptorSize = OldReactorRec<REACTOR_SUSC_POCKET_SIZE$>
|
|
SusceptorSize = SusceptorSize[-4,1]
|
|
|
|
// Get Old Values
|
|
CurrTubeBellJarThk = OldReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
CurrTubeBellJarCnt = OldReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
CurrSuscThk = OldReactorRec<REACTOR_SUSC_THK$>
|
|
CurrSuscWfrCnt = OldReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
CurrLowerQuartzThk = OldReactorRec<REACTOR_LOWER_QUARTZ_THK$>
|
|
CurrLowerQuartzWfr = OldReactorRec<REACTOR_LOWER_QUARTZ_WFR$>
|
|
|
|
// Arms are not used for EPP
|
|
If ReactorType NE 'EPP' then
|
|
CurrArmsWfrCnt = OldReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
If CurrArmsWfrCnt = '' then CurrArmsWfrCnt = 0
|
|
end
|
|
|
|
// Set values to 0 if blank
|
|
If CurrTubeBellJarThk = '' then CurrTubeBellJarThk = 0
|
|
If CurrTubeBellJarCnt = '' then CurrTubeBellJarCnt = 0
|
|
If CurrSuscThk = '' then CurrSuscThk = 0
|
|
If CurrSuscWfrCnt = '' then CurrSuscWfrCnt = 0
|
|
If CurrLowerQuartzThk = '' then CurrLowerQuartzThk = 0
|
|
If CurrLowerQuartzWfr = '' then CurrLowerQuartzWfr = 0
|
|
|
|
Begin Case
|
|
|
|
Case ReactorType = 'EPP'
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + 1
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + TargetThickness
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + 1
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + TargetThickness
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + 1
|
|
|
|
Case ReactorType = 'HTR'
|
|
|
|
Begin Case
|
|
|
|
Case SusceptorSize = 6
|
|
CntAddition = (WaferCount / 5)
|
|
ThkAddition = (WaferCount / 5) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
Case SusceptorSize = 8
|
|
// Round up
|
|
CntAddition = (WaferCount / 3)
|
|
If Count(CntAddition, '.') EQ 1 Then
|
|
CntAddition = Int(CntAddition) + 1
|
|
end
|
|
|
|
ThkAddition = (WaferCount / 3) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
End Case
|
|
|
|
Case ReactorType = 'ASM' OR ReactorType = 'ASM+'
|
|
|
|
ThkAddition = WaferCount * TargetThickness
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + WaferCount
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + WaferCount
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + WaferCount
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
End Case
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, NewReactorRec, 1, 0, 0)
|
|
|
|
end service
|
|
|
|
|
|
Service GetWaferCntMetricsByReactorID(ReactorID)
|
|
|
|
If ReactorID NE '' then
|
|
If RowExists('REACTOR', ReactorID) then
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorID)
|
|
ReactorType = ReactorRec<REACTOR_REACT_TYPE$>
|
|
ResponseData = ''
|
|
Begin Case
|
|
Case ReactorType EQ 'ASM' OR ReactorType EQ 'ASM+'
|
|
ResponseData<1, 1> = ReactorID
|
|
ResponseData<1, 2> = ReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
ResponseData<1, 3> = ReactorRec<REACTOR_SUSC_THK$>
|
|
ResponseData<1, 4> = ReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
ResponseData<1, 5> = ReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
ResponseData<1, 6> = ReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
//These are the column titles to help us with API Responses
|
|
ResponseData<2, 1> = 'ReactorID'
|
|
ResponseData<2, 2> = 'SusceptorWaferCount'
|
|
ResponseData<2, 3> = 'SusceptorThickness'
|
|
ResponseData<2, 4> = 'TubeWaferCount'
|
|
ResponseData<2, 5> = 'TubeThickness'
|
|
ResponseData<2, 6> = 'ArmsWaferCount'
|
|
Case ReactorType EQ 'HTR'
|
|
ResponseData<1, 1> = ReactorID
|
|
ResponseData<1, 2> = ReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
ResponseData<1, 3> = ReactorRec<REACTOR_SUSC_THK$>
|
|
ResponseData<1, 4> = ReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
ResponseData<1, 5> = ReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
ResponseData<1, 6> = ReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
//These are the column titles to help us with API Responses
|
|
ResponseData<2, 1> = 'ReactorID'
|
|
ResponseData<2, 2> = 'SusceptorWaferCount'
|
|
ResponseData<2, 3> = 'SusceptorThickness'
|
|
ResponseData<2, 4> = 'TubeWaferCount'
|
|
ResponseData<2, 5> = 'TubeThickness'
|
|
ResponseData<2, 6> = 'ArmsWaferCount'
|
|
Case ReactorType EQ 'EPP'
|
|
ResponseData<1, 1> = ReactorID
|
|
ResponseData<1, 2> = ReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
ResponseData<1, 3> = ReactorRec<REACTOR_SUSC_THK$>
|
|
ResponseData<1, 4> = ReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
ResponseData<1, 5> = ReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
ResponseData<1, 6> = ReactorRec<REACTOR_LOWER_QUARTZ_WFR$>
|
|
ResponseData<1, 7> = ReactorRec<REACTOR_LOWER_QUARTZ_THK$>
|
|
//These are the column titles to help us with API Responses
|
|
ResponseData<2, 1> = 'ReactorID'
|
|
ResponseData<2, 2> = 'SusceptorWaferCount'
|
|
ResponseData<2, 3> = 'SusceptorThickness'
|
|
ResponseData<2, 4> = 'BellJarWaferCount'
|
|
ResponseData<2, 5> = 'BellJarThickness'
|
|
ResponseData<2, 6> = 'LowerQuartzWaferCount'
|
|
ResponseData<2, 7> = 'LowerQuartzThickness'
|
|
End Case
|
|
Response = ResponseData
|
|
end else
|
|
Error_Services('Add', 'Error: Invalid Reactor ID passed to REACTOR_SERVICES("GetWaferMetricsByReactorID"')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error: Null Reactor ID passed to REACTOR_SERVICES("GetWaferMetricsByReactorID"')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// DecrementWfrMetrics
|
|
//
|
|
// RDSNo. - [Required]
|
|
//
|
|
// Decrement the REACTOR wafer count and thickness when RDS unload is unsigned.
|
|
//
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service DecrementWfrMetrics(RDSNo)
|
|
|
|
// Get Reactor and run count details
|
|
RDSRec = Xlate('RDS', RDSNo, '', 'X', '')
|
|
TargetThickness = Xlate('RDS', RDSNo, 'THICK_TARGET_TOT', 'X', '')
|
|
TargetThickness = OConv(TargetThickness, 'MD3')
|
|
WaferCount = RDSRec<RDS_WAFERS_IN$>
|
|
ReactorNo = RDSRec<RDS_REACTOR$>
|
|
OldReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
|
|
NewReactorRec = OldReactorRec
|
|
ReactorType = OldReactorRec<REACTOR_REACT_TYPE$>
|
|
SusceptorSize = OldReactorRec<REACTOR_SUSC_POCKET_SIZE$>
|
|
SusceptorSize = SusceptorSize[-4,1]
|
|
|
|
// Get Old Values
|
|
CurrTubeBellJarThk = OldReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
CurrTubeBellJarCnt = OldReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
CurrSuscThk = OldReactorRec<REACTOR_SUSC_THK$>
|
|
CurrSuscWfrCnt = OldReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
CurrLowerQuartzThk = OldReactorRec<REACTOR_LOWER_QUARTZ_THK$>
|
|
CurrLowerQuartzWfr = OldReactorRec<REACTOR_LOWER_QUARTZ_WFR$>
|
|
|
|
// Arms are not used for EPP
|
|
If ReactorType NE 'EPP' then
|
|
CurrArmsWfrCnt = OldReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
If CurrArmsWfrCnt = '' then CurrArmsWfrCnt = 0
|
|
end
|
|
|
|
// Set values to 0 if blank
|
|
If CurrTubeBellJarThk = '' then CurrTubeBellJarThk = 0
|
|
If CurrTubeBellJarCnt = '' then CurrTubeBellJarCnt = 0
|
|
If CurrSuscThk = '' then CurrSuscThk = 0
|
|
If CurrSuscWfrCnt = '' then CurrSuscWfrCnt = 0
|
|
If CurrLowerQuartzThk = '' then CurrLowerQuartzThk = 0
|
|
If CurrLowerQuartzWfr = '' then CurrLowerQuartzWfr = 0
|
|
|
|
Begin Case
|
|
|
|
Case ReactorType = 'EPP'
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - 1
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - TargetThickness
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - 1
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - TargetThickness
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - 1
|
|
|
|
Case ReactorType = 'HTR'
|
|
|
|
Begin Case
|
|
|
|
Case SusceptorSize = 6
|
|
CntAddition = (WaferCount / 5)
|
|
ThkAddition = (WaferCount / 5) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
Case SusceptorSize = 8
|
|
// Round up
|
|
CntAddition = (WaferCount / 3)
|
|
If Count(CntAddition, '.') EQ 1 Then
|
|
CntAddition = Int(CntAddition) + 1
|
|
end
|
|
|
|
ThkAddition = (WaferCount / 3) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
End Case
|
|
|
|
Case ReactorType = 'ASM' OR ReactorType = 'ASM+'
|
|
|
|
ThkAddition = WaferCount * TargetThickness
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - WaferCount
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - WaferCount
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - WaferCount
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
End Case
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, NewReactorRec, 1, 0, 0)
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// IncrementTestWfrMetrics
|
|
//
|
|
// TargetThickness - [Required]
|
|
// WaferCount - [Required]
|
|
// ReactorNo - [Required]
|
|
//
|
|
// Increment the REACTOR wafer count and thickness for test wafers.
|
|
//
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service IncrementTestWfrMetrics(TargetThickness, WaferCount, ReactorNo)
|
|
|
|
OldReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
|
|
NewReactorRec = OldReactorRec
|
|
ReactorType = OldReactorRec<REACTOR_REACT_TYPE$>
|
|
SusceptorSize = OldReactorRec<REACTOR_SUSC_POCKET_SIZE$>
|
|
SusceptorSize = SusceptorSize[-4,1]
|
|
|
|
// Get Old Values
|
|
CurrTubeBellJarThk = OldReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
CurrTubeBellJarCnt = OldReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
CurrSuscThk = OldReactorRec<REACTOR_SUSC_THK$>
|
|
CurrSuscWfrCnt = OldReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
CurrLowerQuartzThk = OldReactorRec<REACTOR_LOWER_QUARTZ_THK$>
|
|
CurrLowerQuartzWfr = OldReactorRec<REACTOR_LOWER_QUARTZ_WFR$>
|
|
|
|
// Arms are not used for EPP
|
|
If ReactorType NE 'EPP' then
|
|
CurrArmsWfrCnt = OldReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
If CurrArmsWfrCnt = '' then CurrArmsWfrCnt = 0
|
|
end
|
|
|
|
// Set values to 0 if blank
|
|
If CurrTubeBellJarThk = '' then CurrTubeBellJarThk = 0
|
|
If CurrTubeBellJarCnt = '' then CurrTubeBellJarCnt = 0
|
|
If CurrSuscThk = '' then CurrSuscThk = 0
|
|
If CurrSuscWfrCnt = '' then CurrSuscWfrCnt = 0
|
|
If CurrLowerQuartzThk = '' then CurrLowerQuartzThk = 0
|
|
If CurrLowerQuartzWfr = '' then CurrLowerQuartzWfr = 0
|
|
|
|
Begin Case
|
|
|
|
Case ReactorType = 'EPP'
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + 1
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + TargetThickness
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + 1
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + TargetThickness
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + 1
|
|
|
|
Case ReactorType = 'HTR'
|
|
|
|
Begin Case
|
|
|
|
Case SusceptorSize = 6
|
|
CntAddition = (WaferCount / 5)
|
|
ThkAddition = (WaferCount / 5) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
Case SusceptorSize = 8
|
|
// Round up
|
|
CntAddition = (WaferCount / 3)
|
|
If Count(CntAddition, '.') EQ 1 Then
|
|
CntAddition = Int(CntAddition) + 1
|
|
end
|
|
|
|
ThkAddition = (WaferCount / 3) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
End Case
|
|
|
|
Case ReactorType = 'ASM' OR ReactorType = 'ASM+'
|
|
|
|
ThkAddition = WaferCount * TargetThickness
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk + ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt + WaferCount
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt + WaferCount
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk + ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr + WaferCount
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt + WaferCount
|
|
|
|
End Case
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, NewReactorRec, 1, 0, 0)
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// DecrementTestWfrMetrics
|
|
//
|
|
// TargetThickness - [Required]
|
|
// WaferCount - [Required]
|
|
// ReactorNo - [Required]
|
|
//
|
|
// Decrement the REACTOR wafer count and thickness for test wafers.
|
|
//
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service DecrementTestWfrMetrics(TargetThickness, WaferCount, ReactorNo)
|
|
|
|
OldReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
|
|
NewReactorRec = OldReactorRec
|
|
ReactorType = OldReactorRec<REACTOR_REACT_TYPE$>
|
|
SusceptorSize = OldReactorRec<REACTOR_SUSC_POCKET_SIZE$>
|
|
SusceptorSize = SusceptorSize[-4,1]
|
|
|
|
// Get Old Values
|
|
CurrTubeBellJarThk = OldReactorRec<REACTOR_TUBE_BELL_JAR_THK$>
|
|
CurrTubeBellJarCnt = OldReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$>
|
|
CurrSuscThk = OldReactorRec<REACTOR_SUSC_THK$>
|
|
CurrSuscWfrCnt = OldReactorRec<REACTOR_SUSC_WFR_CNT$>
|
|
CurrLowerQuartzThk = OldReactorRec<REACTOR_LOWER_QUARTZ_THK$>
|
|
CurrLowerQuartzWfr = OldReactorRec<REACTOR_LOWER_QUARTZ_WFR$>
|
|
|
|
// Arms are not used for EPP
|
|
If ReactorType NE 'EPP' then
|
|
CurrArmsWfrCnt = OldReactorRec<REACTOR_ARMS_WFR_CNT$>
|
|
If CurrArmsWfrCnt = '' then CurrArmsWfrCnt = 0
|
|
end
|
|
|
|
// Set values to 0 if blank
|
|
If CurrTubeBellJarThk = '' then CurrTubeBellJarThk = 0
|
|
If CurrTubeBellJarCnt = '' then CurrTubeBellJarCnt = 0
|
|
If CurrSuscThk = '' then CurrSuscThk = 0
|
|
If CurrSuscWfrCnt = '' then CurrSuscWfrCnt = 0
|
|
If CurrLowerQuartzThk = '' then CurrLowerQuartzThk = 0
|
|
If CurrLowerQuartzWfr = '' then CurrLowerQuartzWfr = 0
|
|
|
|
Begin Case
|
|
|
|
Case ReactorType = 'EPP'
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - 1
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - TargetThickness
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - 1
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - TargetThickness
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - 1
|
|
|
|
Case ReactorType = 'HTR'
|
|
|
|
Begin Case
|
|
|
|
Case SusceptorSize = 6
|
|
CntAddition = (WaferCount / 5)
|
|
ThkAddition = (WaferCount / 5) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk + ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
Case SusceptorSize = 8
|
|
// Round up
|
|
CntAddition = (WaferCount / 3)
|
|
If Count(CntAddition, '.') EQ 1 Then
|
|
CntAddition = Int(CntAddition) + 1
|
|
end
|
|
|
|
ThkAddition = (WaferCount / 3) * TargetThickness
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - CntAddition
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - CntAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - CntAddition
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
End Case
|
|
|
|
Case ReactorType = 'ASM' OR ReactorType = 'ASM+'
|
|
|
|
ThkAddition = WaferCount * TargetThickness
|
|
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = CurrTubeBellJarThk - ThkAddition
|
|
NewReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = CurrTubeBellJarCnt - WaferCount
|
|
NewReactorRec<REACTOR_SUSC_THK$> = CurrSuscThk - ThkAddition
|
|
NewReactorRec<REACTOR_SUSC_WFR_CNT$> = CurrSuscWfrCnt - WaferCount
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_THK$> = CurrLowerQuartzThk - ThkAddition
|
|
NewReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = CurrLowerQuartzWfr - WaferCount
|
|
NewReactorRec<REACTOR_ARMS_WFR_CNT$> = CurrArmsWfrCnt - WaferCount
|
|
|
|
End Case
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, NewReactorRec, 1, 0, 0)
|
|
|
|
end service
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ResetWfrMetric
|
|
//
|
|
// RDSNo. - [Required]
|
|
// MetricType - [Required]('TUBE_BELL_JAR_THK', 'TUBE_BELL_JAR_WFR_CNT', 'SUSC_THK', 'SUSC_WFR_CNT', 'LOWER_QUARTZ_THK', 'LOWER_QUARTZ_WFR', 'ARMS_WFR_CNT')
|
|
//
|
|
// Reset a specified REACTOR metric to 0.
|
|
//
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ResetWfrMetric(ReactorNo, MetricType = REACTORMETRIC)
|
|
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactorNo)
|
|
|
|
Begin Case
|
|
|
|
Case MetricType = 'TUBE_BELL_JAR_THK'
|
|
ReactorRec<REACTOR_TUBE_BELL_JAR_THK$> = 0
|
|
|
|
Case MetricType = 'TUBE_BELL_JAR_WFR_CNT'
|
|
ReactorRec<REACTOR_TUBE_BELL_JAR_WFR_CNT$> = 0
|
|
|
|
Case MetricType = 'SUSC_THK'
|
|
ReactorRec<REACTOR_SUSC_THK$> = 0
|
|
|
|
Case MetricType = 'SUSC_WFR_CNT'
|
|
ReactorRec<REACTOR_SUSC_WFR_CNT$> = 0
|
|
|
|
Case MetricType = 'LOWER_QUARTZ_THK'
|
|
ReactorRec<REACTOR_LOWER_QUARTZ_THK$> = 0
|
|
|
|
Case MetricType = 'LOWER_QUARTZ_WFR'
|
|
ReactorRec<REACTOR_LOWER_QUARTZ_WFR$> = 0
|
|
|
|
Case MetricType = 'ARMS_WFR_CNT'
|
|
ReactorRec<REACTOR_ARMS_WFR_CNT$> = 0
|
|
|
|
End Case
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactorNo, ReactorRec, 1, 0, 0)
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetReactors
|
|
//
|
|
// 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 GetReactors(MatchType, MatchSize)
|
|
|
|
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('GetReactor', 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$
|
|
Case Not(RowExists('TOOL', 'R':ReactorNo))
|
|
// This tool does not exist
|
|
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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetReactorNumbers
|
|
//
|
|
// Returns an @FM delimited list of Reactor Numbers.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetReactorNumbers(MatchType, MatchSize)
|
|
|
|
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('GetReactor', 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 ReactorType EQ ''
|
|
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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// GetReactor
|
|
//
|
|
// Returns a JSON formatted object of information related to the indicated reactor number.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service GetReactor(ReactorNo)
|
|
|
|
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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// CreatePerformanceTrackers
|
|
//
|
|
// Creates performance tracking database rows in the REACTOR_PERFORMANCE table. This creates a unique tracker for each
|
|
// Reactor/Part pair based on the indicated dates scheduled work orders.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service CreatePerformanceTrackers(ScheduleDate, CreateReports)
|
|
|
|
// 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('GetScheduleEvents', ScheduleDate, ScheduleDate, '', '', False$)
|
|
If ScheduleEvents NE '' then
|
|
PerfKeyIDs = ''
|
|
For Each ScheduleEvent in ScheduleEvents using @FM
|
|
KeyIDs = ScheduleEvent<0, 2>
|
|
WorkOrderNo = KeyIDs[1, '*']
|
|
EpiPartNo = KeyIDs[Col2() + 1, '*']
|
|
ReactorNo = KeyIDs[Col2() + 1, '*']
|
|
ScheduleDate = KeyIDs[Col2() + 1, '*']
|
|
Sequence = KeyIDs[Col2() + 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', ReactorNo, WorkOrderNo, ScheduleDate, Sequence, 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', PerfKeyID, True$, 0)
|
|
PerfRow<2> = PerfRow<2> + Iconv(WafersExpected, 'MD2')
|
|
Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE', 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', PerfKeyID, True$, 0)
|
|
PerfRow<2> = PerfRow<2> * ProRate
|
|
Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE', PerfKeyID, PerfRow, True$, False$, True$)
|
|
end
|
|
Next PerfKeyID
|
|
|
|
// Clear out all cached data.
|
|
Memory_Services('ReleaseHashTable')
|
|
end
|
|
end
|
|
|
|
If CreateReports then
|
|
Reactor_Services('CreateDailyPerformanceReport', ScheduleDate)
|
|
If Mod(ScheduleDate, 7) EQ 5 then
|
|
// This is early Friday. Create the weekly performance report for the upcoming week. First, the
|
|
// CreatePerformanceTrackers must be called for all days in the upcoming week.
|
|
NextMonday = ScheduleDate + 3
|
|
NextSunday = ScheduleDate + 9
|
|
For ScheduleDate = NextMonday to NextSunday
|
|
Reactor_Services('CreatePerformanceTrackers', 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('CreateWeeklyPerformanceReport', 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('ClearWafersExpected', ScheduleDate)
|
|
Next ScheduleDate
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// UpdatePerformanceTrackers
|
|
//
|
|
// Updates the wafers processed column in the performance tracking database rows.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service UpdatePerformanceTrackers(ScheduleDate, CreateReports)
|
|
|
|
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', 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', PerfKeyID, PerfRow, True$, False$, True$)
|
|
end
|
|
end
|
|
Repeat
|
|
|
|
If CreateReports then
|
|
Reactor_Services('UpdateDailyPerformanceReport', 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('UpdateWeeklyPerformanceReport', ScheduleDate - 6)
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ClearWafersExpected
|
|
//
|
|
// Clears the expected wafers for all database rows the REACTOR_PERFORMANCE table based on the indicated schedule date.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ClearWafersExpected(ScheduleDate)
|
|
|
|
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')
|
|
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', @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', PerfKeyID, True$, 0)
|
|
PerfRow<2> = ''
|
|
Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE', PerfKeyID, PerfRow, True$, False$, True$)
|
|
Next DetailPerfKeyID
|
|
end
|
|
end
|
|
end
|
|
Repeat
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// ClearWafersProcessed
|
|
//
|
|
// Clears the processed wafers for all database rows the REACTOR_PERFORMANCE table based on the indicated schedule date.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service ClearWafersProcessed(ScheduleDate)
|
|
|
|
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')
|
|
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', @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', PerfKeyID, True$, 0)
|
|
PerfRow<3> = ''
|
|
Database_Services('WriteDataRow', 'REACTOR_PERFORMANCE', PerfKeyID, PerfRow, True$, False$, True$)
|
|
Next DetailPerfKeyID
|
|
end
|
|
end
|
|
end
|
|
Repeat
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// CreateDailyPerformanceReport
|
|
//
|
|
// Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE table. This creates an
|
|
// Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service CreateDailyPerformanceReport(ScheduleDate)
|
|
|
|
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')
|
|
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', PerfKeyID, True$, 0)
|
|
DetailPerfKeyIDs = PerfRow<1>
|
|
If DetailPerfKeyIDs NE '' then
|
|
For Each @ID in DetailPerfKeyIDs using @VM
|
|
@RECORD = Database_Services('ReadDataRow', 'REACTOR_PERFORMANCE', @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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// UpdateDailyPerformanceReport
|
|
//
|
|
// Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE table. This creates an
|
|
// Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service UpdateDailyPerformanceReport(ScheduleDate)
|
|
|
|
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')
|
|
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', @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)
|
|
//Comment = Excel_Services('GetCellValue', objDocument, 'SSR', 'M', CellRow)
|
|
//Excel_Services('SetCellValue', objDocument, 'SSR', 'M', CellRow, Comment)
|
|
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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// CreateWeeklyPerformanceReport
|
|
//
|
|
// Creates weekly performance tracking report using the database rows in the REACTOR_PERFORMANCE table. This creates an
|
|
// Excel spreadsheet using the "Fab Performance Weekly Template.xlsx" file as a template.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service CreateWeeklyPerformanceReport(YearWeekNo)
|
|
|
|
// 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')
|
|
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', 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', @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
|
|
|
|
end service
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// UpdateWeeklyPerformanceReport
|
|
//
|
|
// Creates daily performance tracking report using the database rows in the REACTOR_PERFORMANCE table. This creates an
|
|
// Excel spreadsheet using the "Fab Performance Daily Template.xlsx" file as a template.
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
Service UpdateWeeklyPerformanceReport(YearWeekNo)
|
|
|
|
// 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')
|
|
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', @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, 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(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
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactorCurrLoad(ReactNo)
|
|
|
|
Response = ''
|
|
ReactStatusRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactNo)
|
|
LoadedCassettes = ReactStatusRec<REACT_STATUS_LOAD_CASS_ID$>
|
|
Response = LoadedCassettes
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorCurrLoadRDS(ReactNo)
|
|
|
|
Response = ''
|
|
ReactStatusRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactNo)
|
|
LoadedCassettes = ReactStatusRec<REACT_STATUS_LOAD_RDS$>
|
|
Response = LoadedCassettes
|
|
|
|
|
|
Response = ''
|
|
ReactStatusRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactNo)
|
|
LoadedCassettes = ReactStatusRec<REACT_STATUS_LOAD_RDS$>
|
|
Response = LoadedCassettes
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactCurrModeRec(ReactNo)
|
|
|
|
Response = ''
|
|
ReactModeRecKey = Xlate('REACTOR_CHILD_KEY_IDS_NG', ReactNo, REACTOR_CHILD_KEY_IDS_REACT_MODE_KEY_IDS$, 'X')
|
|
ReactModeRec = Database_Services('ReadDataRow', 'REACT_MODE_NG', ReactModeRecKey)
|
|
Response = ReactModeRec
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactCurrModeId(ReactNo)
|
|
|
|
Response = ''
|
|
ReactModeRecKey = Xlate('REACTOR_CHILD_KEY_IDS_NG', ReactNo, REACTOR_CHILD_KEY_IDS_REACT_MODE_KEY_IDS$, 'X')
|
|
Response = ReactModeRecKey
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactCurrModeName(ReactNo)
|
|
|
|
Response = ''
|
|
ReactModeRec = Reactor_Services('GetReactCurrModeRec', ReactNo)
|
|
Response = ReactModeRec<REACT_MODE_NG_MODE$>
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactModeHistory(ReactNo, DaysToReport)
|
|
|
|
StartDt = Date() - DaysToReport
|
|
Response = ''
|
|
LegacyDate = 19749
|
|
If ( (ReactNo NE '') and (DaysToReport NE '') ) then
|
|
If Date() - DaysToReport LE LegacyDate then
|
|
modeArray = ''
|
|
// New Modes
|
|
SelectSent = 'SELECT REACT_MODE_NG WITH REACT_NO = ':QUOTE(ReactNo):' AND WITH START_DT > ':QUOTE(OConv(StartDt, 'D4/')):' BY-DSND START_DTM '
|
|
Set_Status(0)
|
|
RList(SelectSent, TARGET_ACTIVELIST$, "", "", "")
|
|
IF Get_Status(errCode) THEN
|
|
ErrMsg(errCode)
|
|
RETURN
|
|
END
|
|
IF @RecCount then
|
|
EoF = 0
|
|
NumKeys = @RecCount
|
|
Cnt = 0
|
|
|
|
Loop
|
|
ReadNext Mode Else EoF = 1
|
|
until EoF
|
|
RowToAdd = ''
|
|
ServiceCategories = XLATE('REACT_MODE_NG', Mode, 'PROB_CAT_DESC', 'X')
|
|
swap @VM with @svm in ServiceCategories
|
|
ServiceDescs = XLATE('REACT_MODE_NG', Mode, 'SERV_DESC', 'X')
|
|
ReactorLogID = XLATE('REACT_MODE_NG', Mode, 'START_RL_ID', 'X')
|
|
StartDTM = OCONV(XLATE('REACT_MODE_NG', Mode, 'START_DTM', 'X'),'DT2/^HS')
|
|
ServiceNotes = XLATE('REACTOR_LOG',ReactorLogID, REACTOR_LOG_NOTES$, 'X')
|
|
swap @VM with @svm in ServiceDescs
|
|
RowToAdd <1,1> = StartDTM
|
|
RowToAdd <1,2> = OCONV(XLATE('REACT_MODE_NG', Mode,'ELAP_HRS','X'),'MD2,')
|
|
RowToAdd <1,3> = OCONV(XLATE('REACT_MODE_NG', Mode, 'MODE', 'X' ),'[REACT_MODE_CONV]')
|
|
RowToAdd <1,4> = XLATE('REACT_MODE_NG', Mode, 'START_NOTES', 'X')
|
|
RowToAdd <1,5> = ServiceCategories
|
|
RowToAdd <1,6> = XLATE('REACT_MODE_NG', Mode, 'START_USER', 'X')
|
|
RowToAdd <1,7> = ReactorLogID
|
|
RowToAdd <1,8> = ServiceDescs
|
|
|
|
ServiceNotesDtms = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_NOTES_DTMS$, 'X')
|
|
ServiceNotesUsers = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_NOTES_USERS$, 'X')
|
|
|
|
ServiceNotesFormatted = ''
|
|
For each ServiceNote in ServiceNotes using @VM setting vPos
|
|
ServiceNotesFormatted<0, vPos> = OConv(ServiceNotesDtms<0, vPos>, 'DT2/^H') : ' - ' : OConv(ServiceNotesUsers<0, vPos>, '[CONV_XLATE,LSL_USERS*FIRST_LAST]') : ' - ' : ServiceNote
|
|
Next ServiceNote
|
|
|
|
NumNotes = DCount(ServiceNotesFormatted, @VM)
|
|
// Wrap text using CRLF$
|
|
For NoteIndex = 1 to NumNotes
|
|
Note = ServiceNotesFormatted<0, NoteIndex>
|
|
NoteLen = Len(Note)
|
|
If NoteLen GT 100 then
|
|
NumLoops = Int(NoteLen/100)
|
|
For LoopIndex = 1 to NumLoops
|
|
Dummy = Note[LoopIndex * 100, 'F ']
|
|
Loc = Col2()
|
|
Note[Loc, 0] = CRLF$
|
|
Next LoopIndex
|
|
ServiceNotesFormatted<0, NoteIndex> = Note : CRLF$
|
|
end
|
|
Next NoteIndex
|
|
|
|
ServiceNotes = ServiceNotesFormatted
|
|
|
|
Swap @VM with CRLF$ in ServiceNotes
|
|
RowToAdd <1,9> = ServiceNotes
|
|
modeArray := RowToAdd : @FM
|
|
Repeat
|
|
|
|
end
|
|
GoSub ClearCursors
|
|
ClearSelect TARGET_ACTIVELIST$
|
|
// Old Modes
|
|
SelectSent = 'SELECT REACT_MODE WITH REACT_NO = ':QUOTE(ReactNo):' AND WITH START_DT > ':QUOTE(OConv(StartDt, 'D4/')):' BY-DSND START_DTM '
|
|
Set_Status(0)
|
|
RList(SelectSent, TARGET_ACTIVELIST$, "", "", "")
|
|
IF Get_Status(errCode) THEN
|
|
ErrMsg(errCode)
|
|
RETURN
|
|
END
|
|
|
|
IF @RecCount then
|
|
EoF = 0
|
|
NumKeys = @RecCount
|
|
Cnt = 0
|
|
|
|
Loop
|
|
ReadNext Mode Else EoF = 1
|
|
until EoF
|
|
|
|
RowToAdd = ''
|
|
ServiceCategories = XLATE('REACT_MODE', Mode, 'PROB_CAT_DESC', 'X')
|
|
swap @VM with @svm in ServiceCategories
|
|
ServiceDescs = XLATE('REACT_MODE', Mode, 'SERV_DESC', 'X')
|
|
ReactorLogID = XLATE('REACT_MODE', Mode, 'START_RL_ID', 'X')
|
|
StartDTM = OCONV(XLATE('REACT_MODE', Mode, 'START_DTM', 'X'),'DT2/^HS')
|
|
ServiceNotes = XLATE('REACTOR_LOG',ReactorLogID, REACTOR_LOG_NOTES$, 'X')
|
|
swap @VM with @svm in ServiceDescs
|
|
RowToAdd <1,1> = StartDTM
|
|
RowToAdd <1,2> = OCONV(XLATE('REACT_MODE', Mode,'ELAP_HRS','X'),'MD2,')
|
|
RowToAdd <1,3> = OCONV(XLATE('REACT_MODE', Mode, 'MODE', 'X' ),'[REACT_MODE_CONV]')
|
|
RowToAdd <1,4> = XLATE('REACT_MODE', Mode, 'START_NOTES', 'X')
|
|
RowToAdd <1,5> = ServiceCategories
|
|
RowToAdd <1,6> = XLATE('REACT_MODE', Mode, 'START_USER', 'X')
|
|
RowToAdd <1,7> = ReactorLogID
|
|
RowToAdd <1,8> = ServiceDescs
|
|
|
|
ServiceNotesDtms = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_NOTES_DTMS$, 'X')
|
|
ServiceNotesUsers = Xlate('REACTOR_LOG', ReactorLogID, REACTOR_LOG_NOTES_USERS$, 'X')
|
|
|
|
ServiceNotesFormatted = ''
|
|
For each ServiceNote in ServiceNotes using @VM setting vPos
|
|
ServiceNotesFormatted<0, vPos> = OConv(ServiceNotesDtms<0, vPos>, 'DT2/^H') : ' - ' : OConv(ServiceNotesUsers<0, vPos>, '[CONV_XLATE,LSL_USERS*FIRST_LAST]') : ' - ' : ServiceNote
|
|
Next ServiceNote
|
|
|
|
NumNotes = DCount(ServiceNotesFormatted, @VM)
|
|
// Wrap text using CRLF$
|
|
For NoteIndex = 1 to NumNotes
|
|
Note = ServiceNotesFormatted<0, NoteIndex>
|
|
NoteLen = Len(Note)
|
|
If NoteLen GT 100 then
|
|
NumLoops = Int(NoteLen/100)
|
|
For LoopIndex = 1 to NumLoops
|
|
Dummy = Note[LoopIndex * 100, 'F ']
|
|
Loc = Col2()
|
|
Note[Loc, 0] = CRLF$
|
|
Next LoopIndex
|
|
ServiceNotesFormatted<0, NoteIndex> = Note : CRLF$
|
|
end
|
|
Next NoteIndex
|
|
|
|
ServiceNotes = ServiceNotesFormatted
|
|
|
|
Swap @VM with @SVM in ServiceNotes
|
|
RowToAdd <1,9> = ServiceNotes
|
|
modeArray := RowToAdd : @FM
|
|
|
|
|
|
Repeat
|
|
response = modeArray
|
|
end
|
|
end else
|
|
Open 'REACT_MODE_NG' to ReactModeTable then
|
|
OPEN 'DICT.REACT_MODE_NG' TO @DICT then
|
|
|
|
//StartDt = OCONV(StartDt,'D4/')
|
|
SelectSent = 'SELECT REACT_MODE_NG WITH REACT_NO = ':QUOTE(ReactNo):' AND WITH START_DT > ':QUOTE(OConv(StartDt, 'D4/')):' 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}
|
|
ServiceNotes = XLATE('REACTOR_LOG', StartRLID, REACTOR_LOG_NOTES$, 'X')
|
|
ServiceNotesDtms = Xlate('REACTOR_LOG', StartRLID, REACTOR_LOG_NOTES_DTMS$, 'X')
|
|
ServiceNotesUsers = Xlate('REACTOR_LOG', StartRLID, REACTOR_LOG_NOTES_USERS$, 'X')
|
|
ServiceNotesFormatted = ''
|
|
|
|
For each ServiceNote in ServiceNotes using @VM setting vPos
|
|
ServiceNotesFormatted<0, vPos> = OConv(ServiceNotesDtms<0, vPos>, 'DT2/^H') : ' - ' : OConv(ServiceNotesUsers<0, vPos>, '[CONV_XLATE,LSL_USERS*FIRST_LAST]') : ' - ' : ServiceNote
|
|
Next ServiceNote
|
|
|
|
NumNotes = DCount(ServiceNotesFormatted, @VM)
|
|
// Wrap text using CRLF$
|
|
For NoteIndex = 1 to NumNotes
|
|
Note = ServiceNotesFormatted<0, NoteIndex>
|
|
NoteLen = Len(Note)
|
|
If NoteLen GT 100 then
|
|
NumLoops = Int(NoteLen/100)
|
|
For LoopIndex = 1 to NumLoops
|
|
Dummy = Note[LoopIndex * 100, 'F ']
|
|
Loc = Col2()
|
|
Note[Loc, 0] = CRLF$
|
|
Next LoopIndex
|
|
ServiceNotesFormatted<0, NoteIndex> = Note : CRLF$
|
|
end
|
|
Next NoteIndex
|
|
|
|
ServiceNotes = ServiceNotesFormatted
|
|
|
|
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
|
|
Swap @VM with CRLF$ in ServiceNotes
|
|
|
|
Response<@RecCount, 1> = StartDTM
|
|
Response<@RecCount, 2> = ElapsedHrs
|
|
Response<@RecCount, 3> = Mode
|
|
Response<@RecCount, 4> = Notes
|
|
Response<@RecCount, 5> = ProbCatDescs
|
|
Response<@RecCount, 6> = StartUser
|
|
Response<@RecCount, 7> = StartRLID
|
|
Response<@RecCount, 8> = ServDescs
|
|
Response<@RecCount, 9> = ServiceNotes
|
|
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_NG" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to Open "REACT_MODE_NG" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorCassLoadHistory(ReactNo, DaysToReport)
|
|
|
|
Response = ''
|
|
If ( (ReactNo NE '') and (DaysToReport NE '') ) then
|
|
Open 'RDS' to RDSTable then
|
|
OPEN 'DICT.RDS' TO @DICT then
|
|
StartDt = Date() - DaysToReport
|
|
SelectSent = 'SELECT RDS WITH REACTOR = ':QUOTE(ReactNo):' AND WITH DATE_IN > ':QUOTE(OConv(StartDt, 'D4/')):' BY-DSND DATETIME_IN '
|
|
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 RDSTable,@ID then
|
|
@RecCount += 1
|
|
RDSNo = {SEQ}
|
|
DateIn = OCONV({DATETIME_IN},'DT2/^HS')
|
|
DateOut = OCONV({DATETIME_OUT},'DT2/^HS')
|
|
LoadOperator = {OPERATOR_IN}
|
|
UnLoadOperator = {OPERATOR_OUT}
|
|
|
|
Response<@RecCount, 1> = RDSNo
|
|
Response<@RecCount, 2> = DateIn
|
|
Response<@RecCount, 3> = DateOut
|
|
Response<@RecCount, 4> = LoadOperator
|
|
Response<@RecCount, 5> = UnLoadOperator
|
|
end
|
|
Repeat
|
|
end else
|
|
ErrMsg = 'Error in service ':Service:'. Error code: ':errCode:'.'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to Open "DICT.RDS" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to Open "RDS" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactorCassLoadHistoryRange(ReactNo, StartDTM, StopDTM)
|
|
|
|
Response = ''
|
|
If ( (ReactNo NE '') and (StartDTM NE '') and (StopDTM NE '')) then
|
|
Open 'RDS' to RDSTable then
|
|
OPEN 'DICT.RDS' TO @DICT then
|
|
SelectSent = 'SELECT RDS WITH REACTOR EQ ':ReactNo:' AND WITH DATETIME_IN GE ':StartDTM:' AND WITH DATETIME_IN LE ':StopDTM:' BY-DSND DATETIME_IN '
|
|
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 RDSTable,@ID then
|
|
@RecCount += 1
|
|
RDSNo = {SEQ}
|
|
DateIn = OCONV({DATETIME_IN},'DT2/^HS')
|
|
DateOut = OCONV({DATETIME_OUT},'DT2/^HS')
|
|
LoadOperator = {OPERATOR_IN}
|
|
UnLoadOperator = {OPERATOR_OUT}
|
|
|
|
Response<@RecCount, 1> = RDSNo
|
|
Response<@RecCount, 2> = DateIn
|
|
Response<@RecCount, 3> = DateOut
|
|
Response<@RecCount, 4> = LoadOperator
|
|
Response<@RecCount, 5> = UnLoadOperator
|
|
end
|
|
Repeat
|
|
end else
|
|
ErrMsg = 'Error in service ':Service:'. Error code: ':errCode:'.'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to Open "DICT.RDS" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end else
|
|
ErrorMsg = 'Unable to Open "RDS" table!'
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service IncrementCycleCount(ToolID)
|
|
|
|
If ToolID NE '' then
|
|
// A reactor number may be passed in. Convert it to the corresponding tool ID if necessary.
|
|
If Num(ToolID) then ToolID = 'R':ToolID
|
|
ToolRec = Database_Services('ReadDataRow', 'TOOL', ToolID)
|
|
If Error_Services('NoError') then
|
|
CycleCnt = ToolRec<TOOL_CYCLE_CNT$>
|
|
CycleCnt += 1
|
|
ToolRec<TOOL_CYCLE_CNT$> = CycleCnt
|
|
Database_Services('WriteDataRow', 'TOOL', ToolID, ToolRec, True$, False$, True$)
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service CreateReactModeChange(UserID, ReactNo, Mode, ModeSubCat, ModeText, ForceModeChange)
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\ReactorModeChg'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Mode Change Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'Notes'
|
|
objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, '', False$, False$, True$)
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
ErrorMsg = ''
|
|
IF ForceModeChange NE True$ then ForceModeChange = False$
|
|
If ( (UserID NE '') and (ReactNo NE '') and (Mode NE '') and (ModeSubCat NE '')) then
|
|
CurTime = Time()
|
|
CurDate = Date()
|
|
NGPrevModeKey = Xlate('REACTOR_CHILD_KEY_IDS_NG', ReactNo, REACTOR_CHILD_KEY_IDS_REACT_MODE_KEY_IDS$, 'X')<1, 1>
|
|
PrevModeRec = Reactor_Services('GetReactCurrModeRec', ReactNo)
|
|
SelectedModeRec = Database_Services('ReadDataRow', 'REACTOR_MODES', Mode)
|
|
SelE10State = SelectedModeRec<REACTOR_MODES_E10_STATE$>
|
|
|
|
CommentException = False$
|
|
|
|
Begin Case
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_MAINTENANCE_UNSCHEDULED' AND Mode EQ 'MAINTENANCE_UNSCHEDULED'
|
|
CommentException = True$
|
|
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_MAINTENANCE_SCHEDULED' AND Mode EQ 'MAINTENANCE_SCHEDULED'
|
|
CommentException = True$
|
|
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_ENGINEER_UNSCHEDULED' AND Mode EQ 'ENGINEERING_INVESTIGATION'
|
|
CommentException = True$
|
|
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_ENGINEER_SCHEDULED' AND Mode EQ 'ENGINEERING_DEVELOPMENT'
|
|
CommentException = True$
|
|
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_ENGTECH_UNSCHEDULED' AND (Mode EQ 'TROUBLESHOOT_ENGTECH' OR Mode EQ 'ENGINEERING_INVESTIGATION')
|
|
CommentException = True$
|
|
|
|
Case PrevModeRec<REACT_MODE_NG_MODE$> EQ 'WAITING_FOR_ENGTECH_SCHEDULED' AND Mode EQ 'ENGINEERING_DEVELOPMENT'
|
|
CommentException = True$
|
|
|
|
End Case
|
|
If ((ModeText NE '') and (Len(ModeText) GE 4)) OR CommentException then
|
|
|
|
NewModeCategory = SelectedModeRec<REACTOR_MODES_MODE_CATEGORY$>
|
|
OldRlRecordKey = PrevModeRec<REACT_MODE_NG_START_RL_ID$>
|
|
If Reactor_Log_Services('IsMaint', OldRlRecordKey) AND ForceModeChange EQ False$ then
|
|
If (NOT(Reactor_Log_Services('IsSigned', OldRlRecordKey))) then
|
|
ErrorMsg = 'The current mode cannot be changed until the technician has signed off on the Reactor Log.'
|
|
end
|
|
end
|
|
|
|
ModeSubCatID = ''
|
|
Locate ModeSubCat in SelectedModeRec<REACTOR_MODES_SERVICE_CATEGORIES$> using @VM setting SvcPos then
|
|
NewModeSvcList = SelectedModeRec<REACTOR_MODES_SERVICE_CATEGORY_ID$>
|
|
ModeSubCatID = NewModeSvcList<1,SvcPos>
|
|
end else
|
|
ErrorMsg = 'Failed to locate ModeSubCat.'
|
|
end
|
|
|
|
CurrentMode = PrevModeRec<REACT_MODE_NG_MODE$>
|
|
ActiveProveInPreventsModeChange = Reactor_Services('ActiveProveInPreventsModeChange', ReactNo, Mode, CurrentMode)
|
|
|
|
If Error_Services('HasError') then
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
end else
|
|
If ActiveProveInPreventsModeChange EQ True$ then
|
|
ErrorMsg = 'A reactor prove in is required before changing the mode. Active prove in types: '
|
|
|
|
TypeList = ''
|
|
ProveInTypes = Reactor_Services('GetActiveProveInTypes', ReactNo)
|
|
for each ProveInType in ProveInTypes using @VM setting Idx
|
|
If Idx GT 1 then
|
|
TypeList := ', '
|
|
end
|
|
TypeList := ProveInType
|
|
Next ProveInType
|
|
|
|
ErrorMsg := TypeList
|
|
end
|
|
end
|
|
|
|
IdleStartupRequired = Reactor_Services('GetIdleStartupRequired', ReactNo)
|
|
If ErrorMsg EQ '' and IdleStartupRequired and Mode[1, 2] EQ 'UP' then
|
|
ProveInTypes = Reactor_Services('GetActiveProveInTypes', ReactNo)
|
|
IdleStartupActive = False$
|
|
For each ProveInType in ProveInTypes using @VM setting Idx
|
|
If ProveInType EQ 'IDLE' then
|
|
IdleStartupActive = True$
|
|
end
|
|
Next ProveInType
|
|
|
|
If IdleStartupActive EQ True$ then
|
|
ErrorMsg = "You must complete the IDLE_STARTUP prove in checklist before putting the reactor UP."
|
|
end else
|
|
ErrorMsg = "An IDLE_STARTUP prove in checklist is required before putting the reactor UP. Change the mode to IDLE_STARTUP, then complete the checklist."
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
ActiveHgCVChecklists = Nica_Orders_Services('GetActiveOrders', 'REACTOR', ReactNo, 'IQS_HGCV_ALARM')
|
|
HgCVChecklistActive = (ActiveHgCVChecklists NE '')
|
|
If ( HgCVChecklistActive and (SelE10State _EQC 'Productive') ) then
|
|
ErrorMsg = "An HgCV OCAP Checklist is active for this reactor and must be completed or overridden in order to change to a productive state."
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
IntrMaintFeatureFlag = Xlate('FEATURE_FLAGS', 'NICA_INTRUSIVE_MAINTENANCE', FEATURE_FLAGS.ENABLED$, 'X')
|
|
If IntrMaintFeatureFlag EQ True$ then
|
|
ActiveIntrusiveMaintChecklists = Nica_Orders_Services('GetActiveOrders', 'REACTOR', ReactNo, 'INTRUSIVE_MAINT')
|
|
IntrusiveMaintChecklistActive = (ActiveIntrusiveMaintChecklists NE '')
|
|
If ( IntrusiveMaintChecklistActive and (SelE10State _EQC 'Productive') ) then
|
|
ErrorMsg = "An Intrusive Maintenance Checklist is active for this reactor and must be completed or overridden in order to change to a productive state."
|
|
end
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
If Len(Mode) GT 10 and Mode[1, 10] EQ 'CHANGEOVER' then
|
|
Nica_Orders_Services('CreateNewOrder', 'REACTOR', ReactNo, 'CHANGEOVER')
|
|
end
|
|
|
|
If Mode EQ 'INITIATE_IDLE' then
|
|
Nica_Orders_Services('CreateNewOrder', 'REACTOR', ReactNo, 'INITIATE_IDLE')
|
|
end
|
|
|
|
If Mode EQ 'IDLE_STARTUP' then
|
|
Nica_Orders_Services('CreateNewOrder', 'REACTOR', ReactNo, 'IDLE')
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
//Log the current Mode Change
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Reactor No: ' : ReactNo : ' - Requested Mode Change: ' : Mode
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
|
|
OldReactUtilID = PrevModeRec<REACT_MODE_NG_START_RU_ID$>
|
|
|
|
if OldReactUtilID NE '' then
|
|
OldReactUtilRec = Database_Services('ReadDataRow', 'REACT_UTIL', OldReactUtilID)
|
|
OldReactUtilRec<react_util_end_date$> = CurDate
|
|
OldReactUtilRec<react_util_end_time$> = CurTime
|
|
OldReactUtilRec<react_util_mode_finish_user$> = UserId
|
|
Database_Services('WriteDataRow', 'REACT_UTIL', OldReactUtilID, OldReactUtilRec)
|
|
end
|
|
|
|
If Error_Services('NoError') then
|
|
**********************************************************************************
|
|
* WRITE OUT NEW MODE INFORMATION
|
|
|
|
//Create new React_Util record
|
|
NewRUKey = NextKey('REACT_UTIL')
|
|
|
|
If Error_Services('NoError') then
|
|
|
|
NewRLKey = NextKey('REACTOR_LOG')
|
|
|
|
If Error_Services('NoError') then
|
|
|
|
RUtilRec = ''
|
|
RUtilRec<react_util_reactor$> = ReactNo
|
|
RUtilRec<REACT_UTIL_NOTES$> = ModeText
|
|
RMode = ''
|
|
RUtilRec<react_util_mode$> = Mode
|
|
RUtilRec<react_util_start_date$> = CurDate
|
|
RUtilRec<react_util_start_time$> = CurTime
|
|
RUtilRec<react_util_mode_start_user$> = UserID
|
|
RUtilRec<react_util_reactor_log_id$> = NewRLKey
|
|
// Get current work order from the CONFIG table
|
|
DailySchedName = 'WO_DAILY_SCHED':ReactNo
|
|
DSR = XLATE('CONFIG', DailySchedName, '', 'X')
|
|
WOCust = DSR<WOCust$>
|
|
WorkOrder = Field(WOCust, ' ', 1)
|
|
RUtilRec<react_util_wo$> = WorkOrder
|
|
RUtilRec<react_util_cust_no$> = xlate( 'WO_LOG', WorkOrder, wo_log_cust_no$, 'X' ) ;
|
|
********************************************************************************************************
|
|
|
|
//Create a new Reactor_Log Entry
|
|
EntryId = UserID
|
|
|
|
RLRec = ''
|
|
RLRec<reactor_log_start_date$> = CurDate
|
|
RLRec<reactor_log_start_time$> = CurTime
|
|
RLRec<reactor_log_reactor$> = ReactNo
|
|
if NewModeCategory EQ 'MAINTENANCE' then
|
|
RLRec<reactor_log_category$> = 'M' ;* for maintenance
|
|
end
|
|
RLRec<reactor_log_entry_id$> = UserID
|
|
RLRec<reactor_log_entry_date$> = CurDate
|
|
RLRec<reactor_log_react_util_id$> = NewRUKey
|
|
RLRec<reactor_log_react_prob_cat_id$> = ModeSubCatID
|
|
|
|
Database_Services('WriteDataRow', 'REACTOR_LOG', NewRLKey, RLRec)
|
|
If Error_Services('NoError') then
|
|
Database_Services('WriteDataRow', 'REACT_UTIL', NewRUKey, RUtilRec)
|
|
If Error_Services('NoError') then
|
|
Rec = ''
|
|
Rec<Mode$> = Mode
|
|
Rec<Username$> = oconv( UserID, '[XLATE_CONV,LSL_USERS*FIRST_LAST]' )
|
|
Rec<Date$> = oconv( CurDate, 'D4/' )
|
|
Rec<Time$> = oconv( CurTime, 'MTH' )
|
|
Rec<ReactUtilID$> = NewRUKey
|
|
Rec<ReactorLogID$> = NewRLKey
|
|
Rec<Service$> = ModeSubCat
|
|
Rec<Note$> = ModeText
|
|
CurrDTM = Rec<Date$>:" ":Rec<Time$>
|
|
|
|
NGPrevModeDTM = Field(NGPrevModeKey, '*', 2)
|
|
PrevModeKey = NGPrevModeKey
|
|
OldMode = OCONV(XLATE('REACTOR',ReactNo,'CURR_MODE','X'),'[REACT_MODE_CONV]')
|
|
OpenDTM = FIELD(PrevModeKey,'*',2)
|
|
OpenDTM = OCONV(OpenDTM,'DT4/^S')
|
|
Mode = Rec<Mode$>
|
|
RecName = 'REACT_MODE':ReactNo
|
|
|
|
* * * * * Changes by JCH on 11/5/2007 * * * * *
|
|
ProdModes = 'Production':@VM
|
|
ProdModes := 'Production (incr sampling)':@VM
|
|
ProdModes := 'UP_WITH_RESTRICTIONS':@VM
|
|
ProdModes := 'UP':@VM
|
|
ProdModes := 'UP_WITH_INCREASED_SAMPLING':@VM
|
|
ProdModes := 'UP_WITH_INCREASED_SAMPLING_SAMPLING':@VM
|
|
ProdModes := 'UP_WITH_INCREASED_SAMPLING_METROLOGY':@VM
|
|
ProdModes := 'UP_NOT_RUNNING':@VM
|
|
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Reactor No: ' : ReactNo : ' - Current Mode: ' : OldMode : ' - New Mode: ' : Mode
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
LOCATE OldMode IN ProdModes USING @VM SETTING DUMMY THEN
|
|
|
|
LOCATE Mode IN ProdModes USING @VM SETTING DUMMY ELSE
|
|
|
|
OutOfProdDTM = Rec<Date$>:' ':Rec<Time$>
|
|
|
|
obj_React_Status('SetOutOfProdDTM',ReactNo:@RM:OutOfProdDTM)
|
|
|
|
IF Get_Status(errCode) THEN ErrorMsg = errCode
|
|
|
|
END ;* End of check on New Mode
|
|
END ;* End of check on Current Mode
|
|
|
|
* * * End of changes * * * * *
|
|
//Write new mode info to config table.
|
|
OrigConfigRec = Database_Services('ReadDataRow', 'CONFIG', RecName)
|
|
Database_Services('WriteDataRow', 'CONFIG', RecName, Rec)
|
|
|
|
If Error_Services('NoError') then
|
|
IF OldMode NE '' THEN
|
|
crParms = ReactNo
|
|
crParms := @RM:OpenDTM
|
|
crParms := @RM:CurrDTM
|
|
crParms := @RM:UserID
|
|
crParms := @RM:Rec<Note$>
|
|
crParms := @RM:Rec<ReactUtilID$>
|
|
crParms := @RM:Rec<ReactorLogID$>
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Reactor No: ' : ReactNo : ' - obj_React_Mode("Close") - Key ID: ' : ReactNo : '*' : Iconv(OpenDTM, 'DT')
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
obj_React_Mode('Close',crParms) ;* Close the currently active mode
|
|
END
|
|
If Not(Get_Status(errCode)) then
|
|
|
|
crParms = ReactNo
|
|
crParms := @RM:CurrDTM
|
|
crParms := @RM:UserID
|
|
crParms := @RM:Mode
|
|
crParms := @RM:Rec<Note$>
|
|
crParms := @RM:Rec<ReactUtilID$>
|
|
crParms := @RM:Rec<ReactorLogID$>
|
|
crParms := @RM:ModeSubCat
|
|
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Reactor No: ' : ReactNo : ' - obj_React_Mode("Create") - Key ID: ' : ReactNo : '*' : Iconv(CurrDTM, 'DT')
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
|
|
obj_React_Mode('Create',crParms) ;* Create new active mode record
|
|
|
|
IF Get_Status(errCode) THEN
|
|
// Failed to create new react mode
|
|
ErrorMsg = errCode
|
|
GoSub RollbackReactUtil
|
|
// Delete new REACTOR_LOG record
|
|
Database_Services('DeleteDataRow', 'REACTOR_LOG', NewRLKey)
|
|
// Delete new REACT_UTIL record
|
|
Database_Services('DeleteDataRow', 'REACT_UTIL', NewRUKey)
|
|
// Rollback CONFIG record
|
|
Database_Services('WriteDataRow', 'CONFIG', RecName, OrigConfigRec)
|
|
// Reopen previous react mode
|
|
Database_Services('WriteDataRow', 'REACT_MODE_NG', NGPrevModeKey, PrevModeRec)
|
|
end else
|
|
// Check to see if notifications are active for this mode
|
|
If SelectedModeRec<REACTOR_MODES_NOTIFICATION_ACTIVE$> then
|
|
//If notifications are active get the classes from the REACTOR_MODE record
|
|
SendToClasses = SelectedModeRec<REACTOR_MODES_NOTIFY_CLASS$>
|
|
For each class in SendToClasses using @VM
|
|
//Send to all the classes
|
|
notesParms = ''
|
|
IncludeNextShift = False$
|
|
//If we are close to shift change we want to add in the next shift.
|
|
CurrTime = Time()
|
|
if SRP_Time('Hour', CurrTime) EQ 17 OR SRP_Time('Hour', CurrTime) EQ 5 then
|
|
IncludeNextShift = True$
|
|
end
|
|
Recipients = LSL_USERS_SERVICES('GetOnShiftUsersByClass', class, IncludeNextShift); *Get all the on shift recipients
|
|
SentFrom = 'OI_ADMIN'
|
|
Subject = 'Reactor Mode Notification - ': ReactNo : ' ' : Mode
|
|
Message = 'Reactor: ' :ReactNo: ' has been placed into ' : Mode :'.'
|
|
Message := CRLF$ : 'Sub-Category: ' : ModeSubCat
|
|
Message := CRLF$ : 'User: ' : UserID
|
|
Message := CRLF$ : 'Notes: '
|
|
Message := CRLF$ : ModeText
|
|
AttachWindow = ''
|
|
AttachKey = ''
|
|
SendToGroup = ''
|
|
notesParms = Recipients:@RM:SentFrom:@RM:Subject:@RM:Message:@RM:AttachWindow:@RM:AttachKey:@RM:SendToGroup
|
|
Obj_Notes('Create', notesParms)
|
|
Next class
|
|
end
|
|
|
|
// If new mode sub category is an ABORT/ALARM or particular Facilities Failure, then apply abort metrology to the oldest loaded RDS
|
|
|
|
ReactType = Xlate('REACTOR', ReactNo, 'REACT_TYPE', 'X')
|
|
If ReactType NE 'EPP' then
|
|
Begin Case
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - TC Failure'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Contactor Not Sensed On'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Temp Up Failure'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'Gas Delivery Issue'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'Toxic Gas Alarm'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Facilities Level Failure'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Exhaust System Failure (Scrubber Toxic)'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Gas Flow - TCS'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Gas Flow - Dopant'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Gas Flow - Hydrogen'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Susceptor Faults'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - 24V. Interlock Abort'
|
|
ApplyAbortMet = True$
|
|
Case ModeSubCat _EQC 'ABORT/ALARM - Wafer Handling'
|
|
ApplyAbortMet = True$
|
|
Case Otherwise$
|
|
ApplyAbortMet = False$
|
|
End Case
|
|
|
|
If ApplyAbortMet then
|
|
|
|
LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\ReactorAborts'
|
|
LogDate = Oconv(Date(), 'D4/')
|
|
LogTime = Oconv(Time(), 'MTS')
|
|
LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Reactor Abort Log.csv'
|
|
Headers = 'Logging DTM' : @FM : 'ReactorNo' : @FM : 'Notes'
|
|
objAbortLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, '', False$, False$, True$)
|
|
LoggingDTM = LogDate : ' ' : LogTime ; // Logging DTM
|
|
|
|
LogMsg = 'Intermediate or Major ABORT/ALARM mode sub category, ':ModeSubCat:'. '
|
|
LogMsg := 'Attempting to apply abort metrology to loaded RDS.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
// Get the loaded RDS key(s) and apply abort metrology. If two are loaded, select the one loaded first.
|
|
LoadedRdsKeys = Xlate('REACT_STATUS', ReactNo, 'LOAD_RDS', 'X')
|
|
If LoadedRdsKeys NE '' then
|
|
|
|
AbortRds = ''
|
|
|
|
Begin Case
|
|
Case DCount(LoadedRdsKeys, @VM) EQ 2
|
|
// Select the oldest one
|
|
LoadDtms = Xlate('RDS', LoadedRdsKeys, 'DATETIME_IN', 'X')
|
|
If LoadDtms<0, 2> GT LoadDtms<0, 1> then
|
|
AbortRds = LoadedRdsKeys<0, 1>
|
|
end else
|
|
AbortRds = LoadedRdsKeys<0, 2>
|
|
end
|
|
|
|
Swap @VM with ' ' in LoadedRdsKeys
|
|
LogMsg = 'Two loaded RDS keys, ':LoadedRdsKeys:', found in REACT_STATUS record.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
LogMsg = 'Selecting RDS ':AbortRDS:' as it was loaded earlier.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
Case DCount(LoadedRdsKeys, @VM) EQ 1
|
|
// Only one loaded, so use that
|
|
AbortRds = LoadedRdsKeys
|
|
LogMsg = 'One loaded RDS key, ':AbortRds:', found in REACT_STATUS record.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
Case Otherwise$
|
|
// Unexpected condition - log error
|
|
Swap @VM with ' ' in LoadedRdsKeys
|
|
LogMsg = 'Error selecting RDS to apply abort metrology to. Loaded RDS keys, ':LoadedRdsKeys:', found in REACT_STATUS record.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
End Case
|
|
|
|
If AbortRds NE '' then
|
|
LogMsg = 'Attempting to apply abort metrology to RDS ':AbortRds:'.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
Rds_Services('ApplyAbortMetrology', AbortRds)
|
|
If Error_Services('NoError') then
|
|
|
|
LogMsg = 'Successfully applied abort metrology to RDS ':AbortRds:'.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
end else
|
|
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
|
|
LogMsg = 'Error occurred while applying abort metrology to RDS ':AbortRds:'. Error message: ':ErrorMsg
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
|
|
end
|
|
end
|
|
|
|
end else
|
|
// No loaded RDS runs detected
|
|
LogMsg = 'No loaded RDS keys found in REACT_STATUS record.'
|
|
LogData = ''
|
|
LogData<1> = LoggingDtm
|
|
LogData<2> = ReactNo
|
|
LogData<3> = LogMsg
|
|
Logging_Services('AppendLog', objAbortLog, LogData, @RM, @FM)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end else
|
|
// Failed to close previous react mode
|
|
ErrorMsg = errCode
|
|
GoSub RollbackReactUtil
|
|
// Delete new REACTOR_LOG record
|
|
Database_Services('DeleteDataRow', 'REACTOR_LOG', NewRLKey)
|
|
// Delete new REACT_UTIL record
|
|
Database_Services('DeleteDataRow', 'REACT_UTIL', NewRUKey)
|
|
// Rollback CONFIG record
|
|
Database_Services('WriteDataRow', 'CONFIG', RecName, OrigConfigRec)
|
|
end
|
|
END ELSE
|
|
ErrorMsg = 'Reactor No: ' : ReactNo : 'Unable to write ':RecName:' on CONFIG table...' : ReactNo : '*' : Iconv(CurrDTM, 'DT')
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = ErrorMsg
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
GoSub RollbackReactUtil
|
|
// Delete new REACTOR_LOG record
|
|
Database_Services('DeleteDataRow', 'REACTOR_LOG', NewRLKey)
|
|
// Delete new REACT_UTIL record
|
|
Database_Services('DeleteDataRow', 'REACT_UTIL', NewRUKey)
|
|
end
|
|
end else
|
|
// Failed to write REACT_UTIL record
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
GoSub RollbackReactUtil
|
|
// Delete new REACTOR_LOG record
|
|
Database_Services('DeleteDataRow', 'REACTOR_LOG', NewRLKey)
|
|
end
|
|
end else
|
|
// Failed to write REACTOR_LOG record
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
GoSub RollbackReactUtil
|
|
end
|
|
end else
|
|
// Failed to get new REACTOR_LOG key
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
GoSub RollbackReactUtil
|
|
end
|
|
end else
|
|
// Failed to get new REACT_UTIL key
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
GoSub RollbackReactUtil
|
|
end
|
|
end else
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
end
|
|
end
|
|
end else
|
|
Begin Case
|
|
Case ModeText EQ ''
|
|
ErrorMsg = 'You must enter a comment.'
|
|
|
|
Case Len(ModeText) LT 5
|
|
ErrorMsg = 'Comments must be more than 4 characters...'
|
|
End Case
|
|
end
|
|
|
|
end else
|
|
|
|
Begin Case
|
|
|
|
Case UserID EQ ''
|
|
ErrorMsg = 'Null UserID passed into service.'
|
|
|
|
Case ReactNo EQ ''
|
|
ErrorMsg = 'You must choose a Reactor.'
|
|
|
|
Case Mode EQ ''
|
|
ErrorMsg = 'You must choose a VALID Reactor Mode.'
|
|
|
|
Case ModeSubCat EQ ''
|
|
ErrorMsg = 'You must choose a VALID Reactor Problem Category.'
|
|
|
|
End Case
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = True$
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. ':ErrorMsg)
|
|
Response = False$
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service FormatReactStatusSingle(ReactNo)
|
|
|
|
Response = ''
|
|
CurrModeRec = Reactor_Services('GetReactCurrModeRec', ReactNo)
|
|
CurrLoadings = Reactor_Services('GetReactorCurrLoad', ReactNo)
|
|
|
|
ReactStatusArray = CurrModeRec
|
|
ReactStatusArray<12> = CurrLoadings; *Currently loaded cassettes
|
|
|
|
Response = ReactStatusArray
|
|
|
|
end service
|
|
|
|
|
|
Service GetSingleReactStatusJson(reactNo)
|
|
|
|
response = ''
|
|
// Create the root object JSON
|
|
If SRP_Json(objReactor, "New") then
|
|
// Create the array of reactors
|
|
If SRP_Json(objReactorArray, "New", "Array") then
|
|
ReactStatusArray = Reactor_Services('FormatReactStatusSingle', reactNo)
|
|
CurrE10State = Xlate('REACTOR_MODES', ReactStatusArray<REACT_MODE_NG_MODE$>, REACTOR_MODES_E10_STATE$, 'X')
|
|
ModeIconName = Xlate('REACTOR_MODES', ReactStatusArray<REACT_MODE_NG_MODE$>, REACTOR_MODES_ICON$, 'X')
|
|
RunningStatus = false$
|
|
CurrLoad = Reactor_Services('GetReactorCurrLoad', ReactNo)
|
|
CurrSubCat = ReactStatusArray<REACT_MODE_NG_SERVICE_DESC$>
|
|
if CurrLoad NE '' then
|
|
RunningStatus = true$
|
|
end
|
|
objSingleReactor = ''
|
|
If SRP_Json(objSingleReactor, "New") then
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ReactorNumber', reactNo, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ReactorMode', ReactStatusArray<REACT_MODE_NG_MODE$>, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'E10State', CurrE10State, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ModeIconName', ModeIconName, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'IsRunning', RunningStatus, 'BOOLEAN')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ModeSubCat', CurrSubCat, 'STRING')
|
|
SRP_Json(objReactorArray, "Add", objSingleReactor)
|
|
SRP_Json(objSingleReactor, "Release")
|
|
end
|
|
// Now add the array as a member of the root object
|
|
SRP_Json(objReactor, "Set", "reactors", objReactorArray)
|
|
|
|
// All done with the array object
|
|
SRP_Json(objReactorArray, "Release")
|
|
end
|
|
// Now get the actual JSON
|
|
resultingJSON = SRP_Json(objReactor, "Stringify", "STYLED")
|
|
|
|
// All done with the root object
|
|
SRP_Json(objReactor, "Release")
|
|
end
|
|
|
|
response = resultingJSON
|
|
|
|
end service
|
|
|
|
|
|
Service GetAllReactStatusJson()
|
|
|
|
Response = ''
|
|
|
|
AllReactNos = Reactor_Services('GetReactorNumbers')
|
|
|
|
//Create the root objec JSON
|
|
If SRP_Json(objReactor, "New") then
|
|
//Create the array of reactors
|
|
If SRP_Json(objReactorArray, "New", "Array") then
|
|
//Loop through all reactor nums and add to the array
|
|
for each reactNo in AllReactNos using @FM
|
|
if reactNo NE 'Cln' OR reactNo NE '140' then
|
|
ReactStatusArray = Reactor_Services('FormatReactStatusSingle', reactNo)
|
|
CurrE10State = Xlate('REACTOR_MODES', ReactStatusArray<REACT_MODE_NG_MODE$>, REACTOR_MODES_E10_STATE$, 'X')
|
|
ModeIconName = Xlate('REACTOR_MODES', ReactStatusArray<REACT_MODE_NG_MODE$>, REACTOR_MODES_ICON$, 'X')
|
|
RunningStatus = false$
|
|
CurrLoad = Reactor_Services('GetReactorCurrLoad', ReactNo)
|
|
if CurrLoad NE '' then
|
|
RunningStatus = true$
|
|
end
|
|
If SRP_Json(objSingleReactor, "New") then
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ReactorNumber', reactNo, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ReactorMode', ReactStatusArray<REACT_MODE_NG_MODE$>, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'E10State', CurrE10State, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'ModeIconName', ModeIconName, 'STRING')
|
|
SRP_JSON(objSingleReactor, 'SETVALUE', 'IsRunning', RunningStatus, 'BOOLEAN')
|
|
SRP_Json(objReactorArray, "Add", objSingleReactor)
|
|
SRP_Json(objSingleReactor, "Release")
|
|
end
|
|
end
|
|
|
|
|
|
Next reactNo
|
|
// Now add the array as a member of the root object
|
|
SRP_Json(objReactor, "Set", "reactors", objReactorArray)
|
|
|
|
// All done with the array object
|
|
SRP_Json(objReactorArray, "Release")
|
|
end
|
|
// Now get the actual JSON
|
|
resultingJSON = SRP_Json(objReactor, "Stringify", "STYLED")
|
|
|
|
// All done with the root object
|
|
SRP_Json(objReactor, "Release")
|
|
end
|
|
|
|
response = resultingJSON
|
|
|
|
end service
|
|
|
|
|
|
Service IsReactorLoaded(ReactNo)
|
|
|
|
ErrorMsg = ''
|
|
Response = False$
|
|
If ReactNo NE '' then
|
|
LoadedRDS = Xlate('REACT_STATUS', ReactNo, 'LOAD_RDS', 'X')
|
|
If LoadedRDS NE '' then Response = True$
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactNo passed in.'
|
|
end
|
|
If ErrorMsg NE '' then
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorTimeSinceUnload(ReactNo)
|
|
|
|
ErrorMsg = ''
|
|
Response = 0
|
|
|
|
If ReactNo NE '' then
|
|
LastUnloadTime = Xlate('REACT_STATUS', ReactNo, 'UNLOAD_DTM', 'X')
|
|
|
|
Response = SRP_DateTime("MinuteSpan", LastUnloadTime, Datetime(), 0)
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactNo passed in.'
|
|
end
|
|
|
|
If ErrorMsg NE '' then
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service ConvertRecordToJSON(ReactorNo, ItemURL, CurrUser, FullObject=BOOLEAN)
|
|
|
|
If FullObject EQ '' then FullObject = True$
|
|
ErrorMsg = ''
|
|
JSON = ''
|
|
If ReactorNo then
|
|
objJSON = ''
|
|
If SRP_JSON(objJSON, 'New', 'Object') then
|
|
// Add in reactor current mode, available modes, and available sub categories.
|
|
CurrModeKey = Reactor_Services('GetReactCurrModeId', ReactorNo)
|
|
CurrMode = Xlate('REACT_MODE_NG', CurrModeKey, REACT_MODE_NG_MODE$, 'X')
|
|
ServiceDesc = Xlate('REACT_MODE_NG', CurrModeKey, REACT_MODE_NG_SERVICE_DESC$, 'X')
|
|
If (CurrUser NE '') then AvailModes = Reactor_Modes_Services('AvailableModes', CurrMode, CurrUser)
|
|
CurrRLKey = Xlate('REACT_MODE_NG', CurrModeKey, REACT_MODE_NG_START_RL_ID$ , 'X')
|
|
ReactorType = Xlate('REACTOR', ReactorNo, 'REACT_TYPE', 'X')
|
|
ReactAssign = Xlate('REACTOR', ReactorNo, 'REACT_ASSIGNMENT', 'X')
|
|
React_Assign_Conv('OCONV', ReactAssign, '', ReactAssign)
|
|
// Create reactor object
|
|
If SRP_JSON(objReactor, 'New', 'Object') then
|
|
SRP_JSON(objReactor, 'SetValue', 'reactorNo', ReactorNo)
|
|
SRP_JSON(objReactor, 'SetValue', 'reactType', ReactorType)
|
|
SRP_JSON(objReactor, 'SetValue', 'reactAssignment', ReactAssign)
|
|
PickPlace = Xlate('REACTOR', ReactorNo, 'PICK_PLACE', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'pickPlace', PickPlace, 'Boolean')
|
|
LLDisabledKey = Xlate('REACTOR', ReactorNo, 'ACTIVE_LL_DISABLED', 'X')
|
|
LoadLockDisabled = Xlate('REACT_LL', LLDisabledKey, 'DISABLED', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'loadLockDown', LoadLockDisabled)
|
|
SRP_JSON(objReactor, 'SetValue', '0311Active', Xlate('REACTOR', ReactorNo, '0311_ACTIVE', 'X'), 'Boolean')
|
|
SRP_JSON(objReactor, 'SetValue', 'active0311Checklist', Xlate('REACTOR', ReactorNo, '0311_ACTIVE', 'X'), 'Boolean')
|
|
SRP_JSON(objReactor, 'SetValue', 'TubeBellJarCnt', Xlate('REACTOR', ReactorNo, REACTOR_TUBE_BELL_JAR_THK$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'TubeBellJarThk', Xlate('REACTOR', ReactorNo, REACTOR_TUBE_BELL_JAR_WFR_CNT$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'SusceptorCnt', Xlate('REACTOR', ReactorNo, REACTOR_SUSC_WFR_CNT$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'SusceptorThk', Xlate('REACTOR', ReactorNo, REACTOR_SUSC_THK$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'LowerQuartzCnt', Xlate('REACTOR', ReactorNo, REACTOR_LOWER_QUARTZ_WFR$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'LowerQuartzThk', Xlate('REACTOR', ReactorNo, REACTOR_LOWER_QUARTZ_THK$, 'X'))
|
|
SRP_JSON(objReactor, 'SetValue', 'ArmsCnt', Xlate('REACTOR', ReactorNo, REACTOR_ARMS_WFR_CNT$, 'X'))
|
|
|
|
// Add Current Run Status (Current Loaded Cassettes)
|
|
LoadedRDS = Xlate('REACT_STATUS', ReactorNo, 'LOAD_RDS', 'X')
|
|
If LoadedRDS NE '' then
|
|
objLoadedRDS = ''
|
|
If SRP_JSON(objLoadedRDS, 'New', 'Array') then
|
|
For each RDS in LoadedRDS using @VM setting vPos
|
|
SRP_JSON(objLoadedRDS, 'AddValue', RDS)
|
|
Next RDS
|
|
SRP_JSON(objReactor, 'Set', 'loadedRDS', objLoadedRDS)
|
|
SRP_JSON(objLoadedRDS, 'Release')
|
|
end
|
|
end else
|
|
SRP_JSON(objReactor, 'SetValue', 'loadedRDS', '')
|
|
end
|
|
|
|
// Add new reactor items here
|
|
InstItems = Xlate('REACTOR', ReactorNo, REACTOR_CURR_INST_ITEMS$, 'X')
|
|
If InstItems NE '' then
|
|
objInstItems = ''
|
|
If SRP_JSON(objInstItems, 'New', 'Array') then
|
|
For each Item in InstItems using @VM setting vPos
|
|
swap '*' with @VM in Item
|
|
SRP_JSON(objInstItems, 'AddValue', Item<1, 2>)
|
|
Next Item
|
|
SRP_JSON(objReactor, 'Set', 'installedReactItems', objInstItems)
|
|
SRP_JSON(objInstItems, 'Release')
|
|
end
|
|
end else
|
|
SRP_JSON(objReactor, 'SetValue', 'installedReactItems', '')
|
|
end
|
|
|
|
// Add Current Run Status (Is running)
|
|
ReactorRunning = (LoadedRDS NE '')
|
|
SRP_JSON(objReactor, 'SetValue', 'isRunning', ReactorRunning, 'Boolean')
|
|
|
|
// Add Out of prod time
|
|
OutofProdDTM = Xlate('REACT_STATUS', ReactorNo, 'OUT_OF_PROD_DTM', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'outOfProdDTM', OConv(OutofProdDTM, 'DT2/^H'))
|
|
|
|
If FullObject then
|
|
// Add Last Unload Time
|
|
LastUnloadDTM = Xlate('REACT_STATUS', ReactorNo, 'UNLOAD_RDS_DTM', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'unloadDTM', OConv(LastUnloadDTM, 'DT2/^H'))
|
|
|
|
// Add Last Load Time
|
|
LastLoadDTM = Xlate('REACT_STATUS', ReactorNo, 'LOAD_RDS_DTM', 'X')
|
|
LastLoadDTM = LastLoadDTM[-1, 'B':@VM]
|
|
SRP_JSON(objReactor, 'SetValue', 'loadDTM', OConv(LastLoadDTM, 'DT2/^H'))
|
|
|
|
// Add Last Reactor Readings
|
|
LastReadWfrsDTM = Xlate('REACTOR', ReactorNo, 'LAST_READ_WFRS_DTM', 'X')
|
|
LastReadWfrs = Xlate('REACT_READS', ReactorNo:'*':LastReadWfrsDTM, 'WAFER_CNT', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'lastReadWafersDTM', OConv(LastReadWfrsDTM, 'DT2/^H'))
|
|
SRP_JSON(objReactor, 'SetValue', 'lastReadWafers', LastReadWfrs)
|
|
end
|
|
|
|
// Add work order object
|
|
SchedConfigRec = Database_Services('ReadDataRow', 'CONFIG', 'WO_DAILY_SCHED':ReactorNo)
|
|
WorkOrderCust = SchedConfigRec<WOCust$>
|
|
CurrWorkOrder = Field(WorkOrderCust, ' ', 1)
|
|
SRP_JSON(objReactor, 'SetValue', 'workOrder', CurrWorkOrder)
|
|
WOHotStatus = Xlate('WO_LOG', CurrWorkOrder, 'HOT_FLAG', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'workOrderHotStatus', WOHotStatus)
|
|
WOCustomer = Field(WorkOrderCust, ' ', 2)
|
|
SRP_JSON(objReactor, 'SetValue', 'workOrderCustomer', WOCustomer)
|
|
If FullObject then
|
|
JSONWorkOrder = Work_Order_Services('ConvertRecordToJSON', CurrWorkOrder)
|
|
objWorkOrder = ''
|
|
If SRP_JSON(objWorkOrder, 'Parse', JSONWorkOrder) EQ '' then
|
|
objTemp = SRP_JSON(objWorkOrder, 'Get', 'workOrder')
|
|
SRP_JSON(objReactor, 'Set', 'workOrder', objTemp)
|
|
SRP_JSON(objTemp, 'Release')
|
|
SRP_JSON(objWorkOrder, 'Release')
|
|
end
|
|
end
|
|
|
|
// Reactor Mode object/properties
|
|
If FullObject then
|
|
// Add reactor mode object
|
|
JSONReactorMode = React_Mode_NG_Services('ConvertRecordToJSON', CurrModeKey, '', CurrUser)
|
|
objReactorMode = ''
|
|
If SRP_JSON(objReactorMode, 'Parse', JSONReactorMode) EQ '' then
|
|
objTemp = SRP_JSON(objReactorMode, 'Get', 'reactorMode')
|
|
SRP_JSON(objReactor, 'Set', 'reactorMode', objTemp)
|
|
SRP_JSON(objTemp, 'Release')
|
|
SRP_JSON(objReactorMode, 'Release')
|
|
end
|
|
end else
|
|
CurrMode = Xlate('REACT_MODE_NG', CurrModeKey, 'MODE', 'X')
|
|
SubCat = Xlate('REACT_MODE_NG', CurrModeKey, 'SERVICE_DESC', 'X')
|
|
E10State = Xlate('REACTOR_MODES', CurrMode, 'E10_STATE', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'currMode', CurrMode)
|
|
SRP_JSON(objReactor, 'SetValue', 'serviceDesc', SubCat)
|
|
SRP_JSON(objReactor, 'SetValue', 'e10State', E10State)
|
|
end
|
|
|
|
If Not(FullObject) then
|
|
// Add reactor log properties
|
|
CurrRlKey = Xlate('REACTOR', ReactorNo, 'CURR_MODE_RL_ID', 'X')
|
|
If CurrRLKey NE '' then
|
|
RlChecklistActive = Xlate('REACTOR_LOG', CurrRlKey, 'CHECKLIST_ACTIVE', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'reactorLogChecklistActive', RlChecklistActive, 'Boolean')
|
|
If RlChecklistActive then
|
|
RlChecklistTypes = Xlate('REACTOR_LOG', CurrRlKey, 'CHECKLIST_TYPE', 'X')
|
|
RlChecklistOrderIds = Xlate('REACTOR_LOG', CurrRlKey, 'CHECKLIST_ORDER_ID', 'X')
|
|
objRlChecklistArray = ''
|
|
If SRP_JSON(objRlChecklistArray, 'New', 'Array') then
|
|
objChecklist = ''
|
|
For each RlChecklistType in RlChecklistTypes using @VM setting vPos
|
|
If SRP_JSON(objChecklist, 'New', 'Object') then
|
|
SRP_JSON(objChecklist, 'SetValue', 'reactorLogChecklistType', RlChecklistType)
|
|
RlChecklistOrderId = RlChecklistOrderIds<0, vPos>
|
|
SRP_JSON(objChecklist, 'SetValue', 'reactorLogChecklistOrderId', RlChecklistOrderId)
|
|
SRP_JSON(objRlChecklistArray, 'Add', objChecklist)
|
|
SRP_JSON(objChecklist, 'Release')
|
|
end
|
|
Next RlChecklistType
|
|
SRP_JSON(objReactor, 'Set', 'reactorLogChecklists', objRlChecklistArray)
|
|
SRP_JSON(objRlChecklistArray, 'Release')
|
|
end
|
|
end
|
|
end
|
|
// Add prove in checklist properties
|
|
PiChecklistActive = Xlate('REACTOR', ReactorNo, 'PROVE_IN_ACTIVE', 'X')
|
|
SRP_JSON(objReactor, 'SetValue', 'proveInChecklistActive', PiChecklistActive, 'Boolean')
|
|
If PiChecklistActive then
|
|
PiTypes = Xlate('REACTOR', ReactorNo, 'PROVE_IN_TYPE', 'X')
|
|
PiChecklistOrderIds = Xlate('REACTOR', ReactorNo, 'PROVE_IN_ORDER_ID', 'X')
|
|
objPiChecklistArray = ''
|
|
If SRP_JSON(objPiChecklistArray, 'New', 'Array') then
|
|
objProveIn = ''
|
|
For each PiType in PiTypes using @VM setting vPos
|
|
If SRP_JSON(objProveIn, 'New', 'Object') then
|
|
SRP_JSON(objProveIn, 'SetValue', 'proveInType', PiType)
|
|
PiChecklistOrderId = PiCheckListOrderIds<0, vPos>
|
|
SRP_JSON(objProveIn, 'SetValue', 'proveInOrderId', PiChecklistOrderId)
|
|
SRP_JSON(objPiChecklistArray, 'Add', objProveIn)
|
|
SRP_JSON(objProveIn, 'Release')
|
|
end
|
|
Next PiType
|
|
SRP_JSON(objReactor, 'Set', 'proveInChecklists', objPiChecklistArray)
|
|
SRP_JSON(objPiChecklistArray)
|
|
end
|
|
end
|
|
end
|
|
|
|
If itemURL NE '' then
|
|
// The itemURL was passed in so add HAL+JSON properties.
|
|
objLinks = ''
|
|
// Create the _links property and then all link objects needed for this resource.
|
|
If SRP_JSON(objLinks, 'New', 'Object') then
|
|
// Create a self link.
|
|
objLink = ''
|
|
If SRP_JSON(objLink, 'New', 'Object') then
|
|
SRP_JSON(objLink, 'SetValue', 'href', ItemURL, 'String')
|
|
SRP_JSON(objLink, 'SetValue', 'title', 'Self', 'String')
|
|
SRP_JSON(objLinks, 'Set', 'self', objLink)
|
|
SRP_JSON(objLink, 'Release')
|
|
end
|
|
SRP_JSON(objReactor, 'Set', '_links', objLinks)
|
|
SRP_JSON(objLinks, 'Release')
|
|
end
|
|
// Create the _class property for this resource.
|
|
SRP_JSON(objReactor, 'SetValue', '_class', 'resource')
|
|
end
|
|
SRP_JSON(objJSON, 'Set', 'reactor', objReactor)
|
|
SRP_JSON(objReactor, 'Release')
|
|
end
|
|
JSON = SRP_JSON(objJSON, 'Stringify', 'Styled')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error creating JSON object.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactNo passed in.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = JSON
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service ConvertJSONToRecord(KeyID, JSON)
|
|
|
|
Record = ''
|
|
If JSON NE '' then
|
|
If SRP_JSON(objJSON, 'Parse', JSON) EQ '' then
|
|
objReactor = SRP_JSON(objJSON, 'Get', 'reactor')
|
|
Record = Database_Services('ReadDataRow', 'REACTOR', KeyID)
|
|
If Error_Services('NoError') then
|
|
// Add code to update additional columns as needed.
|
|
// If property is "" then clear the field.
|
|
// If property is null then do not update it.
|
|
NewVal = SRP_JSON(objReactor, 'GetValue', '0311Active')
|
|
If NewVal NE 'null' then
|
|
Record<REACTOR_0311_ACTIVE$> = NewVal
|
|
end
|
|
end
|
|
SRP_JSON(objReactor, 'Release')
|
|
SRP_JSON(objJSON, 'Release')
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Unable to parse JSON payload.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null JSON passed in.')
|
|
end
|
|
|
|
Response = Record
|
|
|
|
end service
|
|
|
|
|
|
Service CleanReactStatus()
|
|
|
|
hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
|
|
Lock hSysLists, ServiceKeyID then
|
|
ReactNos = Reactor_Services('GetReactorNumbers')
|
|
For each ReactNo in ReactNos using @FM
|
|
HaveLock = Database_Services('GetKeyIDLock', 'REACT_STATUS', ReactNo)
|
|
If HaveLock then
|
|
OrigReactStatRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactNo)
|
|
ReactStatRec = OrigReactStatRec
|
|
If Error_Services('NoError') then
|
|
For Col = 1 to 9
|
|
OrigList = OrigReactStatRec<Col>
|
|
If OrigList NE '' then
|
|
CleanList = ''
|
|
For each Val in OrigList using @VM
|
|
If Val NE 1 then CleanList<0, -1> = Val
|
|
Next Val
|
|
ReactStatRec<Col> = CleanList
|
|
end
|
|
Next Col
|
|
If OrigReactStatRec NE ReactStatRec then
|
|
Database_Services('WriteDataRow', 'REACT_STATUS', ReactNo, ReactStatRec, True$, False$, False$)
|
|
end else
|
|
Database_Services('ReleaseKeyIDLock', 'REACT_STATUS', ReactNo)
|
|
end
|
|
end
|
|
end
|
|
Next ReactNo
|
|
Unlock hSysLists, ServiceKeyID else Null
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactModeKeysByTimeSpan(ReactorNo, StartDtm, StopDtm)
|
|
|
|
Begin Case
|
|
Case ReactorNo Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. ReactorNo not supplied.')
|
|
Case StartDtm Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. StartDtm not supplied.')
|
|
Case StopDtm Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. StopDtm not supplied.')
|
|
End Case
|
|
If Error_Services('NoError') then
|
|
//Get all modes within the StartDtm and StopDtm
|
|
StartDt = FIELD(StartDtm, '.', 1)
|
|
StopDt = Field(StopDtm, '.', 1)
|
|
keys = ''
|
|
OPEN 'DICT.REACT_MODE_NG' TO @DICT then
|
|
SearchString = ''
|
|
SearchString := "START_DTM" :@VM: StartDtm : '~' : StopDtm: @FM
|
|
SearchString := "STOP_DTM" :@VM: ';' : StartDtm : '~' : StopDtm : @FM
|
|
SearchString := "REACT_NO" :@VM: ReactorNo : @FM
|
|
keylist = ""
|
|
option = ""
|
|
flag = ""
|
|
Btree.Extract(SearchString, 'REACT_MODE_NG', @DICT, keylist, option, flag)
|
|
for each key in keylist
|
|
keys<-1> = key
|
|
Next key
|
|
end
|
|
if keys<1> EQ '' then
|
|
//Get Current Mode because it started before report date and has yet to finish
|
|
//Is the report time for the current mode?
|
|
CurrReactorModeKey = Reactor_Services('GetReactCurrModeId', ReactorNo)
|
|
CurrReactorModeStartDtm = Field(CurrReactorModeKey, '*', 2)
|
|
IF StopDtm GT CurrReactorModeStartDtm then
|
|
keys<-1> = CurrReactorModeKey
|
|
end else
|
|
//
|
|
SearchString = ''
|
|
SearchString := "START_DTM" :@VM: '<=' : StartDtm: @FM
|
|
SearchString := "STOP_DTM" :@VM: '>=' : StopDtm : @FM
|
|
SearchString := "REACT_NO" :@VM: ReactorNo : @FM
|
|
SubKeyList = ""
|
|
option = ""
|
|
flag = ""
|
|
Btree.Extract(SearchString, 'REACT_MODE_NG', @DICT, SubKeyList, option, flag)
|
|
for each SubKey in SubKeyList
|
|
keys<-1> = SubKey
|
|
Next SubKey
|
|
end
|
|
|
|
|
|
//Is the report time outside of the current mode
|
|
end
|
|
Response = keys
|
|
end else
|
|
Response = Error_Services('GetMessage')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
|
|
Service GetReactorUptimeMetricsByTimeSpan(ReactorNo, StartDtm, StopDtm)
|
|
|
|
ToolData = ''
|
|
TotalProductiveMinutes = 0
|
|
TotalUnscheduledDownMinutes = 0
|
|
TotalScheduledDownMinutes = 0
|
|
TotalNonSchedMinutes = 0
|
|
TotalEngMinutes = 0
|
|
|
|
Begin Case
|
|
Case ReactorNo Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. ReactorNo not supplied.')
|
|
Case StartDtm Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. StartDtm not supplied.')
|
|
Case StopDtm Eq ''
|
|
Error_Services('Add', 'Error in ' : Service : ' service. StopDtm not supplied.')
|
|
End Case
|
|
//If StopDtm is in future then set it to current time.
|
|
If StopDtm GT Datetime() then
|
|
StopDtm = Datetime()
|
|
end
|
|
If Error_Services('NoError') then
|
|
|
|
//Get Keys for the supplied time span
|
|
ReactModeNGKeys = Reactor_Services('GetReactModeKeysByTimeSpan', ReactorNo, StartDtm, StopDtm)
|
|
If Error_Services('NoError') then
|
|
//Get total minutes of timespan.
|
|
TotalReportMinutes = SRP_Datetime('MinuteSpan', StartDtm, StopDtm)
|
|
//Loop Through each mode key returned
|
|
|
|
for each key in ReactModeNGKeys using @VM
|
|
ReactModeNGRec = Database_Services('ReadDataRow', 'REACT_MODE_NG', key)
|
|
ModeStartDtm = Field(key, '*', 2)
|
|
ModeStopDtm = ReactModeNGRec<REACT_MODE_NG_STOP_DTM$>
|
|
ReactModeName = ReactModeNGRec<REACT_MODE_NG_MODE$>
|
|
E10State = Xlate('REACTOR_MODES', ReactModeName, REACTOR_MODES_E10_STATE$, 'X')
|
|
MinutesInMode = 0
|
|
Begin Case
|
|
CASE E10State EQ 'Productive'
|
|
//Begin Production
|
|
if ModeStartDtm LT StartDtm then
|
|
//Mode Started Earlier than report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan
|
|
If ModeStopDtm NE '' then
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed
|
|
|
|
If ModeStartDtm LT StartDtm then
|
|
//if ModeStartDtm is before StartDtm and is not close used the total report timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end else
|
|
//Use the ModeStartDtm and the StopDtm
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end
|
|
end else
|
|
//Mode started after report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan OR isn't yet closed
|
|
If ModeStopDtm NE '' then
|
|
//Mode is closed. Started and finished within the report time so use the Mode's start and stop
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed. Started within the report time but has yet to stop.
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
TotalProductiveMinutes += MinutesInMode
|
|
Case E10State EQ 'Unscheduled Down'
|
|
//Begin Production
|
|
if ModeStartDtm LT StartDtm then
|
|
//Mode Started Earlier than report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan
|
|
If ModeStopDtm NE '' then
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed
|
|
|
|
If ModeStartDtm LT StartDtm then
|
|
//if ModeStartDtm is before StartDtm and is not close used the total report timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end else
|
|
//Use the ModeStartDtm and the StopDtm
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end
|
|
end else
|
|
//Mode started after report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan OR isn't yet closed
|
|
If ModeStopDtm NE '' then
|
|
//Mode is closed. Started and finished within the report time so use the Mode's start and stop
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed. Started within the report time but has yet to stop.
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
TotalUnscheduledDownMinutes += MinutesInMode
|
|
Case E10State EQ 'Scheduled Down'
|
|
//Begin Production
|
|
if ModeStartDtm LT StartDtm then
|
|
//Mode Started Earlier than report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan
|
|
If ModeStopDtm NE '' then
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed
|
|
|
|
If ModeStartDtm LT StartDtm then
|
|
//if ModeStartDtm is before StartDtm and is not close used the total report timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end else
|
|
//Use the ModeStartDtm and the StopDtm
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end
|
|
end else
|
|
//Mode started after report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan OR isn't yet closed
|
|
If ModeStopDtm NE '' then
|
|
//Mode is closed. Started and finished within the report time so use the Mode's start and stop
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed. Started within the report time but has yet to stop.
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
TotalScheduledDownMinutes += MinutesInMode
|
|
Case E10State EQ 'Non-Scheduled' OR E10State EQ 'Standby'
|
|
if ModeStartDtm LT StartDtm then
|
|
//Mode Started Earlier than report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan
|
|
If ModeStopDtm NE '' then
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed
|
|
|
|
If ModeStartDtm LT StartDtm then
|
|
//if ModeStartDtm is before StartDtm and is not close used the total report timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end else
|
|
//Use the ModeStartDtm and the StopDtm
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end
|
|
end else
|
|
//Mode started after report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan OR isn't yet closed
|
|
If ModeStopDtm NE '' then
|
|
//Mode is closed. Started and finished within the report time so use the Mode's start and stop
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed. Started within the report time but has yet to stop.
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
TotalNonSchedMinutes += MinutesInMode
|
|
Case E10State EQ 'Engineering'
|
|
if ModeStartDtm LT StartDtm then
|
|
//Mode Started Earlier than report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan
|
|
If ModeStopDtm NE '' then
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed
|
|
|
|
If ModeStartDtm LT StartDtm then
|
|
//if ModeStartDtm is before StartDtm and is not close used the total report timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end else
|
|
//Use the ModeStartDtm and the StopDtm
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', StartDTM, StopDtm)
|
|
end
|
|
end else
|
|
//Mode started after report time
|
|
If ModeStopDtm LT StopDtm then
|
|
//Mode finished within the timespan OR isn't yet closed
|
|
If ModeStopDtm NE '' then
|
|
//Mode is closed. Started and finished within the report time so use the Mode's start and stop
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, ModeStopDtm)
|
|
end else
|
|
//Mode is not closed. Started within the report time but has yet to stop.
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end else
|
|
//Mode finished after the timespan
|
|
MinutesInMode = SRP_Datetime('MinuteSpan', ModeStartDtm, StopDtm)
|
|
end
|
|
end
|
|
TotalEngMinutes += MinutesInMode
|
|
End Case
|
|
|
|
Next key
|
|
ProdPercentage = (TotalProductiveMinutes / TotalReportMinutes) * 100
|
|
UnschedDownPercentage = (TotalUnscheduledDownMinutes / TotalReportMinutes) * 100
|
|
SchedDownPercentage = (TotalScheduledDownMinutes / TotalReportMinutes) * 100
|
|
NonSchedPercentage = (TotalNonSchedMinutes / TotalReportMinutes) * 100
|
|
EngPercentage = (TotalEngMinutes / TotalReportMinutes) * 100
|
|
|
|
|
|
//Percentages
|
|
ToolData<1, PRODUCTIVE$> = ProdPercentage
|
|
ToolData<1, UNSCHED$> = UnschedDownPercentage
|
|
ToolData<1, SCHED$> = SchedDownPercentage
|
|
ToolData<1, NONSCHED$> = NonSchedPercentage
|
|
ToolData<1, ENG$> = EngPercentage
|
|
//Total Minutes
|
|
ToolData<2, PRODUCTIVE$> = TotalProductiveMinutes
|
|
ToolData<2, UNSCHED$> = TotalUnscheduledDownMinutes
|
|
ToolData<2, SCHED$> = TotalScheduledDownMinutes
|
|
ToolData<2, NONSCHED$> = TotalNonSchedMinutes
|
|
ToolData<2, ENG$> = TotalEngMinutes
|
|
Response = ToolData
|
|
end else
|
|
Response = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
Response = Error_Services('GetMessage')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorUptimeMetricsByTypeAndTimeSpan(startDtm, endDtm, reactType)
|
|
|
|
Begin Case
|
|
Case startDtm EQ ''
|
|
Error_Services('Add', 'Error getting reactor uptime metrics -> Report start date not supplied')
|
|
Case endDtm EQ ''
|
|
Error_Services('Add', 'Error getting reactor uptime metrics -> Report end date not supplied')
|
|
End Case
|
|
If reactType EQ '' then reactType = 'ALL'
|
|
If Error_Services('NoError') then
|
|
If endDtm GT Date() then
|
|
//This sets the current report end time to the current time.
|
|
endDtm = Datetime()
|
|
end
|
|
reportMinutes = SRP_Datetime('MinuteSpan', startDtm, endDtm)
|
|
if num(reportMinutes) then
|
|
Begin Case
|
|
Case reactType EQ 'ASM' or reactType EQ 'ASM+'
|
|
Reactors = Reactor_Services('GetReactorNumbers', 'ASM') : @FM : Reactor_Services('GetReactorNumbers', 'ASM+')
|
|
Case reactType EQ 'HTR'
|
|
Reactors = Reactor_Services('GetReactorNumbers', 'HTR')
|
|
Case reactType EQ 'EPP'
|
|
Reactors = Reactor_Services('GetReactorNumbers', 'EPP')
|
|
Case reactType EQ 'ALL'
|
|
Reactors = Reactor_Services('GetReactorNumbers', 'ASM') : @FM : Reactor_Services('GetReactorNumbers', 'ASM+') : @FM : Reactor_Services('GetReactorNumbers', 'HTR') : @FM : Reactor_Services('GetReactorNumbers', 'EPP')
|
|
End Case
|
|
AllReactorsScheduledMinutes = 0
|
|
AllReactorsUptimeMinutes = 0
|
|
AllReactorsProdMinutes = 0
|
|
AllReactorsUnschedDownMinutes = 0
|
|
AllReactorsSchedDownMinutes = 0
|
|
AllReactorsEngMinutes = 0
|
|
AllReactorsIdleMinutes = 0
|
|
AllReactorsSingleLL= 0
|
|
TotalMinutesUp = 0
|
|
ReactorsData = ''
|
|
ReactorsExcluded = ''
|
|
for each Reactor in Reactors using @FM
|
|
ReactorStateTimes = Reactor_Services('GetReactorUptimeMetricsByTimeSpan', Reactor, startDtm, endDtm)
|
|
PercentProd = ReactorStateTimes<1,PRODUCTIVE$>
|
|
MinuteProd = ReactorStateTimes<2,PRODUCTIVE$>
|
|
PercentUnSchedDown = ReactorStateTimes<1,UNSCHED$>
|
|
MinuteUnschedDown = ReactorStateTimes<2,UNSCHED$>
|
|
PercentSchedDown = ReactorStateTimes<1,SCHED$>
|
|
MinuteSchedDown = ReactorStateTimes<2,SCHED$>
|
|
PercentNonSched = ReactorStateTimes<1,NONSCHED$>
|
|
MinutesNonSched = ReactorStateTimes<2,NONSCHED$>
|
|
PercentEng = ReactorStateTimes<1, ENG$>
|
|
MinutesEng = ReactorStateTimes<2, ENG$>
|
|
if MinutesNonSched LT reportMinutes then
|
|
thisReactorExpectedAvailMinutes = reportMinutes - MinutesNonSched; * This is the amount of minutes the single reactor was scheduled to run work.
|
|
AllReactorsScheduledMinutes += thisReactorExpectedAvailMinutes; * Add it to the collective of reactors
|
|
thisReactorUptimeMinutes = MinuteProd + MinutesEng
|
|
AllReactorsUptimeMinutes = thisReactorUptimeMinutes + AllReactorsUptimeMinutes
|
|
AllReactorsProdMinutes += MinuteProd
|
|
AllReactorsUnschedDownMinutes += MinuteUnschedDown
|
|
AllReactorsSchedDownMinutes += MinuteSchedDown
|
|
AllReactorsEngMinutes += MinutesEng
|
|
AllReactorsIdleMinutes += MinutesNonSched
|
|
if reactType NE 'EPP' then
|
|
thisReactorDisabledLoadLock = Reactor_Services('GetReactorDownLL', Reactor) NE ''
|
|
AllReactorsSingleLL += thisReactorDisabledLoadLock
|
|
end else
|
|
thisReactorDisabledLoadLock = 0
|
|
end
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTORS$,-1> = Reactor
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_PROD_PERCENTAGE$,-1> = PercentProd
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_PROD_MINUTES$,-1> = MinuteProd
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_ENG_PERCENTAGE$, -1> = PercentEng
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_ENG_MINUTES$, -1> = MinutesEng
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_DOWN_UNSCHED_PERCENTAGE$, -1> = PercentUnSchedDown
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_DOWN_UNSCHED_MINUTES$, -1> = MinuteUnschedDown
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_DOWN_SCHED_PERCENTAGE$, -1> = PercentSchedDown
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_DOWN_SCHED_MINUTES$, -1> = MinuteSchedDown
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_IDLE_PERCENTAGE$, -1> = PercentNonSched
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_IDLE_MINUTES$, -1> = MinutesNonSched
|
|
ReactorsData<REACTOR_DAILY_UPTIME_INCL_REACTOR_SINGLE_LL$, -1> = thisReactorDisabledLoadLock
|
|
end else
|
|
ReactorsData<REACTOR_DAILY_UPTIME_EXCLUDED_REACTORS$, -1> = Reactor
|
|
end
|
|
Next Reactor
|
|
if AllReactorsScheduledMinutes GT 0 then
|
|
TotalUptimePercent = SRP_Math('ROUND', AllReactorsUptimeMinutes / AllReactorsScheduledMinutes, 5)
|
|
TotalUptimeMinutes = SRP_Math('ROUND', AllReactorsUptimeMinutes, 5)
|
|
TotalAvailMinutes = SRP_Math('ROUND', AllReactorsScheduledMinutes, 5)
|
|
TotalProdPercent = SRP_Math('ROUND', AllReactorsProdMinutes / AllReactorsScheduledMinutes, 5)
|
|
TotalUnschedDownPercent = SRP_Math('ROUND', AllReactorsUnschedDownMinutes / AllReactorsScheduledMinutes, 5)
|
|
TotalSchedDownPercent = SRP_Math('ROUND', AllReactorsSchedDownMinutes / AllReactorsScheduledMinutes, 5)
|
|
TotalEngPercent = SRP_Math('ROUND', AllReactorsEngMinutes / AllReactorsScheduledMinutes, 5)
|
|
TotalIdlePercent = SRP_Math('ROUND', AllReactorsIdleMinutes / AllReactorsScheduledMinutes, 5)
|
|
end else
|
|
TotalUptimePercent = 0
|
|
TotalUptimeMinutes = 0
|
|
TotalAvailMinutes = 0
|
|
TotalProdPercent = 0
|
|
TotalUnschedDownPercent = 0
|
|
TotalSchedDownPercent = 0
|
|
TotalEngPercent = 0
|
|
TotalIdlePercent = 0
|
|
end
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_PERCENTAGE$> = TotalUptimePercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_PROD_PERCENTAGE$> = TotalProdPercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_PROD_MINUTES$> = AllReactorsProdMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_ENG_PERCENTAGE$> = TotalEngPercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_ENG_MINUTES$> = AllReactorsEngMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_DOWN_UNSCHED_PERCENTAGE$> = TotalUnschedDownPercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_DOWN_UNSCHED_MINUTES$> = AllReactorsUnschedDownMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_DOWN_SCHED_PERCENTAGE$> = TotalSchedDownPercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_DOWN_SCHED_MINUTES$> = AllReactorsSchedDownMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_IDLE_PERCENTAGE$> = TotalIdlePercent
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_IDLE_MINUTES$> = AllReactorsIdleMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_UPTIME_MINUTES$> = TotalUptimeMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_AVAIL_MINUTES$> = TotalAvailMinutes
|
|
ReactorsData<REACTOR_DAILY_UPTIME_TOTAL_SINGLE_LL$> = AllReactorsSingleLL
|
|
Response = ReactorsData
|
|
end else
|
|
Error_Services('Add', 'Error getting reactor uptime metrics -> Unable to get total report duration.')
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetLoadedRds(ReactNo)
|
|
|
|
StopRDS = Xlate('REACT_STATE', ReactNo, 'LAST_RDS_NO', 'X')
|
|
|
|
// Get list of RDS on current reactor that are not FQA
|
|
ReactorConfigKey = 'WO_DAILY_SCHED':ReactNo
|
|
WoNo = Field(Xlate('CONFIG', ReactorConfigKey, WOCust$, 'X'), ' ', 1)
|
|
RDSColumns = ''
|
|
RDSColumns<0, 1> = 'SEQ'
|
|
RDSList = RDS_Services('GetRDSData', WoNo, RDSColumns, False$, '')
|
|
|
|
// Find the index of StopRDS
|
|
RDSList = SRP_Sort_Array(RDSList, "AN1")
|
|
RDSFastArray = SRP_Fastarray("Create", RDSList)
|
|
StopRDSIdx = 0
|
|
SRP_Fastarray("Match", RDSFastArray, StopRDS, StopRDSIdx)
|
|
RDSList = SRP_Fastarray("GetVariable", RDSFastArray)
|
|
|
|
RdsKeys = '':@FM:''
|
|
RdsKeysPosition = 1
|
|
RdsIdx = StopRDSIdx + 1
|
|
DateIn = ''
|
|
DateOut = ''
|
|
Loop
|
|
DateIn = Xlate('RDS', RDSList<RdsIdx>, RDS_DATE_IN$, 'X')
|
|
DateOut = Xlate('RDS', RDSList<RdsIdx>, RDS_DATE_OUT$, 'X')
|
|
While (DateIn NE '') and (DateOut EQ '')
|
|
RdsKeys<RdsKeysPosition> = RDSList<RdsIdx>
|
|
If (RdsKeysPosition EQ 1) then
|
|
RdsKeysPosition = 2
|
|
end else
|
|
RdsKeysPosition = 1
|
|
end
|
|
RdsIdx += 1
|
|
Repeat
|
|
|
|
Response = RdsKeys
|
|
|
|
end service
|
|
|
|
|
|
Service ActiveProveInPreventsModeChange(ReactNo, NewMode, CurrentMode)
|
|
|
|
If (ReactNo NE '') then
|
|
If (NewMode NE '') then
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactNo)
|
|
ActiveProveIn = Reactor_Services('GetProveInActive', ReactNo)
|
|
If ActiveProveIn EQ True$ then
|
|
Nica_Orders_Services('GetOrderUpdates')
|
|
ActiveProveIn = Reactor_Services('GetProveInActive', ReactNo)
|
|
If ActiveProveIn EQ True$ then
|
|
Begin Case
|
|
Case CurrentMode EQ 'INITIATE_IDLE'
|
|
IdleStartupActive = Reactor_Services('GetIdleStartupRequired', ReactNo)
|
|
If IdleStartupActive EQ True$ then
|
|
Response = True$
|
|
end else
|
|
Response = False$
|
|
end
|
|
Case Len(NewMode) GE 2 and NewMode[1, 2] EQ 'UP'
|
|
Response = True$
|
|
Case Otherwise$
|
|
Response = False$
|
|
End Case
|
|
end else
|
|
Response = False$
|
|
end
|
|
end else
|
|
Response = False$
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ' : Service : ' service. NewMode was empty')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ' : Service : ' service. ReactNo was empty')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorDownLL(ReactNo)
|
|
|
|
Response = ''
|
|
If RowExists('REACTOR', ReactNo) then
|
|
LLDisabledID = Database_Services('ReadDataColumn', 'REACTOR', ReactNo, REACTOR_ACTIVE_LL_DISABLED$, True$, 0)
|
|
If LLDisabledID NE '' then
|
|
If RowExists('REACT_LL', LLDisabledID) then
|
|
DownLoadLock = Database_Services('ReadDataColumn', 'REACT_LL', LLDisabledID, REACT_LL_DISABLED$, True$, 0)
|
|
Response = DownLoadLock
|
|
end
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorLoadCountLimit(ReactNo)
|
|
|
|
ErrMsg = 'Error in ReactorServices -> GetReactorLoadCountLimit: '
|
|
MaxLoadCount = 999
|
|
If ReactNo NE '' then
|
|
If RowExists('REACTOR', ReactNo) then
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactNo)
|
|
If Error_Services('NoError') then
|
|
ReactType = ReactorRec<REACTOR_REACT_TYPE$>
|
|
PickPlace = ReactorRec<REACTOR_PICK_PLACE$>
|
|
DisabledLoadLockCnt = DCount(ReactorRec<REACTOR_ACTIVE_LL_DISABLED$>, @VM)
|
|
Begin Case
|
|
Case ReactType EQ 'ASM'
|
|
If PickPlace then
|
|
MaxLoadCount = 2 - DisabledLoadLockCnt
|
|
end else
|
|
MaxLoadCount = 1
|
|
end
|
|
Case ReactType EQ 'ASM+'
|
|
If PickPlace then
|
|
MaxLoadCount = 2 - DisabledLoadLockCnt
|
|
end else
|
|
MaxLoadCount = 1
|
|
end
|
|
Case ReactType EQ 'HTR'
|
|
If PickPlace then
|
|
MaxLoadCount = 2 - DisabledLoadLockCnt
|
|
end else
|
|
MaxLoadCount = 1
|
|
end
|
|
Case ReactType EQ 'EPP'
|
|
MaxLoadCount = 2;*EPP needs to have an additional load capability.
|
|
End Case
|
|
end else
|
|
ErrMsg := Error_Services('GetMessage')
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
ErrMsg := 'Reactor ' : ReactNo : ' does not exist.'
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
ErrMsg := 'Reactor Number was null.'
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
Response = MaxLoadCount
|
|
|
|
end service
|
|
|
|
|
|
Service GetReactorAvailChamberCount(ReactNo)
|
|
|
|
ErrMsg = 'Error in ReactorServices -> GetReactorAvailChamberCount: '
|
|
AvailableChamberCount = 0
|
|
If ReactNo NE '' then
|
|
If RowExists('REACTOR', ReactNo) then
|
|
LoadedRDS = Reactor_Services('GetReactorCurrLoadRDS', ReactNo)
|
|
ReactorCurrLoadCnt = DCount(LoadedRDS, @VM)
|
|
ReactorCurrCapacity = Reactor_Services('GetReactorLoadCountLimit', ReactNo)
|
|
AvailableChamberCount = ReactorCurrCapacity - ReactorCurrLoadCnt
|
|
end else
|
|
ErrMsg := 'Reactor ' : ReactNo : ' does not exist.'
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
ErrMsg := 'Reactor Number was null.'
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
Response = AvailableChamberCount
|
|
|
|
end service
|
|
|
|
|
|
Service RemoveRDSFromReactorLoad(RDSNo, ReactorNo, User)
|
|
|
|
Response = 0
|
|
If User NE '' then
|
|
If RDSNo NE '' then
|
|
If ReactorNo NE '' then
|
|
ReactStatusRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactorNo)
|
|
If Error_Services('NoError') then
|
|
Locate RDSNo in ReactStatusRec<REACT_STATUS_LOAD_RDS$> setting RDSPos then
|
|
ReactStatusRec = Delete(ReactStatusREc, REACT_STATUS_LOAD_RDS$, RDSPos, 0)
|
|
ReactStatusRec = Delete(ReactStatusREc, REACT_STATUS_LOAD_RDS_DTM$, RDSPos, 0)
|
|
ReactStatusRec = Delete(ReactStatusREc, REACT_STATUS_LOAD_CASS_ID$, RDSPos, 0)
|
|
ReactStatusRec = Delete(ReactStatusREc, REACT_STATUS_LOAD_DTM$, RDSPos, 0)
|
|
Database_Services('WriteDataRow', 'REACT_STATUS', ReactorNo, ReactStatusRec, 1, 0, 1)
|
|
If Error_Services('NoError') then
|
|
Response = 1
|
|
end else
|
|
ErrMsg = Error_Services('GetMessage')
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: RDS was not found as a loaded lot.')
|
|
end
|
|
end else
|
|
ErrMsg = Error_Services('GetMessage')
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: No Reactor No was supplied.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: No RDS No was supplied.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: No Username was supplied.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service AddRDSToReactorLoad(RDSNo, ReactorNo)
|
|
|
|
Response = 0
|
|
If RDSNo NE '' then
|
|
If ReactorNo NE '' then
|
|
ReactStatusRec = Database_Services('ReadDataRow', 'REACT_STATUS', ReactorNo)
|
|
If Error_Services('NoError') then
|
|
Locate RDSNo in ReactStatusRec<REACT_STATUS_LOAD_RDS$> using @VM setting iPos else
|
|
WONo = Xlate('RDS', RDSNo, 'WO_NO', 'X')
|
|
CassNo = Xlate('RDS', RDSNo, 'CASS_NO', 'X')
|
|
WOMatKey = WONo : '*' : CassNo
|
|
ThisDTM = SRP_Datetime('Now')
|
|
ReactStatusRec<REACT_STATUS_LOAD_RDS$, -1> = RDSNo
|
|
ReactStatusRec<REACT_STATUS_LOAD_RDS_DTM$, -1> = ThisDTM
|
|
ReactStatusRec<REACT_STATUS_LOAD_CASS_ID$, -1> = WOMatKey
|
|
ReactStatusRec<REACT_STATUS_LOAD_DTM$, -1> = ThisDTM
|
|
Database_Services('WriteDataRow', 'REACT_STATUS', ReactorNo, ReactStatusRec, 1, 0, 1)
|
|
end
|
|
end else
|
|
ErrMsg = Error_Services('GetMessage')
|
|
Error_Services('Add', ErrMsg)
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: No Reactor No was supplied.')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in Reactor Services -> RemoveRDSFromReactorLoad: No RDS No was supplied.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service UpdateReactorIQSViolations()
|
|
|
|
ReactNos = Reactor_Services('GetReactorNumbers')
|
|
If Error_Services('NoError') then
|
|
CurrViols = Database_Services('ReadDataRow', 'CONFIG', 'IQS_VIOL_DATA')
|
|
If Error_Services('NoError') then
|
|
ViolatingReactors = CurrViols<IQS_VIOL_DATA.REACTOR$>
|
|
ViolationDtms = CurrViols<IQS_VIOL_DATA.LAST_ALARM$>
|
|
ViolationTests = CurrViols<IQS_VIOL_DATA.TEST$>
|
|
Swap ' AM' with 'AM' in ViolationDtms
|
|
Swap ' PM' with 'PM' in ViolationDtms
|
|
ViolationDtms = IConv(ViolationDtms, 'DT')
|
|
For each ReactNo in ReactNos
|
|
ActiveAlarm = False$
|
|
For each ViolReactor in ViolatingReactors using @VM setting vPos
|
|
If ViolReactor EQ ReactNo then
|
|
ActiveAlarm = True$
|
|
ThisAlarmDtm = ViolationDtms<0, vPos>
|
|
ThisAlarmTest = ViolationTests<0, vPos>
|
|
// Check if a new alarm and update if necessary
|
|
LastAlarmDtm = Xlate('REACTOR', ReactNo, REACTOR_IQS_ALARM_DTM$, 'X')
|
|
If LastAlarmDtm LT ThisAlarmDtm then
|
|
// New alarm
|
|
HaveLock = Database_Services('GetKeyIDLock', 'REACTOR', ReactNo, True$)
|
|
If HaveLock then
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactNo)
|
|
If Error_Services('NoError') then
|
|
ReactorRec<REACTOR_IQS_ALARM_DTM$> = ThisAlarmDtm
|
|
ReactorRec<REACTOR_IQS_ALARM_TEST$> = ThisAlarmTest
|
|
// WriteDataRow will clear the lock as long as "IgnoreAllLocks" is false
|
|
// REACTOR_ACTIONS will be triggered, which will generate a NICA order if a new HgCV alarm is detected
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactNo, ReactorRec, True$, False$, False$)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Next ViolReactor
|
|
|
|
If Not(ActiveAlarm) then
|
|
// Clear last active alarm
|
|
HaveLock = Database_Services('GetKeyIDLock', 'REACTOR', ReactNo, True$)
|
|
If HaveLock then
|
|
ReactorRec = Database_Services('ReadDataRow', 'REACTOR', ReactNo)
|
|
If Error_Services('NoError') then
|
|
ReactorRec<REACTOR_IQS_ALARM_DTM$> = ''
|
|
ReactorRec<REACTOR_IQS_ALARM_TEST$> = ''
|
|
// WriteDataRow will clear the lock as long as "IgnoreAllLocks" is false
|
|
Database_Services('WriteDataRow', 'REACTOR', ReactNo, ReactorRec, True$, False$, False$)
|
|
end
|
|
end
|
|
end
|
|
Next ReactNo
|
|
end
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetProveInActive(ReactNo)
|
|
|
|
If ReactNo NE '' then
|
|
OrderTypes = 'CHANGEOVER' : @VM : 'INITIATE_IDLE' : @VM : 'IDLE'
|
|
ActiveProveInIds = Nica_Orders_Services('GetActiveOrders', 'REACTOR', ReactNo, OrderTypes)
|
|
Response = (ActiveProveInIds NE '')
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetActiveProveInTypes(ReactNo)
|
|
|
|
If ReactNo NE '' then
|
|
ActiveProveInOrderIds = Reactor_Services('GetActiveProveInOrderIds', ReactNo)
|
|
If ActiveProveInOrderIds NE '' then
|
|
Response = Xlate('NICA_ORDERS', ActiveProveInOrderIds, 'ORDER_TYPE', 'X')
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetActiveProveInProgresses(ReactNo)
|
|
|
|
Response = ''
|
|
If ReactNo NE '' then
|
|
ActiveProveInOrderIds = Reactor_Services('GetActiveProveInOrderIds', ReactNo)
|
|
If ActiveProveInOrderIds NE '' then
|
|
OrderTypes = Xlate('NICA_ORDERS', ActiveProveInOrderIds, 'ORDER_TYPE', 'X')
|
|
OrderCount = Dcount(OrderTypes, @VM)
|
|
For I = 1 to OrderCount
|
|
OrderType = OrderTypes<I>
|
|
ProgressPercentage = Xlate('NICA_ORDERS', ActiveProveInOrderIds<i>, 'PROGRESS_PERCENTAGE', 'X')
|
|
Response<-1> = OrderType : '- ' : ProgressPercentage :'% Complete.'
|
|
Next I
|
|
end
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
Service GetActiveProveInOrderIds(ReactNo)
|
|
|
|
If ReactNo NE '' then
|
|
OrderTypes = 'CHANGEOVER' : @VM : 'INITIATE_IDLE' : @VM : 'IDLE'
|
|
Response = Nica_Orders_Services('GetActiveOrders', 'REACTOR', ReactNo, OrderTypes)
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetIdleStartupRequired(ReactNo)
|
|
|
|
If ReactNo NE '' then
|
|
Response = Xlate('REACTOR', ReactNo, REACTOR_IDLE_STARTUP_REQUIRED$, 'X')
|
|
end else
|
|
Error_Services('Add', 'Error in ':Service:' service. Null ReactNo passed into service.')
|
|
end
|
|
|
|
end service
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Internal GoSubs
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
RollbackReactUtil:
|
|
|
|
// Reopen previous REACT_UTIL record
|
|
If OldReactUtilID NE '' then
|
|
OldReactUtilRec = Database_Services('ReadDataRow', 'REACT_UTIL', OldReactUtilID)
|
|
OldReactUtilRec<react_util_end_date$> = ''
|
|
OldReactUtilRec<react_util_end_time$> = ''
|
|
OldReactUtilRec<react_util_mode_finish_user$> = ''
|
|
Database_Services('WriteDataRow', 'REACT_UTIL', OldReactUtilID, OldReactUtilRec)
|
|
end
|
|
|
|
return
|
|
|
|
|
|
ClearCursors:
|
|
|
|
For counter = 0 to 8
|
|
ClearSelect counter
|
|
Next counter
|
|
|
|
return
|
|
|