コード例 #1
0
ファイル: ScenariosController.cs プロジェクト: Morebis-GIT/CI
        public IHttpActionResult Delete(Guid id)
        {
            if (!ModelState.IsValid)
            {
                return(this.Error().InvalidParameters("Invalid scenario parameters"));
            }

            Scenario scenario = _scenarioRepository.Get(id);

            if (scenario == null)
            {
                return(this.NotFound());
            }

            // Check that scenario isn't referenced by a run
            var runs = _runRepository.GetByScenarioId(id);

            if (runs.Any())
            {
                return(this.Error().BadRequest("Cannot delete a scenario because a run has a dependency on it"));
            }

            // Check that scenario being deleted isn't the default
            TenantSettings tenantSettings = _tenantSettingsRepository.Get();

            if (scenario.Id == tenantSettings.DefaultScenarioId)
            {
                return(this.Error().BadRequest("Cannot delete the default scenario"));
            }

            _passRepository.RemoveByScenarioId(id);
            _scenarioRepository.Delete(id);

            return(this.NoContent());
        }
コード例 #2
0
        /// <summary>
        /// Returns RunModels for runs
        /// </summary>
        /// <param name="runs"></param>
        /// <param name="scenarioRepository"></param>
        /// <param name="passRepository"></param>
        /// <param name="analysisGroupRepository"></param>
        /// <param name="tenantSettingsRepository"></param>
        /// <returns></returns>
        public static List <RunModel> MapToRunModels(IEnumerable <Run> runs, IScenarioRepository scenarioRepository,
                                                     IPassRepository passRepository, IAnalysisGroupRepository analysisGroupRepository,
                                                     ITenantSettingsRepository tenantSettingsRepository, IMapper mapper)
        {
            // Get scenarios for all runs
            var scenarios = scenarioRepository.FindByIds(runs.SelectMany(r => r.Scenarios).Select(s => s.Id).Distinct()).ToList();

            // Get passes for all runs
            var passes = passRepository.FindByIds(scenarios.SelectMany(s => s.Passes).Select(p => p.Id).Distinct()).ToList();

            var analysisGroupIds = runs.SelectMany(x => x.AnalysisGroupTargets.Select(t => t.AnalysisGroupId)).ToArray();
            var analysisGroups   = analysisGroupIds.Any()
                ? analysisGroupRepository.GetByIds(analysisGroupIds).ToDictionary(x => x.Id)
                : new Dictionary <int, AnalysisGroupNameModel>();

            // Get default ScenarioId
            var defaultScenarioId = tenantSettingsRepository.Get().DefaultScenarioId;

            List <RunModel> runModels = new List <RunModel>();

            foreach (var run in runs)
            {
                var runModel = mapper.Map <RunModel>(Tuple.Create(run, scenarios, passes, analysisGroups, defaultScenarioId));
                runModels.Add(runModel);
            }
            return(runModels);
        }
コード例 #3
0
        public Dictionary <string, object> GetFeatureSettings(string featureStr)
        {
            Dictionary <string, object> featuresdict = new Dictionary <string, object>();
            var tenantSetting = _tenantSettingsRepository.Get();

            foreach (var feature in tenantSetting.Features)
            {
                if (feature.Id.ToLower() == featureStr.ToLower())
                {
                    foreach (KeyValuePair <string, object> setting in feature.Settings)
                    {
                        featuresdict.Add(setting.Key, setting.Value);
                    }
                }
            }

            return(featuresdict);
        }
コード例 #4
0
        /// <summary>
        /// Returns ScenarioModel from Scenario
        /// </summary>
        /// <param name="scenario"></param>
        /// <param name="scenarioRepository"></param>
        /// <param name="passRepository"></param>
        /// <param name="tenantSettingsRepository"></param>
        /// <returns></returns>
        public static ScenarioModel MapToScenarioModel(Scenario scenario, IScenarioRepository scenarioRepository, IPassRepository passRepository,
                                                       ITenantSettingsRepository tenantSettingsRepository, IMapper mapper)
        {
            // Get passes
            List <Pass> passes = passRepository.FindByIds(scenario.Passes.Select(p => p.Id)).ToList();

            // Get default ScenarioId
            var defaultScenarioId = tenantSettingsRepository.Get().DefaultScenarioId;

            var scenarioModel = mapper.Map <ScenarioModel>(Tuple.Create(scenario, passes, defaultScenarioId));

            return(scenarioModel);
        }
コード例 #5
0
        public IHttpActionResult GetTenantTimeSettings()
        {
            try
            {
                var tenantSettings = _tenantSettingsRepository.Get();

                return(Ok(tenantSettings.ConvertToTimeTenantSettings(_productFeatureManager)));
            }
            catch (Exception ex)
            {
                return(this.Error().UnknownError(ex.Message));
            }
        }
コード例 #6
0
        /// <summary>
        /// Returns ScenarioModel list from Scenario list
        /// </summary>
        /// <param name="scenarios"></param>
        /// <param name="scenarioRepository"></param>
        /// <param name="passRepository"></param>
        /// <param name="tenantSettingsRepository"></param>
        /// <returns></returns>
        public static List <ScenarioModel> MapToScenarioModels(
            List <Scenario> scenarios,
            IScenarioRepository scenarioRepository,
            IPassRepository passRepository,
            ITenantSettingsRepository tenantSettingsRepository,
            IMapper mapper)
        {
            var scenarioModels     = new List <ScenarioModel>();
            var passIdsInScenarios = scenarios
                                     .SelectMany(s => s.Passes)
                                     .Select(p => p.Id);

            var passes = passRepository.GetAll().Where(p => passIdsInScenarios.Contains(p.Id)).ToList();

            var defaultScenarioId = tenantSettingsRepository.Get().DefaultScenarioId;

            scenarios.ForEach(scenario => scenarioModels.Add(mapper.Map <ScenarioModel>(
                                                                 Tuple.Create(scenario, passes, defaultScenarioId))));

            return(scenarioModels);
        }
コード例 #7
0
        public async Task <IHttpActionResult> SetDefault(Guid id)
        {
            if (id == Guid.Empty)
            {
                return(BadRequest("Invalid Id"));
            }

            LibrarySalesAreaPassPriority libSalesAreaPassPriority = await _librarySalesAreaPassPrioritiesRepository.GetAsync(id);

            if (libSalesAreaPassPriority == null)
            {
                return(NotFound());
            }

            TenantSettings tenantSettings = _tenantSettingsRepository.Get();

            if (tenantSettings != null)
            {
                tenantSettings.DefaultSalesAreaPassPriorityId = id;
                _tenantSettingsRepository.AddOrUpdate(tenantSettings);
            }
            return(Ok());
        }
コード例 #8
0
        public SystemLogicalDateService(ITenantSettingsRepository tenantSettingsRepository, IFeatureManager featureManager, IClock clock, IAuditEventRepository auditEventRepository)
        {
            _clock = clock;

            var tenantSettings = tenantSettingsRepository.Get();

            var useSystemLogicalDate = featureManager.IsEnabled(nameof(ProductFeature.UseSystemLogicalDate));

            if (useSystemLogicalDate)
            {
                var isDateValid = DateTime.TryParseExact(tenantSettings.SystemLogicalDate, SystemLogicalDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var systemLogicalDate);

                if (isDateValid)
                {
                    _isSystemLogicalDateUsed = true;
                    _systemLogicalDate       = systemLogicalDate.Add(_clock.GetCurrentInstant().ToDateTimeUtc().TimeOfDay);
                }
                else
                {
                    auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForWarningMessage(0, 0, $"System Logical Date is not it valid format. " +
                                                                                                    $"Date set: '{tenantSettings.SystemLogicalDate}', but valid format is: '{SystemLogicalDateFormat}'. Using current Date instead."));
                }
            }
        }
コード例 #9
0
        public IEnumerable <TenantSettings> GetAll()
        {
            var tenantSettings = _tenantSettingsRepository.Get();

            return(tenantSettings != null ? new[] { tenantSettings } : default(IEnumerable <TenantSettings>));
        }
コード例 #10
0
        /// <summary>
        /// Handles run completed, all scenarios
        /// </summary>
        /// <param name="run"></param>
        /// <param name="success"></param>
        public void Notify(Run run, bool success)
        {
            TenantSettings tenantSettings          = _tenantSettingsRepository.Get();
            bool           notificationsConfigured = false;

            _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForRunCompleted(0, 0, run.Id, success ? "Completed successfully" : "Completed with errors"));

            // Get run event settings
            if (tenantSettings.RunEventSettings != null)
            {
                RunEventSettings runEventSettings = tenantSettings.RunEventSettings.Where(item => item.EventType == RunEvents.RunCompleted).FirstOrDefault();
                if (runEventSettings != null)
                {
                    var exceptions = new List <Exception>();

                    try
                    {
                        // Check HTTP notification
                        INotification <HTTPNotificationSettings> httpNotification = _notifications?.GetNotification <HTTPNotificationSettings>();
                        if (runEventSettings.HTTP != null && httpNotification != null && runEventSettings.HTTP.Enabled)
                        {
                            notificationsConfigured = true;
                            try
                            {
                                _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForGameplanPipelineStart(0, 0,
                                                                                                                        PipelineEventIDs.STARTED_NOTIFYING_MULE_SOFT_API, run.Id, null, null, string.Format("Generating HTTP notification for run completed (RunID={0}, Success={1})", run.Id, success)));

                                _pipelineAuditEventRepository.Add(PipelineEventHelper.CreatePipelineAuditEvent(AuditEventTypes.GamePlanRun,
                                                                                                               PipelineEventIDs.STARTED_NOTIFYING_MULE_SOFT_API, run.Id, Guid.Empty, null));

                                httpNotification.RunCompleted(run, success, runEventSettings.HTTP);

                                _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForGameplanPipelineEnd(0, 0,
                                                                                                                      PipelineEventIDs.FINISHED_NOTIFYING_MULE_SOFT_API, run.Id, null, null, string.Format("Generated HTTP notification for run completed (RunID={0}, Success={1})", run.Id, success), null, null));

                                _pipelineAuditEventRepository.Add(PipelineEventHelper.CreatePipelineAuditEvent(AuditEventTypes.GamePlanRun,
                                                                                                               PipelineEventIDs.FINISHED_NOTIFYING_MULE_SOFT_API, run.Id, Guid.Empty, null));
                            }
                            catch (System.Exception exception)
                            {
                                _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForGameplanPipelineEnd(0, 0,
                                                                                                                      PipelineEventIDs.FINISHED_NOTIFYING_MULE_SOFT_API, run.Id, null, null, string.Format("Failed to generate HTTP notification for run completed (RunID={0}, Success={1})", run.Id, success), exception.Message, exception));

                                _pipelineAuditEventRepository.Add(PipelineEventHelper.CreatePipelineAuditEvent(AuditEventTypes.GamePlanRun,
                                                                                                               PipelineEventIDs.FINISHED_NOTIFYING_MULE_SOFT_API, run.Id, Guid.Empty, exception.Message));
                                throw;
                            }
                            finally
                            {
                                _pipelineAuditEventRepository.SaveChanges();
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        exceptions.Add(exception);
                    }

                    if (exceptions.Count == 1)
                    {
                        throw exceptions[0];
                    }
                    else if (exceptions.Count > 0)
                    {
                        throw new AggregateException(exceptions);
                    }
                }
            }

            // Log warning if notifications not enabled so that there's no dispute over why they weren't generated
            if (!notificationsConfigured)
            {
                _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForWarningMessage(0, 0, string.Format("Not generating notification for run completed because notifications are not configured or enabled (RunID={0}, Success={1})", run.Id, success)));
            }
        }
コード例 #11
0
        public List <SystemMessage> Validate(Run run)
        {
            var messages = new List <SystemMessage>();

            using (var scope = _repositoryFactory.BeginRepositoryScope())
            {
                var repositories = scope.CreateRepositories(
                    typeof(ISalesAreaRepository),
                    typeof(ICampaignRepository),
                    typeof(IAutoBookInstanceConfigurationRepository),
                    typeof(IDemographicRepository),
                    typeof(IScheduleRepository),
                    typeof(ISmoothConfigurationRepository)
                    );
                var salesAreaRepository = repositories.Get <ISalesAreaRepository>();
                var campaignRepository  = repositories.Get <ICampaignRepository>();
                var autoBookInstanceConfigurationRepository = repositories.Get <IAutoBookInstanceConfigurationRepository>();
                var demographicRepository         = repositories.Get <IDemographicRepository>();
                var scheduleRepository            = repositories.Get <IScheduleRepository>();
                var smoothConfigurationRepository = repositories.Get <ISmoothConfigurationRepository>();

                // Validate run details, first check that run is well formed and
                // carry on if it pass this first method check
                messages.AddRange(ValidateRunDetailsForStartRun(run));
                if (messages.Count != 0)
                {
                    return(messages);
                }

                // Get Sales areas for run and list of sales area names from
                // run.SalesAreaPriorities NOT set to 'Exclude'
                var runSalesAreas     = new List <SalesArea>();
                var runSalesAreaNames = new List <string>();
                if (run.SalesAreaPriorities.Any())
                {
                    runSalesAreas     = salesAreaRepository.FindByNames(run.SalesAreaPriorities.Where(s => s.Priority != SalesAreaPriorityType.Exclude).Select(s => s.SalesArea).ToList());
                    runSalesAreaNames = salesAreaRepository.GetListOfNames(runSalesAreas);
                }
                else
                {
                    // If there are NO entries in run.SalesAreaPriorities then
                    // get all sales are names from the repository of sales areas
                    runSalesAreaNames = salesAreaRepository.GetListOfNames(salesAreaRepository.GetAll().ToList());
                }

                // check that there are some sales areas from one of the two
                // sources above
                if (!runSalesAreaNames.Any())
                {
                    messages.Add(FormatSystemMessage(SystemMessage.SalesAreaDataMissing));

                    // only carry on with the run validation if there are some
                    // sales areas
                    return(messages);
                }

                bool isOptimiserNeeded = run.Optimisation || run.RightSizer || run.ISR;

                var allAutoBookInstanceConfigurations = autoBookInstanceConfigurationRepository.GetAll().ToList();
                if (!allAutoBookInstanceConfigurations.Any())
                {
                    allAutoBookInstanceConfigurations = _autoBooks.CreateDefaultInstanceConfigurations();
                }

                var allCampaigns = campaignRepository.GetAllFlat().ToList();
                var runCampaigns = RunManager.GetRunCampaigns(run, allCampaigns);
                var demographics = demographicRepository.GetAll().ToList();

                // Validate RatingsData
                if (_featureManager.IsEnabled(nameof(ProductFeature.NineValidationRatingPredictions)))
                {
                    var demographicsGameplan = demographics.Where(g => g.Gameplan).Select(x => x.ExternalRef).ToList();

                    var noOfRatingPredictionsPerScheduleDayAreaDemo = _tenantSettingsRepository.Get()?.NoOfRatingsPerSalesDayDemo ?? 96;
                    messages.AddRange(ValidateMissingRatingsForStartRun(run.StartDate, run.EndDate, runSalesAreaNames, demographicsGameplan, noOfRatingPredictionsPerScheduleDayAreaDemo));
                }

                if (isOptimiserNeeded && allAutoBookInstanceConfigurations.Count > 1)   //single instance?
                {
                    // Get number of breaks
                    int breaks = RunManager.GetBreakCountEstimate(run, runSalesAreas, _repositoryFactory);

                    messages.AddRange(ValidateAutoBookResourcesForStartRun(run, allAutoBookInstanceConfigurations, runSalesAreas.Count, runCampaigns.Count, demographics.Count, breaks));
                }

                // Validate ISR settings
                messages.AddRange(ValidateISRSettingsForStartRun(run, runSalesAreas));

                // Validate RS settings
                messages.AddRange(ValidateRSSettingsForStartRun(run, runSalesAreas));

                // Validate Optimisation settings
                messages.AddRange(ValidateOptimisationSettingsForStartRun(run));

                // Validate Smooth configuration
                messages.AddRange(ValidateSmoothConfiguration(run, smoothConfigurationRepository));

                // Validate against existing runs
                messages.AddRange(ValidateExistingRunsForStartRun());

                // Validate schedule data (Breaks, spots, campaigns etc)
                messages.AddRange(ValidateScheduleDataForStartRun(run, runCampaigns, runSalesAreas, demographics.Count));

                // Validate demographics
                messages.AddRange(ValidateDemographicsForStartRun(demographics));

                // Validate output files, can't process output files if data is missing
                messages.AddRange(ValidateOutputFilesForStartRun(run));

                // Validate universes
                messages.AddRange(ValidateUniversesForStartRun(run, runSalesAreas));
            }

            return(messages);
        }
コード例 #12
0
ファイル: RunsValidator.cs プロジェクト: Morebis-GIT/CI
        /// <summary>
        /// Validates for saving run
        /// </summary>
        /// <param name="run"></param>
        /// <param name="allScenarios"></param>
        /// <param name="allPassesByScenario"></param>
        public void ValidateForSave(
            Run run,
            List <Scenario> allScenarios,
            List <List <Pass> > allPassesByScenario,
            List <SalesArea> allSalesAreas)
        {
            // Basic validation
            Run.ValidateForSave(run);

            ValidateAnalysisGroupTargets(run.AnalysisGroupTargets);

            if (run.RunTypeId != 0)
            {
                if (_featureManager.IsEnabled(nameof(ProductFeature.RunType)))
                {
                    var runType = _runTypeRepository.Get(run.RunTypeId);
                    if (runType is null || runType.Hidden)
                    {
                        throw new Exception("Run type not found");
                    }
                }
                else
                {
                    run.RunTypeId = 0;
                }
            }

            if (run.Scenarios.Count > 1 && !_brsConfigurationTemplateRepository.Exists(run.BRSConfigurationTemplateId))
            {
                throw new Exception("BRS template not found");
            }

            RunsValidations.ValidateScenarios(allScenarios);

            // validate all passes
            for (int index = 0; index < allPassesByScenario.Count; index++)
            {
                allPassesByScenario[index]?.ForEach(pass =>
                {
                    Pass.ValidateForSave(pass);
                    Pass.ValidateScenarioNamingUniqueness(pass, new List <Scenario>()
                    {
                        allScenarios[index]
                    });
                });
            }

            // Check that run doesn't contain default scenario, can only contain
            // a copy
            TenantSettings tenantSettings = _tenantSettingsRepository.Get();

            if (tenantSettings.DefaultScenarioId != Guid.Empty && run.Scenarios.Where(s => s.Id == tenantSettings.DefaultScenarioId).Any())
            {
                throw new Exception("Run cannot contain the default scenario. It must contain a copy");
            }

            if (string.IsNullOrWhiteSpace(tenantSettings.PeakStartTime) ||
                string.IsNullOrWhiteSpace(tenantSettings.PeakEndTime))
            {
                throw new ArgumentNullException(nameof(tenantSettings), "Peak daypart is not set. Please check the tenant settings.");
            }

            if (string.IsNullOrWhiteSpace(tenantSettings.MidnightStartTime) ||
                string.IsNullOrWhiteSpace(tenantSettings.MidnightEndTime))
            {
                throw new ArgumentNullException(nameof(tenantSettings), "Midnight daypart is not set. Please check the tenant settings.");
            }

            // Check sales areas priorities
            if (run.SalesAreaPriorities != null && run.SalesAreaPriorities.Any())
            {
                var existingSalesAreaNames = new HashSet <string>(allSalesAreas.Select(s => s.Name));
                var runSalesAreaNames      = new HashSet <string>();

                var  unknownSalesAreas    = new List <string>();
                var  duplicatedSalesAreas = new List <string>();
                bool areAllExcluded       = true;

                foreach (var priority in run.SalesAreaPriorities)
                {
                    if (!existingSalesAreaNames.Contains(priority.SalesArea))
                    {
                        unknownSalesAreas.Add(priority.SalesArea);
                    }

                    if (runSalesAreaNames.Contains(priority.SalesArea))
                    {
                        duplicatedSalesAreas.Add(priority.SalesArea);
                    }

                    if (priority.Priority != SalesAreaPriorityType.Exclude)
                    {
                        areAllExcluded = false;
                    }

                    runSalesAreaNames.Add(priority.SalesArea);
                }

                if (unknownSalesAreas.Any())
                {
                    throw new Exception(string.Format("Sales area {0} is not valid", unknownSalesAreas[0]));
                }

                if (areAllExcluded)
                {
                    throw new Exception("All Sales area priorities are set to Exclude");
                }

                if (duplicatedSalesAreas.Any())
                {
                    throw new Exception(string.Format("Run Sales area priorities contains duplicate {0}", duplicatedSalesAreas[0]));
                }
            }

            // Get runs & scenarios
            var runsWithScenarioId = _runRepository.GetRunsWithScenarioId();

            // Get scenarios & passes
            var scenariosWithPassId = _scenarioRepository.GetScenariosWithPassId();

            if (run.Scenarios != null && run.Scenarios.Any())
            {
                var runSalesAreas        = run.SalesAreaPriorities?.Where(sa => sa.Priority != SalesAreaPriorityType.Exclude).Select(x => x.SalesArea).ToList();
                var salesAreasToValidate = new List <string>();

                for (int scenarioIndex = 0; scenarioIndex < run.Scenarios.Count; scenarioIndex++)
                {
                    var scenario = run.Scenarios[scenarioIndex];
                    var passes   = allPassesByScenario[scenarioIndex];

                    // Check that scenario isn't linked to another run
                    var otherRunIdsForScenarioId = runsWithScenarioId.Where(rws => rws.ScenarioId == scenario.Id && rws.RunId != run.Id).Select(rws => rws.RunId).ToList();
                    if (otherRunIdsForScenarioId.Any())
                    {
                        var otherRun = _runRepository.Find(otherRunIdsForScenarioId.First());
                        throw new Exception(string.Format("Scenario is already linked to Run {0}", otherRun.Description));
                    }

                    if (passes != null && passes.Any())
                    {
                        foreach (var pass in passes)
                        {
                            // Check that passes aren't linked to other scenarios
                            var otherScenarioIdsForPassId = scenariosWithPassId.Where(swp => swp.PassId == pass.Id && swp.ScenarioId != scenario.Id).Select(swp => swp.ScenarioId).ToList();
                            if (otherScenarioIdsForPassId.Any())
                            {
                                var otherScenario = _scenarioRepository.Get(otherScenarioIdsForPassId.First());
                                throw new Exception(string.Format("Pass is already linked to Scenario {0}", otherScenario.Name));
                            }

                            // Check that passes aren't linked to other
                            // scenarios in this run
                            if (pass.Id > 0)
                            {
                                if (passes.Where(p => p.Id == pass.Id).ToList().Count > 1)
                                {
                                    throw new Exception("Scenario cannot contain multiple instances of the same PassID");
                                }

                                for (int scenarioIndex2 = 0; scenarioIndex2 < run.Scenarios.Count; scenarioIndex2++)
                                {
                                    if (scenarioIndex != scenarioIndex2)
                                    {
                                        if (allPassesByScenario[scenarioIndex2].Select(p => p.Id).Contains(pass.Id))
                                        {
                                            throw new Exception("Pass is already linked to another Scenario for this run");
                                        }
                                    }
                                }
                            }

                            var errorMsg = RunsValidations.ValidatePassSalesAreaPriorities(run, pass, tenantSettings, runSalesAreas);
                            if (!string.IsNullOrWhiteSpace(errorMsg))
                            {
                                throw new Exception(errorMsg);
                            }
                        }
                    }

                    // Check break exclusions
                    if (passes != null && passes.Any() && passes.Any(p => p.BreakExclusions != null && p.BreakExclusions.Any()))
                    {
                        var breakExclusions = passes
                                              .Where(p => p?.BreakExclusions != null && p.BreakExclusions.Any())
                                              .SelectMany(p => p.BreakExclusions)
                                              .Select(b => b.SalesArea);

                        salesAreasToValidate.AddRange(breakExclusions);
                    }
                }

                if (salesAreasToValidate.Any())
                {
                    _salesAreaRepository.ValidateSaleArea(salesAreasToValidate);
                }
            }

            // Check campaigns
            if (run.Campaigns != null && run.Campaigns.Count > 0)
            {
                var existingCampaigns = new HashSet <string>(_campaignRepository.GetAllFlat().Select(x => x.ExternalId));
                var unknownCampaigns  = run.Campaigns.Select(ca => ca.ExternalId)
                                        .Where(externalId => !existingCampaigns.Contains(externalId)).ToList();
                if (unknownCampaigns.Any())
                {
                    throw new Exception(string.Format("Campaign {0} is not valid", unknownCampaigns[0]));
                }
            }

            // Validation for slotting control by Demograph
            if (run.Scenarios != null && run.Scenarios.Any())
            {
                var demographicsToValidate = new List <string>();

                for (int scenarioIndex = 0; scenarioIndex < run.Scenarios.Count; scenarioIndex++)
                {
                    var passes = allPassesByScenario[scenarioIndex];

                    if (passes != null && passes.Any() && passes.Any(p => p.SlottingLimits != null && p.SlottingLimits.Any()))
                    {
                        var slottingLimits = passes
                                             .Where(p => p?.SlottingLimits != null && p.SlottingLimits.Any())
                                             .SelectMany(p => p.SlottingLimits)
                                             .Select(b => b.Demographs);

                        demographicsToValidate.AddRange(slottingLimits);
                    }
                }

                demographicsToValidate = demographicsToValidate.Where(x => x != null).Distinct().ToList();

                if (demographicsToValidate.Any() && !_demographicRepository.ValidateDemographics(demographicsToValidate,
                                                                                                 out List <string> invalidDemographics))
                {
                    var msg = string.Concat(
                        "Invalid Demographic in slotting control by Demograph: ",
                        invalidDemographics != null
                            ? string.Join(",", invalidDemographics)
                            : string.Empty);
                    throw new InvalidDataException(msg);
                }
            }

            ValidateDeliveryCappingGroupIds(_mapper.Map <IEnumerable <CampaignRunProcessesSettingsModel> >(run.CampaignsProcessesSettings));
        }