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()); }
/// <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); }
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); }
/// <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); }
public IHttpActionResult GetTenantTimeSettings() { try { var tenantSettings = _tenantSettingsRepository.Get(); return(Ok(tenantSettings.ConvertToTimeTenantSettings(_productFeatureManager))); } catch (Exception ex) { return(this.Error().UnknownError(ex.Message)); } }
/// <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); }
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()); }
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.")); } } }
public IEnumerable <TenantSettings> GetAll() { var tenantSettings = _tenantSettingsRepository.Get(); return(tenantSettings != null ? new[] { tenantSettings } : default(IEnumerable <TenantSettings>)); }
/// <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))); } }
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); }
/// <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)); }