// ============================================================================= // DEE Action: ASA_Scenario5_CheckMaintenanceWindowOpen // Scenario: 5 — Custom DEE Action at Every Stage // Stage: PreCondition (second precondition, after AllowedWeekdays) // // Purpose: // Check whether the global QMS maintenance window is currently active. // This is a global gate: if it returns false, ALL tasks are skipped on this // polling pass — no individual oven checks are performed. // This DEE is intentionally placed after the native AllowedWeekdays check // so it is never invoked on weekends, keeping QMS call volume low. // // Simulation: // The global maintenance window state is controlled by a single MES // Configuration Entry toggled from the MES UI: // // Path : /Cmf/Tutorials/AutomationScheduleAction/Scenario5/MaintenanceWindowOpen // Type : Boolean // Value: true → window is open → all tasks proceed to detector evaluation // false → window is closed → all tasks skipped with SkippedPreConditionFailed // // Set to false to demonstrate how a closed window blocks all tasks simultaneously, // regardless of individual oven readiness. // // DEE Contract: // Input - Task : AutomationScheduledActionTask (minimal context — precondition stage // has no target entity; this check is global) // Output - Result : Boolean (true = window open, false = window closed) // // Fail-closed: any exception or missing config is treated as false. // ============================================================================= using Cmf.Foundation.BusinessOrchestration.Abstractions; using Cmf.Foundation.BusinessOrchestration.ConfigurationManagement.InputObjects; using Cmf.Foundation.Common.Abstractions; using Cmf.Foundation.Configuration.Abstractions; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; namespace Cmf.Custom.Tutorials.AutomationScheduleAction.Actions { public class ASA_Scenario5_CheckMaintenanceWindowOpen : DeeDevBase { public override bool DeeTestCondition(Dictionary Input) { //---Start DEE Condition Code--- return true; //---End DEE Condition Code--- } public override Dictionary DeeActionCode(Dictionary Input) { //---Start DEE Code--- UseReference("", "Cmf.Foundation.BusinessOrchestration.Abstractions"); UseReference("", "Cmf.Foundation.BusinessOrchestration.ConfigurationManagement"); UseReference("", "Cmf.Foundation.BusinessOrchestration.ConfigurationManagement.InputObjects"); IServiceProvider _svcProvider = Input["ServiceProvider"] as IServiceProvider; IEntityFactory _entFactory = _svcProvider.GetService(); //INPUT: Automation Scheduled Action Task var task = Input["Task"] as IAutomationScheduledActionTask; // In production this is where the QMS query would go // For simulation, we just read the config value to determine if the maintenance window is open const string configParentPath = "/Cmf/Tutorials/AutomationScheduleAction/Scenario5"; const string configName = "MaintenanceWindowOpen"; const string configPath = $"{configParentPath}/{configName}"; IConfig windowConfig = _entFactory.Create(); if (!windowConfig.TryLoad(configPath)) { windowConfig.Name = configName; windowConfig.ValueType = "System.Boolean"; windowConfig.Value = false; windowConfig.Create(configParentPath); } bool windowOpen = windowConfig.GetConfigValue(); //OUTPUT: Boolean - true if task in expected maintenance window, otherwise false Input["Result"] = windowOpen; //---End DEE Code--- return Input; } } }