示例#1
0
        public IHttpActionResult GetRecommendations(Guid id)
        {
            // Allow find by ScenarioId (original) or RunId
            var run = _runRepository.Find(id);

            if (run == null)        // Not a RunId passed, check if a ScenarioId
            {
                run = _runRepository.FindByScenarioId(id);
            }
            if (run == null)
            {
                return(NotFound());
            }
            bool isScenarioId    = (run.Id != id);
            var  recommendations = _recommendationRepository.GetByScenarioId(isScenarioId ? id : run.Scenarios[0].Id);
            var  items           = _mapper.Map <List <RecommendationModel> >(recommendations);

            // For Smooth recommendations only then return "Unplaced", instead
            // of null, for unplaced breaks
            foreach (var item in items)
            {
                if (item.Processor == "smooth" && String.IsNullOrEmpty(item.ExternalBreakNo))
                {
                    item.ExternalBreakNo = Globals.UnplacedBreakString;
                }
            }
            return(Ok(items));
        }
示例#2
0
        public IHttpActionResult GetBRSIndicator(Guid runId, int?brsConfigurationTemplateId = null)
        {
            var run = _runRepository.Find(runId);

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

            var scenarioResults = _brsManager.CalculateBRSIndicators(run, brsConfigurationTemplateId);

            return(Ok(_mapper.Map <List <BRSIndicatorValueForScenarioResultModel> >(scenarioResults)));
        }
        protected override string DownloadRunInputFiles(Guid runId, string localFolder, string localInputFolder)
        {
            var run = _runRepository.Find(runId);

            if (run is null)
            {
                throw new Exception($"Run {runId.ToString()} was not found");
            }

            return(_inputFilesGenerator.PopulateRunData(run));
        }
示例#4
0
        public OutputImmutableDataSnapshot(RunWithScenarioReference runWithScenarioRef, IRunRepository runRepository,
                                           IScenarioRepository scenarioRepository, IPassRepository passRepository,
                                           ICampaignRepository campaignRepository, IScheduleRepository scheduleRepository,
                                           ISalesAreaRepository salesAreaRepository, IDemographicRepository demographicRepository,
                                           IProgrammeDictionaryRepository programmeDictionaryRepository, ISpotRepository spotRepository,
                                           IMetadataRepository metadataRepository)
        {
            var runStartDate = new Lazy <DateTime>(() => Run.Value.StartDate.Add(Run.Value.StartTime));
            var runEndDate   = new Lazy <DateTime>(() => DateHelper.ConvertBroadcastToStandard(Run.Value.EndDate, Run.Value.EndTime));

            Run                      = new Lazy <Run>(() => runRepository.Find(runWithScenarioRef.RunId));
            Scenario                 = new Lazy <Scenario>(() => scenarioRepository.Get(runWithScenarioRef.ScenarioId), true);
            ScenarioPasses           = new Lazy <IEnumerable <Pass> >(() => passRepository.FindByScenarioId(runWithScenarioRef.ScenarioId), true);
            AllCampaigns             = new Lazy <IEnumerable <Campaign> >(campaignRepository.GetAll, true);
            AllSalesAreas            = new Lazy <IEnumerable <SalesArea> >(salesAreaRepository.GetAll, true);
            AllDemographics          = new Lazy <IEnumerable <Demographic> >(demographicRepository.GetAll, true);
            AllProgrammeDictionaries = new Lazy <IEnumerable <ProgrammeDictionary> >(programmeDictionaryRepository.GetAll, true);
            BreakTypes               = new Lazy <IEnumerable <string> >(() => metadataRepository.GetByKey(MetaDataKeys.BreakTypes).Select(e => (string)e.Value));

            SpotsForRun = new Lazy <IEnumerable <Spot> >(() =>
            {
                var salesAreaPriorities = Run.Value.SalesAreaPriorities.Count == 0
                    ? AllSalesAreas.Value
                    : AllSalesAreas.Value.Where(sa => Run.Value.SalesAreaPriorities.Find(rsa => rsa.SalesArea == sa.Name) != null);

                return(spotRepository.Search(
                           runStartDate.Value,
                           runEndDate.Value,
                           salesAreaPriorities.Select(sa => sa.Name).ToList()
                           ));
            },
                                                         true
                                                         );

            BreaksForRun = new Lazy <IEnumerable <BreakSimple> >(() =>
                                                                 scheduleRepository.GetScheduleSimpleBreaks(
                                                                     AllSalesAreas.Value.Select(c => c.Name).ToList(),
                                                                     runStartDate.Value,
                                                                     runEndDate.Value
                                                                     ),
                                                                 true
                                                                 );
        }
示例#5
0
        /// <summary>
        /// Handles completed with error, no results
        /// </summary>
        public void HandleCompletedFatalError(AutoBook autoBook)
        {
            IRunRepository runRepository = null;

            try
            {
                using var scope = _repositoryFactory.BeginRepositoryScope();
                // Get scenario snapshot for diagnostics
                //_scenarioSnapshotGenerator.Generate(autoBook, _scenarioId);

                // Flag scenario as CompletedError, no results available
                DateTime?completedDateTime = DateTime.UtcNow;
                RunManager.UpdateScenarioStatuses(_repositoryFactory, _auditEventRepository, RunId, new List <Guid>()
                {
                    ScenarioId
                }, new List <ScenarioStatuses>()
                {
                    ScenarioStatuses.CompletedError
                }, null, new List <DateTime?>()
                {
                    completedDateTime
                });

                // Get run details
                runRepository = scope.CreateRepository <IRunRepository>();
                var run      = runRepository.Find(RunId);
                var scenario = run.Scenarios.Find(currentScenario => currentScenario.Id == ScenarioId);

                // Notification run scenario completed with error
                try
                {
                    _runCompletionNotifier.Notify(run, scenario, false);
                }
                catch (System.Exception exception)
                {
                    // Log failure, don't throw
                    _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForException(0, 0, string.Format("Error generating notification for run completed failure (RunID={0}, ScenarioID={1})", RunId, ScenarioId), exception));
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                using var scope = _repositoryFactory.BeginRepositoryScope();
                // Load run so that we can check number of completed scenarios, use fresh repo instance in case run changed elsewhere
                runRepository = scope.CreateRepository <IRunRepository>();
                var run = runRepository.Find(RunId);

                // Generate notification if all scenarios completed, success if at least one scenario generated results
                if (run.Scenarios.Count == run.CompletedScenarios.Count)
                {
                    _synchronizationService.Release(run.Id);

                    int countSucccess = run.Scenarios.Where(currentScenario => currentScenario.Status == ScenarioStatuses.CompletedSuccess).ToList().Count;
                    try
                    {
                        _runCompletionNotifier.Notify(run, (countSucccess > 0));
                    }
                    catch (System.Exception exception)
                    {
                        // Log failure, don't throw
                        _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForException(0, 0, string.Format("Error generating notification for run completed failure (RunID={0})", run.Id), exception));
                    }
                }
            }
        }
示例#6
0
        /// <summary>
        /// Handles completed successfully, downloads and processes output data. If we can't process the output data (E.g. Cloud issues)
        /// then that is a failure too.
        /// </summary>
        public void HandleCompletedSuccess()
        {
            bool           success       = false;
            IRunRepository runRepository = null;

            try
            {
                try
                {
                    using var scope = _repositoryFactory.BeginRepositoryScope();
                    // Update status to GettingResults
                    RunManager.UpdateScenarioStatuses(_repositoryFactory, _auditEventRepository, RunId, new List <Guid>()
                    {
                        ScenarioId
                    }, new List <ScenarioStatuses>()
                    {
                        ScenarioStatuses.GettingResults
                    });

                    // Get run details
                    runRepository = scope.CreateRepository <IRunRepository>();
                    var scenarioResultRepository = scope.CreateRepository <IScenarioResultRepository>();
                    var run      = runRepository.Find(RunId);
                    var scenario = run.Scenarios.Find(currentScenario => currentScenario.Id == ScenarioId);

                    // Get results
                    _autoBookOutputHandler.Handle(run, ScenarioId);

                    success = true;

                    // Notification run scenario completed
                    try
                    {
                        _runCompletionNotifier.Notify(run, scenario, success);
                    }
                    catch (System.Exception exception)
                    {
                        // Log failure, don't throw
                        _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForException(0, 0, string.Format("Error generating notification for run completed success (RunID={0}, ScenarioID={1})", RunId, ScenarioId), exception));
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    // Update status to CompletedSuccess/CompletedError
                    DateTime?        completedDateTime = DateTime.UtcNow;
                    ScenarioStatuses scenarioStatus    = success ? ScenarioStatuses.CompletedSuccess : ScenarioStatuses.CompletedError;
                    RunManager.UpdateScenarioStatuses(_repositoryFactory, _auditEventRepository, RunId, new List <Guid>()
                    {
                        ScenarioId
                    }, new List <ScenarioStatuses>()
                    {
                        scenarioStatus
                    }, null, new List <DateTime?>()
                    {
                        completedDateTime
                    });
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                using var scope = _repositoryFactory.BeginRepositoryScope();
                // Load run so that we can check number of completed scenarios, use fresh repo instance in case run changed elsewhere
                runRepository = scope.CreateRepository <IRunRepository>();
                var run = runRepository.Find(RunId);

                // Generate notification if all scenarios completed, success if at least one scenario generates results
                if (run.Scenarios.Count == run.CompletedScenarios.Count)
                {
                    _synchronizationService.Release(run.Id);

                    int countSucccess = run.Scenarios.Where(currentScenario => currentScenario.Status == ScenarioStatuses.CompletedSuccess).ToList().Count;
                    try
                    {
                        _runCompletionNotifier.Notify(run, (countSucccess > 0));
                    }
                    catch (System.Exception exception)
                    {
                        // Log failure, don't throw
                        _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForException(0, 0, string.Format("Error generating notification for run completed success (RunID={0})", RunId), exception));
                    }

                    try
                    {
                        // Calculate BRS Indicator

                        IEnumerable <ScenarioResult> calculatedScenarioResults = _brsIndicatorManager.CalculateBRSIndicatorsAfterRunCompleted(run);

                        SendToLandmark(run, calculatedScenarioResults);
                    }
                    catch (Exception exception)
                    {
                        _auditEventRepository.Insert(AuditEventFactory.CreateAuditEventForException(0, 0, $"Error calculation brs indicator for run completed success (RunID={RunId})", exception));
                    }
                }
            }
        }
示例#7
0
        /// <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));
        }