// ============================================================================= // DEE Action: ASA_Scenario3_CheckSanitationRecordLogged // Scenario: 3 — Controller Version Update — No Materials on Resource // Stage: Acceptance Gate (second gate, after ReadyDelay) // // Purpose: // Before applying the MixingController update, verify that the food safety // system holds a completed sanitation record for the target mixer resource. // This ensures the update only runs after a confirmed CIP cycle — not just // after materials have naturally cleared between batches. // If no completed record is found, return false so the task stays at // SkippedGateFailed and retries on the next polling pass. // // Simulation: // The sanitation record state for each resource is controlled by a per-resource // MES Configuration Entry, toggled independently from the MES UI: // // Path : /Cmf/Tutorials/AutomationScheduleAction/Scenario3/SanitationRecordLogged/{resourceName} // Type : Boolean // Value: true → sanitation record confirmed → gate passes // false → no record yet → SkippedGateFailed // // Example entries for the tutorial resources: // /Cmf/Tutorials/AutomationScheduleAction/Scenario3/SanitationRecordLogged/ASA Mixer-01 // /Cmf/Tutorials/AutomationScheduleAction/Scenario3/SanitationRecordLogged/ASA Mixer-02 // /Cmf/Tutorials/AutomationScheduleAction/Scenario3/SanitationRecordLogged/ASA Mixer-03 // // Set all to false initially. Set one to true to trigger processing for that // resource while the others remain blocked at the gate. // // DEE Contract: // Input - Task : AutomationScheduledActionTask (includes linked resource via EntityName) // Output - Result : Boolean (true = sanitation record found, false = not found) // // 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_Scenario3_CheckSanitationRecordLogged : 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(); var task = Input["Task"] as IAutomationScheduledActionTask; string resourceName = task?.EntityName ?? string.Empty; // In production this is where the food safety system query would go // For simulation, we just read the config value to determine if a completed record is logged const string configParentPath = "/Cmf/Tutorials/AutomationScheduleAction/Scenario3/SanitationRecordLogged"; string configPath = $"{configParentPath}/{resourceName}"; IConfig sanitationConfig = _entFactory.Create(); if (!sanitationConfig.TryLoad(configPath)) { sanitationConfig.Name = resourceName; sanitationConfig.ValueType = "System.Boolean"; sanitationConfig.Value = false; sanitationConfig.Create(configParentPath); } bool recordLogged = sanitationConfig.GetConfigValue(); Input["Result"] = recordLogged; //---End DEE Code--- return Input; } } }