private void PopulateCachedCalculationAggregationsBatch(IEnumerable <ProviderResult> providerResults, Dictionary <string, List <decimal> > cachedCalculationAggregationsBatch, GenerateAllocationMessageProperties messageProperties)
        {
            if (cachedCalculationAggregationsBatch == null)
            {
                _logger.Error($"Cached calculation aggregations not found for key: {messageProperties.CalculationsAggregationsBatchCacheKey}");

                throw new Exception($"Cached calculation aggregations not found for key: {messageProperties.CalculationsAggregationsBatchCacheKey}");
            }

            IEnumerable <string> calculationsToAggregate = messageProperties.CalculationsToAggregate;

            foreach (ProviderResult providerResult in providerResults)
            {
                IEnumerable <CalculationResult> calculationResultsForAggregation = providerResult.CalculationResults.Where(m =>
                                                                                                                           calculationsToAggregate.Contains(VisualBasicTypeGenerator.GenerateIdentifier(m.Calculation.Name), StringComparer.InvariantCultureIgnoreCase));

                foreach (CalculationResult calculationResult in calculationResultsForAggregation)
                {
                    string calculationReferenceName = CalculationTypeGenerator.GenerateIdentifier(calculationResult.Calculation.Name.Trim());

                    string calcNameFromCalcsToAggregate = messageProperties.CalculationsToAggregate.FirstOrDefault(m => string.Equals(m, calculationReferenceName, StringComparison.InvariantCultureIgnoreCase));

                    if (!string.IsNullOrWhiteSpace(calcNameFromCalcsToAggregate) && cachedCalculationAggregationsBatch.ContainsKey(calculationReferenceName))
                    {
                        cachedCalculationAggregationsBatch[calcNameFromCalcsToAggregate].Add(calculationResult.Value.HasValue ? calculationResult.Value.Value : 0);
                    }
                }
            }
        }
        public void GenerateIdentifier_IdentifiersSubstituted(string input, string expected)
        {
            // Act
            string result = CalculationTypeGenerator.GenerateIdentifier(input);

            // Assert
            result
            .Should()
            .Be(expected);
        }
        private async Task <IEnumerable <Job> > CreateGenerateAllocationJobs(JobViewModel parentJob, IEnumerable <IDictionary <string, string> > jobProperties)
        {
            HashSet <string> calculationsToAggregate = new HashSet <string>();

            if (parentJob.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob)
            {
                string calculationAggregatesCacheKeyPrefix = $"{CacheKeys.CalculationAggregations}{parentJob.SpecificationId}";

                await _cacheProvider.RemoveByPatternAsync(calculationAggregatesCacheKeyPrefix);

                IEnumerable <Models.Calcs.Calculation> calculations = await _calculationsRepository.GetCalculationsBySpecificationId(parentJob.SpecificationId);

                foreach (Models.Calcs.Calculation calculation in calculations)
                {
                    IEnumerable <string> aggregateParameters = SourceCodeHelpers.GetCalculationAggregateFunctionParameters(calculation.Current.SourceCode);
                    if (aggregateParameters.IsNullOrEmpty())
                    {
                        continue;
                    }

                    foreach (string aggregateParameter in aggregateParameters)
                    {
                        Models.Calcs.Calculation referencedCalculation = calculations.FirstOrDefault(m => string.Equals(CalculationTypeGenerator.GenerateIdentifier(m.Name.Trim()), aggregateParameter.Trim(), StringComparison.InvariantCultureIgnoreCase));

                        if (referencedCalculation != null)
                        {
                            calculationsToAggregate.Add(aggregateParameter);
                        }
                    }
                }
            }

            IList <JobCreateModel> jobCreateModels = new List <JobCreateModel>();

            Trigger trigger = new Trigger
            {
                EntityId   = parentJob.Id,
                EntityType = nameof(Job),
                Message    = $"Triggered by parent job with id: '{parentJob.Id}"
            };

            int    batchNumber      = 1;
            int    batchCount       = jobProperties.Count();
            string calcsToAggregate = string.Join(",", calculationsToAggregate);

            foreach (IDictionary <string, string> properties in jobProperties)
            {
                properties.Add("batch-number", batchNumber.ToString());
                properties.Add("batch-count", batchCount.ToString());
                properties.Add("calculations-to-aggregate", calcsToAggregate);

                JobCreateModel jobCreateModel = new JobCreateModel
                {
                    InvokerUserDisplayName = parentJob.InvokerUserDisplayName,
                    InvokerUserId          = parentJob.InvokerUserId,
                    JobDefinitionId        = parentJob.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob ? JobConstants.DefinitionNames.CreateAllocationJob : JobConstants.DefinitionNames.GenerateCalculationAggregationsJob,
                    SpecificationId        = parentJob.SpecificationId,
                    Properties             = properties,
                    ParentJobId            = parentJob.Id,
                    Trigger       = trigger,
                    CorrelationId = parentJob.CorrelationId
                };

                batchNumber++;

                jobCreateModels.Add(jobCreateModel);
            }

            return(await _jobsApiClientPolicy.ExecuteAsync(() => _jobsApiClient.CreateJobs(jobCreateModels)));
        }