4324 lines
223 KiB
Plaintext
4324 lines
223 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
|
|
$Insert REACT_PROB_CAT_EQUATES
|
|
$Insert NICA_ORDERS_EQUATES
|
|
$Insert REACTOR_INJECTOR_SETTINGS_EQUATES
|
|
$Insert REACTOR_RATIOS_EQUATES
|
|
$Insert REACT_STATE_EQUATES
|
|
|
|
Equ WOCust$ to 2
|
|
Equ SECONDS_IN_DAY$ to 86400
|
|
|
|
// 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, Reactor_Log_Services, obj_Post_Log
|
|
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, Max, RTI_CreateGUID
|
|
|
|
// 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', 'EXHAUST_CHAMBER_THK'
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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$>
|
|
CurrExhaustThk = OldReactorRec<REACTOR_EXHAUST_CHAMBER_THK$>
|
|
|
|
// 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
|
|
If CurrExhaustThk = '' then CurrExhaustThk = 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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + TargetThickness
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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$>
|
|
ResponseData<1, 7> = ReactorRec<REACTOR_EXHAUST_CHAMBER_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> = 'TubeWaferCount'
|
|
ResponseData<2, 5> = 'TubeThickness'
|
|
ResponseData<2, 6> = 'ArmsWaferCount'
|
|
ResponseData<2, 7> = 'ExhuastChamberThickness'
|
|
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$>
|
|
ResponseData<1, 7> = ReactorRec<REACTOR_EXHAUST_CHAMBER_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> = 'TubeWaferCount'
|
|
ResponseData<2, 5> = 'TubeThickness'
|
|
ResponseData<2, 6> = 'ArmsWaferCount'
|
|
ResponseData<2, 7> = 'ExhuastChamberThickness'
|
|
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$>
|
|
ResponseData<1, 8> = ReactorRec<REACTOR_EXHAUST_CHAMBER_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'
|
|
ResponseData<2, 8> = 'ExhuastChamberThickness'
|
|
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$>
|
|
CurrExhaustThk = OldReactorRec<REACTOR_EXHAUST_CHAMBER_THK$>
|
|
|
|
// 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
|
|
If CurrExhaustThk = '' then CurrExhaustThk = 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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - TargetThickness
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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$>
|
|
CurrExhaustThk = OldReactorRec<REACTOR_EXHAUST_CHAMBER_THK$>
|
|
|
|
// 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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + TargetThickness
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk + ThkAddition
|
|
|
|
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$>
|
|
CurrExhaustThk = OldReactorRec<REACTOR_EXHAUST_CHAMBER_THK$>
|
|
|
|
// 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
|
|
If CurrExhaustThk = '' then CurrExhaustThk = 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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - TargetThickness
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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
|
|
NewReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = CurrExhaustThk - ThkAddition
|
|
|
|
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', EXHAUST_CHAMBER_THK)
|
|
//
|
|
// 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
|
|
|
|
Case MetricType = 'EXHAUST_CHAMBER_THK'
|
|
ReactorRec<REACTOR_EXHAUST_CHAMBER_THK$> = 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$>
|
|
RlComment = ''
|
|
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
|
|
AbortAlarmFeatureFlag = Xlate('FEATURE_FLAGS', 'NICA_ABORT_ALARM', FEATURE_FLAGS.ENABLED$, 'X')
|
|
If AbortAlarmFeatureFlag EQ True$ then
|
|
ModeSubCatFlowId = Xlate('REACT_PROB_CAT', ModeSubCatId, REACT_PROB_CAT_ABORT_ALARM_FLOW_ID$, 'X')
|
|
ModeSubCatRespLvl = Xlate('REACT_PROB_CAT', ModeSubCatId, REACT_PROB_CAT_ABORT_ALARM_RESPONSE_LEVEL$, 'X')
|
|
AbortAlarmComp = Xlate('REACTOR', ReactNo, REACTOR_ABORT_ALARM_COMPLETE$, 'X')
|
|
ActiveAbortAlarmOrders = Nica_Orders_Services('GetActiveOrders', 'REACTOR', ReactNo, 'ABORT_ALARM')
|
|
AbortAlarmOrderActive = (ActiveAbortAlarmOrders NE '')
|
|
Begin Case
|
|
Case ( AbortAlarmOrderActive and (SelE10State _EQC 'Productive') )
|
|
ErrorMsg = "An ABORT/ALARM Checklist is active for this reactor and must be completed or overridden in order to change to a productive state."
|
|
|
|
Case ( AbortAlarmOrderActive and IndexC(ModeSubCat, 'ABORT/ALARM', 1) and (ModeSubCatFlowId NE '') )
|
|
// If there is an active ABORT/ALARM NICA order, then we need to check if the new sub mode is different than the sub mode entered when the ABORT/ALARM
|
|
// NICA order was created and is of a higher response level or the new mode is WAITING_FOR_OPERATOR and the sub mode has changed. This means the maintenance
|
|
// team deemed the true ABORT/ALARM root cause was different than the cause the operators selected.
|
|
ActiveAbortAlarmFlowIds = Xlate('NICA_ORDERS', ActiveAbortAlarmOrders, NICA_ORDERS.ORDER_FLOW_IDS$, 'X')
|
|
ActiveAbortAlarmRespLvls = Xlate('NICA_ORDERS', ActiveAbortAlarmOrders, NICA_ORDERS.ORDER_RESPONSE_LEVEL$, 'X')
|
|
MaxActiveRespLvl = ''
|
|
For each ActiveAbortAlarmRespLvl in ActiveAbortAlarmRespLvls using @VM
|
|
MaxActiveRespLvl = Max(MaxActiveRespLvl, ActiveAbortAlarmRespLvl)
|
|
Next ActiveAbortAlarmRespLvl
|
|
If ( (Mode _EQC 'WAITING_FOR_OPERATOR') and (ModeSubCatFlowId NE ActiveAbortAlarmFlowIds) ) |
|
|
or ( (ModeSubCatFlowId NE ActiveAbortAlarmFlowIds) and (ModeSubCatRespLvl GT MaxActiveRespLvl) ) then
|
|
ReactorType = Xlate('REACTOR', ReactNo, REACTOR_REACT_TYPE$, 'X')
|
|
ChecklistIds = Nica_Orders_Services('GetFlowChecklistIds', ModeSubCatFlowId, 'ABORT_ALARM', ReactorType)
|
|
If ChecklistIds NE '' then
|
|
Nica_Orders_Services('CreateNewOrder', 'REACTOR', ReactNo, 'ABORT_ALARM', ModeSubCatFlowId, ModeSubCatRespLvl, ChecklistIds)
|
|
RlComment = 'ABORT/ALARM initiated for flow ':ModeSubCatFlowId:'.'
|
|
end
|
|
end
|
|
|
|
Case ( Not(AbortAlarmComp) and Not(AbortAlarmOrderActive) and IndexC(ModeSubCat, 'ABORT/ALARM', 1) and (ModeSubCatFlowId NE '') )
|
|
ReactorType = Xlate('REACTOR', ReactNo, REACTOR_REACT_TYPE$, 'X')
|
|
ChecklistIds = Nica_Orders_Services('GetFlowChecklistIds', ModeSubCatFlowId, 'ABORT_ALARM', ReactorType)
|
|
If ChecklistIds NE '' then
|
|
Nica_Orders_Services('CreateNewOrder', 'REACTOR', ReactNo, 'ABORT_ALARM', ModeSubCatFlowId, ModeSubCatRespLvl, ChecklistIds)
|
|
RlComment = 'ABORT/ALARM initiated for flow ':ModeSubCatFlowId:'.'
|
|
end
|
|
Case Otherwise$
|
|
// Don't create an ABORT/ALARM NICA order
|
|
Null
|
|
|
|
End Case
|
|
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
|
|
|
|
CurrWoNo = Xlate('CONFIG', 'WO_DAILY_SCHED':ReactNo, 'F2', 'X')
|
|
CurrWoNo = CurrWoNo[1, 'F ']
|
|
If CurrWoNo NE '' then
|
|
CurrPSNo = Xlate('WO_LOG', CurrWoNo, 'PS_NO', 'X')
|
|
end else
|
|
CurrPSNo = ''
|
|
end
|
|
RLRec<REACTOR_LOG_PROD_SPEC_NO$> = CurrPSNo
|
|
|
|
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
|
|
If RlComment NE '' then Reactor_Log_Services('AddComment', ReactNo, RlComment, UserID)
|
|
If SelE10State _EQC 'Productive' then
|
|
// Reset ABORT/ALARM flag
|
|
Open 'REACTOR' to hReactor then
|
|
WriteV False$ to hReactor, ReactNo, REACTOR_ABORT_ALARM_COMPLETE$ then
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Successfully set ABORT_ALARM_COMPLETE flag to false for Reactor No: ' : ReactNo
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
end else
|
|
LogData = ''
|
|
LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM
|
|
LogData<2> = 'Failed set ABORT_ALARM_COMPLETE flag to false for Reactor No: ' : ReactNo
|
|
Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$)
|
|
end
|
|
end
|
|
end
|
|
|
|
// 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
|
|
|
|
|
|
Service GetCurrentInjectorSettings(ReactorNo)
|
|
|
|
ErrorMsg = ''
|
|
CurrInjSettings = ''
|
|
If ReactorNo NE '' then
|
|
If RowExists('REACTOR', ReactorNo) then
|
|
Open 'DICT.REACTOR_INJECTOR_SETTINGS' to hDict then
|
|
Query = 'REACTOR_NO':@VM:ReactorNo:@FM
|
|
Query := 'ACTIVE':@VM:True$:@FM
|
|
KeyList = ''
|
|
Option = 'E'
|
|
Flag = ''
|
|
Btree.Extract(Query, 'REACTOR_INJECTOR_SETTINGS', hDict, KeyList, Option, Flag)
|
|
If Flag EQ 0 then
|
|
Begin Case
|
|
Case DCount(KeyList, @VM) EQ 0
|
|
CurrInjSettings<0, 1> = ''
|
|
CurrInjSettings<0, 2> = ''
|
|
CurrInjSettings<0, 3> = ''
|
|
CurrInjSettings<0, 4> = ''
|
|
CurrInjSettings<0, 5> = ''
|
|
Case DCount(KeyList, @VM) EQ 1
|
|
SettingsRec = Database_Services('ReadDataRow', 'REACTOR_INJECTOR_SETTINGS', KeyList)
|
|
If Error_Services('NoError') then
|
|
CurrInjSettings<0, 1> = SettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_1$>
|
|
CurrInjSettings<0, 2> = SettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_2$>
|
|
CurrInjSettings<0, 3> = SettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_3$>
|
|
CurrInjSettings<0, 4> = SettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_4$>
|
|
CurrInjSettings<0, 5> = SettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_5$>
|
|
end
|
|
Case DCount(KeyList, @VM) GT 1
|
|
ErrorMsg = 'Error in ':Service:' service. Multiple active REACTOR_INJECTOR_SETTINGS records returned.'
|
|
End Case
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening DICT.REACTOR_INJECTOR_SETTINGS.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR, ':ReactorNo:', does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorNo passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = CurrInjSettings
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetCurrentRatios(ReactorNo)
|
|
|
|
ErrorMsg = ''
|
|
CurrRatios = ''
|
|
If ReactorNo NE '' then
|
|
If RowExists('REACTOR', ReactorNo) then
|
|
Open 'DICT.REACTOR_RATIOS' to hDict then
|
|
Query = 'REACTOR_NO':@VM:ReactorNo:@FM
|
|
Query := 'ACTIVE':@VM:True$:@FM
|
|
KeyList = ''
|
|
Option = 'E'
|
|
Flag = ''
|
|
Btree.Extract(Query, 'REACTOR_RATIOS', hDict, KeyList, Option, Flag)
|
|
If Flag EQ 0 then
|
|
NumRatios = ''
|
|
ReactorType = Xlate('REACTOR', ReactorNo, REACTOR_REACT_TYPE$, 'X')
|
|
Begin Case
|
|
Case ReactorNo EQ 73
|
|
// OpenInsight needs to be updated to support reactor type HTR+, which requires 16 ratios.
|
|
NumRatios = 16
|
|
Case ReactorType EQ 'ASM' or ReactorType EQ 'ASM+'
|
|
NumRatios = 10
|
|
Case ReactorType EQ 'HTR'
|
|
NumRatios = 12
|
|
Case Otherwise$
|
|
ErrorMsg = 'Error in ':Service:' service. Error determining number '
|
|
ErrorMsg := 'of Ratios required for reactor ':ReactorNo:'.'
|
|
End Case
|
|
If ErrorMsg EQ '' then
|
|
Begin Case
|
|
Case DCount(KeyList, @VM) EQ 0
|
|
For RatioIndex = 1 to NumRatios
|
|
CurrRatios<0, RatioIndex> = ''
|
|
Next RatioIndex
|
|
Case DCount(KeyList, @VM) EQ 1
|
|
SettingsRec = Database_Services('ReadDataRow', 'REACTOR_RATIOS', KeyList)
|
|
If Error_Services('NoError') then
|
|
For RatioIndex = 0 to (NumRatios - 1)
|
|
CurrRatios<0, RatioIndex + 1> = SettingsRec<REACTOR_RATIOS.RATIO_1$ + RatioIndex>
|
|
Next RatioIndex
|
|
end
|
|
Case DCount(KeyList, @VM) GT 1
|
|
ErrorMsg = 'Error in ':Service:' service. Multiple active REACTOR_RATIOS records returned.'
|
|
End Case
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening DICT.REACTOR_RATIOS.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR, ':ReactorNo:', does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorNo passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = CurrRatios
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetRatiosByReactorLog(ReactorLogId)
|
|
|
|
RatiosKey = ''
|
|
Ratios = ''
|
|
ErrorMsg = ''
|
|
ReactorNo = ''
|
|
If ReactorLogId NE '' then
|
|
If RowExists('REACTOR_LOG', ReactorLogId) then
|
|
Query = 'SELECT REACTOR_RATIOS WITH REACTOR_LOG_ID EQ ':Quote(ReactorLogId)
|
|
Query := ' BY-DSND RATIO_SET_DTM'
|
|
RList(Query, TARGET_ACTIVELIST$)
|
|
ErrCode = ''
|
|
If Not(Get_Status(ErrCode)) then
|
|
If @RecCount GT 0 then
|
|
ReadNext RatiosKey else
|
|
ErrorMsg = 'Error in ':Service:' service. Error looking up reactor '
|
|
ErrorMsg := 'ratios associated with REACTOR_LOG ':ReactorLogId:'.'
|
|
end
|
|
ClearSelect TARGET_ACTIVELIST$
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error looking up reactor '
|
|
ErrorMsg := 'ratios associated with REACTOR_LOG ':ReactorLogId:'.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR_LOG ':ReactorLogId:' does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorLogId passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
If RatiosKey NE '' then
|
|
RatiosRec = Database_Services('ReadDataRow', 'REACTOR_RATIOS', RatiosKey)
|
|
If Error_Services('NoError') then
|
|
If ReactorNo EQ '' then ReactorNo = Xlate('REACTOR_LOG', ReactorLogId, 'REACTOR', 'X')
|
|
If ReactorNo NE '' then
|
|
NumRatios = Reactor_Services('GetNumRatios', ReactorNo)
|
|
For RatioIndex = 0 to (NumRatios - 1)
|
|
Ratios<0, RatioIndex + 1> = RatiosRec<REACTOR_RATIOS.RATIO_1$ + RatioIndex>
|
|
Next RatioIndex
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null Reactor in REACTOR_LOG ':ReactorLogId:'.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error reading REACTOR_RATIOS record ':RatiosKey:'.'
|
|
end
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = Ratios
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetInjectorSettingsByReactorLog(ReactorLogId)
|
|
|
|
ReactInjSetKey = ''
|
|
InjSettings = ''
|
|
ErrorMsg = ''
|
|
If ReactorLogId NE '' then
|
|
If RowExists('REACTOR_LOG', ReactorLogId) then
|
|
Query = 'SELECT REACTOR_INJECTOR_SETTINGS WITH REACTOR_LOG_ID EQ ':Quote(ReactorLogId)
|
|
Query := ' BY-DSND INJ_SET_DTM'
|
|
RList(Query, TARGET_ACTIVELIST$)
|
|
ErrCode = ''
|
|
If Not(Get_Status(ErrCode)) then
|
|
If @RecCount GT 0 then
|
|
ReadNext ReactInjSetKey else
|
|
ErrorMsg = 'Error in ':Service:' service. Error looking up reactor injector '
|
|
ErrorMsg := 'settings associated with REACTOR_LOG ':ReactorLogId:'.'
|
|
end
|
|
ClearSelect TARGET_ACTIVELIST$
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error looking up reactor injector '
|
|
ErrorMsg := 'settings associated with REACTOR_LOG ':ReactorLogId:'.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR_LOG ':ReactorLogId:' does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorLogId passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
If ReactInjSetKey NE '' then
|
|
ReactInjSetRec = Database_Services('ReadDataRow', 'REACTOR_INJECTOR_SETTINGS', ReactInjSetKey)
|
|
If Error_Services('NoError') then
|
|
For InjIndex = 0 to 4
|
|
InjSettings<0, InjIndex + 1> = ReactInjSetRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_1$ + InjIndex>
|
|
Next InjIndex
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error reading REACTOR_INJECTOR_SETTINGS record ':ReactInjSetKey:'.'
|
|
end
|
|
end
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = InjSettings
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service SetNewInjectorSettings(ReactorNo, InjSettings)
|
|
|
|
// Injector settings should be passed in internal format (MD3)
|
|
ErrorMsg = ''
|
|
If ReactorNo NE '' then
|
|
If RowExists('REACTOR', ReactorNo) then
|
|
If InjSettings NE '' then
|
|
If DCount(InjSettings, @VM) EQ 5 then
|
|
For each InjSetting in InjSettings using @VM setting vPos
|
|
If InjSettings EQ '' then ErrorMsg = 'Error in ':Service:' service. Injector setting ':vPos:' is missing.'
|
|
Until ErrorMsg NE ''
|
|
Next InjSetting
|
|
If ErrorMsg EQ '' then
|
|
CurrInjSettings = Reactor_Services('GetCurrentInjectorSettings', ReactorNo)
|
|
If (CurrInjSettings NE InjSettings) then
|
|
CurrRlId = Xlate('CONFIG', 'REACT_MODE':ReactorNo, 8, 'X')
|
|
If CurrRlId NE '' then
|
|
Query = 'REACTOR_NO':@VM:ReactorNo:@FM:'ACTIVE':@VM:True$:@FM
|
|
Open 'DICT.REACTOR_INJECTOR_SETTINGS' to hDict then
|
|
Option = 'E'
|
|
ActiveInjSettingsKeys = ''
|
|
Flag = ''
|
|
Btree.Extract(Query, 'REACTOR_INJECTOR_SETTINGS', hDict, ActiveInjSettingsKeys, Option, Flag)
|
|
If Flag EQ 0 then
|
|
If ActiveInjSettingsKeys NE '' then
|
|
Open 'REACTOR_INJECTOR_SETTINGS' to hTable then
|
|
For each ActiveInjSettingsKey in ActiveInjSettingsKeys using @VM
|
|
WriteV False$ on hTable, ActiveInjSettingsKey, REACTOR_INJECTOR_SETTINGS.ACTIVE$ else
|
|
ErrorMsg = 'Error in ':Service:' service. Error setting previous injector '
|
|
ErrorMsg := 'settings to inactive. File error: ':@File_Error
|
|
end
|
|
Until ErrorMsg NE ''
|
|
Next ActiveInjSettingsKey
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening REACTOR_INJECTOR_SETTINGS to '
|
|
ErrorMsg := 'invalidate previous settings.'
|
|
end
|
|
end
|
|
If ErrorMsg EQ '' then
|
|
NewInjSettingsKey = RTI_CreateGUID()
|
|
If NewInjSettingsKey NE '' then
|
|
NewInjSettingsRec = ''
|
|
NewInjSettingsRec<REACTOR_INJECTOR_SETTINGS.REACTOR_LOG_ID$> = CurrRlId
|
|
NewInjSettingsRec<REACTOR_INJECTOR_SETTINGS.REACTOR_NO$> = ReactorNo
|
|
NewInjSettingsRec<REACTOR_INJECTOR_SETTINGS.INJ_SET_DTM$> = Datetime()
|
|
NewInjSettingsRec<REACTOR_INJECTOR_SETTINGS.ACTIVE$> = True$
|
|
For InjIndex = 0 to 4
|
|
NewInjSettingsRec<REACTOR_INJECTOR_SETTINGS.INJECTOR_1$ + InjIndex> = InjSettings<0, InjIndex + 1>
|
|
Next InjIndex
|
|
Database_Services('WriteDataRow', 'REACTOR_INJECTOR_SETTINGS', NewInjSettingsKey, NewInjSettingsRec)
|
|
If Error_Services('NoError') then
|
|
plParms = 'REACT_STATE':@RM
|
|
plParms := ReactorNo:@RM
|
|
plParms := REACT_STATE_CURR_INJ_RL_ID$:@RM
|
|
plParms := CurrRlId:@RM
|
|
obj_Post_Log('Create',plParms)
|
|
If Get_Status(ErrCode) then
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling obj_Post_Log("Create"). '
|
|
ErrorMsg := 'Error code: ':ErrCode:'.'
|
|
end
|
|
end else
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error creating new REACTOR_INJECTOR_SETTINGS record.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening DICT.REACTOR_INJECTOR_SETTINGS'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error reading current REACTOR_LOG Id.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Input InjSettings are the same as the current InjSettings.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. All five injector settings are required.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null InjSettings passed into service.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR, ':ReactorNo:', does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorNo passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = True$
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
Response = False$
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service SetNewRatios(ReactorNo, Ratios)
|
|
|
|
// Ratios should be passed in internal format (MD3)
|
|
ErrorMsg = ''
|
|
If ReactorNo NE '' then
|
|
If RowExists('REACTOR', ReactorNo) then
|
|
If Ratios NE '' then
|
|
Ratios = SRP_Array('Clean', Ratios, 'Trim', @VM)
|
|
NumRatios = Reactor_Services('GetNumRatios', ReactorNo)
|
|
If Error_Services('NoError') then
|
|
If DCount(Ratios, @VM) EQ NumRatios then
|
|
For each Ratio in Ratios using @VM setting vPos
|
|
Begin Case
|
|
Case Ratio EQ ''
|
|
ErrorMsg = 'Error in ':Service:' service. Ratio ':vPos:' is missing.'
|
|
Case OConv(Ratio, 'MD3') LT 30
|
|
ErrorMsg = 'Error in ':Service:' service. Invalid Ratio value. Ratio ':vPos:' is less than 30.'
|
|
Case OConv(Ratio, 'MD3') GT 100
|
|
ErrorMsg = 'Error in ':Service:' service. Invalid Ratio value. Ratio ':vPos:' is greater than 100.'
|
|
End Case
|
|
Until ErrorMsg NE ''
|
|
Next Ratio
|
|
If ErrorMsg EQ '' then
|
|
CurrRatios = Reactor_Services('GetCurrentRatios', ReactorNo)
|
|
If (CurrRatios NE Ratios) then
|
|
CurrRlId = Xlate('CONFIG', 'REACT_MODE':ReactorNo, 8, 'X')
|
|
If CurrRlId NE '' then
|
|
Query = 'REACTOR_NO':@VM:ReactorNo:@FM:'ACTIVE':@VM:True$:@FM
|
|
Open 'DICT.REACTOR_RATIOS' to hDict then
|
|
Option = 'E'
|
|
ActiveRatiosKeys = ''
|
|
Flag = ''
|
|
Btree.Extract(Query, 'REACTOR_RATIOS', hDict, ActiveRatiosKeys, Option, Flag)
|
|
If Flag EQ 0 then
|
|
If ActiveRatiosKeys NE '' then
|
|
Open 'REACTOR_RATIOS' to hTable then
|
|
For each ActiveRatiosKey in ActiveRatiosKeys using @VM
|
|
WriteV False$ on hTable, ActiveRatiosKey, REACTOR_RATIOS.ACTIVE$ else
|
|
ErrorMsg = 'Error in ':Service:' service. Error setting previous ratios '
|
|
ErrorMsg := 'record to inactive. File error: ':@File_Error
|
|
end
|
|
Until ErrorMsg NE ''
|
|
Next ActiveRatiosKey
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening REACTOR_RATIOS table to '
|
|
ErrorMsg := 'invalidate previous ratios.'
|
|
end
|
|
end
|
|
If ErrorMsg EQ '' then
|
|
NewRatiosKey = RTI_CreateGUID()
|
|
If NewRatiosKey NE '' then
|
|
NewRatiosRec = ''
|
|
NewRatiosRec<REACTOR_RATIOS.REACTOR_LOG_ID$> = CurrRlId
|
|
NewRatiosRec<REACTOR_RATIOS.REACTOR_NO$> = ReactorNo
|
|
NewRatiosRec<REACTOR_RATIOS.RATIO_SET_DTM$> = Datetime()
|
|
NewRatiosRec<REACTOR_RATIOS.ACTIVE$> = True$
|
|
For RatioIndex = 0 to (NumRatios - 1)
|
|
NewRatiosRec<REACTOR_RATIOS.RATIO_1$ + RatioIndex> = Ratios<0, RatioIndex + 1>
|
|
Next RatioIndex
|
|
Database_Services('WriteDataRow', 'REACTOR_RATIOS', NewRatiosKey, NewRatiosRec)
|
|
If Error_Services('NoError') then
|
|
plParms = 'REACT_STATE':@RM
|
|
plParms := ReactorNo:@RM
|
|
plParms := REACT_STATE_CURR_RATIO_RL_ID$:@RM
|
|
plParms := CurrRlId:@RM
|
|
obj_Post_Log('Create',plParms)
|
|
If Get_Status(ErrCode) then
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling obj_Post_Log("Create"). '
|
|
ErrorMsg = 'Error code: ':ErrCode:'.'
|
|
end
|
|
end else
|
|
ErrorMsg = Error_Services('GetMessage')
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error creating new REACTOR_RATIOS record.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error calling Btree.Extract.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error opening DICT.REACTOR_RATIOS'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error reading current REACTOR_LOG Id.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Input Ratios are the same as the current Ratios.'
|
|
end
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Reactor ':ReactorNo:' requires ':NumRatios:' values '
|
|
ErrorMsg := 'for ratios. Only ':DCount(Ratios, @VM):' were supplied.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Error determining number of required ratios '
|
|
ErrorMsg := 'for reactor ':ReactorNo:'. Error message: ':Error_Services("GetMessage")
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null Ratios passed into service.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR, ':ReactorNo:', does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorNo passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = True$
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
Response = False$
|
|
end
|
|
|
|
end service
|
|
|
|
|
|
Service GetNumRatios(ReactorNo)
|
|
|
|
ErrorMsg = ''
|
|
NumRatios = ''
|
|
If (ReactorNo NE '') then
|
|
If RowExists('REACTOR', ReactorNo) then
|
|
ReactorType = Xlate('REACTOR', ReactorNo, REACTOR_REACT_TYPE$, 'X')
|
|
Begin Case
|
|
Case ReactorNo EQ 73
|
|
// OpenInsight needs to be updated to support reactor type HTR+, which requires 16 ratios.
|
|
NumRatios = 16
|
|
Case ReactorType EQ 'ASM' or ReactorType EQ 'ASM+'
|
|
NumRatios = 10
|
|
Case ReactorType EQ 'HTR'
|
|
NumRatios = 12
|
|
Case Otherwise$
|
|
ErrorMsg = 'Error in ':Service:' service. Error determining number '
|
|
ErrorMsg := 'of Ratios required for reactor ':ReactorNo:'.'
|
|
End Case
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. REACTOR, ':ReactorNo:', does not exist.'
|
|
end
|
|
end else
|
|
ErrorMsg = 'Error in ':Service:' service. Null ReactorNo passed into service.'
|
|
end
|
|
|
|
If ErrorMsg EQ '' then
|
|
Response = NumRatios
|
|
end else
|
|
Error_Services('Add', ErrorMsg)
|
|
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
|
|
|