示例#1
0
        public async Task <IActionResult> UpdateBuildProjectRelationships(string specificationId, DatasetRelationshipSummary relationship)
        {
            if (string.IsNullOrWhiteSpace(specificationId))
            {
                _logger.Error("No specification Id was provided to UpdateBuildProjectRelationships");

                return(new BadRequestObjectResult("Null or empty specification Id provided"));
            }

            if (relationship == null)
            {
                _logger.Error("A null relationship message was provided to UpdateBuildProjectRelationships");

                return(new BadRequestObjectResult("Null relationship provided"));
            }

            BuildProject buildProject = await GetBuildProjectForSpecificationId(specificationId);

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

            buildProject.Build = _sourceCodeService.Compile(buildProject, calculations ?? Enumerable.Empty <Models.Calcs.Calculation>());

            if (!_featureToggle.IsDynamicBuildProjectEnabled())
            {
                await _buildProjectsRepositoryPolicy.ExecuteAsync(() => _buildProjectsRepository.UpdateBuildProject(buildProject));
            }

            await _sourceCodeService.SaveAssembly(buildProject);

            return(new OkObjectResult(buildProject));
        }
示例#2
0
        public async Task IsCalculationNameValid_WhenCalculationDoesNotExist_ThenReturnsOkResult()
        {
            // Arrange
            string specificationId = "spec1";

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new SpecificationSummary {
                Id = specificationId
            });

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(new List <Models.Calcs.Calculation>());

            CalculationService service = CreateCalculationService(specificationRepository: specificationRepository, calculationsRepository: calculationsRepository);

            // Act
            IActionResult result = await service.IsCalculationNameValid(specificationId, "calc1", null);

            // Assert
            result
            .Should()
            .BeOfType <OkResult>();
        }
        public async Task ResetCalculationForFieldDefinitionChanges_GivenNoCalculationsToProcess_LogsAndDoesNotContinue()
        {
            //Arrange
            const string specificationId = "spec-id";

            IEnumerable <DatasetSpecificationRelationshipViewModel> relationships = Enumerable.Empty <DatasetSpecificationRelationshipViewModel>();
            IEnumerable <string> currentFieldDefinitionNames = Enumerable.Empty <string>();

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(Enumerable.Empty <Calculation>());

            CalculationService calculationService = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository);

            //Act
            await calculationService.ResetCalculationForFieldDefinitionChanges(relationships, specificationId, currentFieldDefinitionNames);

            //Assert
            logger
            .Received(1)
            .Information(Arg.Is($"No calculations found to reset for specification id '{specificationId}'"));
        }
示例#4
0
        public async Task IsCalculationNameValid_WhenCalculationDoesNotExist_ThenReturnsOkResult()
        {
            // Arrange
            string specificationId = "spec1";

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, new SpecModel.SpecificationSummary {
                Id = specificationId
            }));

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(new List <Calculation>());

            CalculationService service = CreateCalculationService(specificationsApiClient: specificationsApiClient, calculationsRepository: calculationsRepository);

            // Act
            IActionResult result = await service.IsCalculationNameValid(specificationId, "calc1", null);

            // Assert
            result
            .Should()
            .BeOfType <OkResult>();
        }
示例#5
0
        async public Task GetCalculationSummariesForSpecification_WhenCalculationsNotFoundInCacheAndResponseFromRepositoryIsNull_ThenErrorReturned()
        {
            // Arrange
            const string specificationId = "specid";

            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues(specificationId) }
            });

            HttpRequest request = Substitute.For <HttpRequest>();

            request
            .Query
            .Returns(queryStringValues);

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns((IEnumerable <Calculation>)null);

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <List <CalculationSummaryModel> >($"{CacheKeys.CalculationsSummariesForSpecification}{specificationId}")
            .Returns((List <CalculationSummaryModel>)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, cacheProvider: cacheProvider);

            // Act
            IActionResult result = await service.GetCalculationSummariesForSpecification(request);

            // Assert
            result
            .Should()
            .BeOfType <InternalServerErrorResult>()
            .Which
            .Value
            .Should()
            .Be("Calculations from repository returned null");

            await calculationsRepository
            .Received(1)
            .GetCalculationsBySpecificationId(Arg.Is(specificationId));

            await cacheProvider
            .Received(1)
            .GetAsync <List <CalculationSummaryModel> >($"{CacheKeys.CalculationsSummariesForSpecification}{specificationId}");

            logger
            .Received(1)
            .Warning($"Calculations from repository returned null for specification ID of '{specificationId}'");
        }
示例#6
0
        public async Task <SpecificationCalculationRelationships> GetSpecificationCalculationRelationships(string specificationId)
        {
            Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId));

            ApiResponse <SpecificationSummary> specificationResponse = await _specificationsResilience.ExecuteAsync(() =>
                                                                                                                    _specifications.GetSpecificationSummaryById(specificationId));

            SpecificationSummary specificationSummary = specificationResponse?.Content;

            if (specificationSummary == null)
            {
                throw new ArgumentOutOfRangeException(nameof(specificationId),
                                                      $"No specification with id {specificationId}. Unable to get calculation relationships");
            }

            Calculation[] calculations = (await _calculationsResilience.ExecuteAsync(() =>
                                                                                     _calculations.GetCalculationsBySpecificationId(specificationId)))?.ToArray();

            if (calculations.IsNullOrEmpty())
            {
                throw new ArgumentOutOfRangeException(nameof(specificationId),
                                                      $"No calculations for specification with id {specificationId}. Unable to get calculation relationships");
            }

            IEnumerable <CalculationRelationship> calculationRelationships = _calculationAnalysis.DetermineRelationshipsBetweenCalculations(calculations);

            BuildProject buildProject = await _buildProjectsService.GetBuildProjectForSpecificationId(specificationId);

            IEnumerable <FundingLineCalculationRelationship> fundingLineRelationships = _calculationAnalysis.DetermineRelationshipsBetweenFundingLinesAndCalculations(calculations, buildProject.FundingLines);

            calculationRelationships = calculationRelationships.Concat(fundingLineRelationships.Select(_ => new CalculationRelationship {
                CalculationOneId = _.CalculationOneId, CalculationTwoId = _.CalculationTwoId
            }));

            IEnumerable <DatasetReference> datasetReferences = _datasetReferenceService.GetDatasetRelationShips(calculations, buildProject.DatasetRelationships);

            return(new SpecificationCalculationRelationships
            {
                Specification = _mapper.Map <Specification>(specificationSummary),
                Calculations = _mapper.Map <IEnumerable <GraphCalculation> >(calculations),
                FundingLines = _mapper.Map <IEnumerable <GraphFundingLine> >(buildProject.FundingLines?.Values.SelectMany(_ => _.FundingLines)),
                CalculationRelationships = calculationRelationships,
                FundingLineRelationships = fundingLineRelationships,
                CalculationDataFieldRelationships = datasetReferences.SelectMany(_ => _.Calculations.Select(calc => new CalculationDataFieldRelationship {
                    Calculation = calc, DataField = _.DataField
                })).Distinct(),
                DatasetDataFieldRelationships = datasetReferences.Select(_ => new DatasetDataFieldRelationship {
                    Dataset = _.Dataset, DataField = _.DataField
                }),
                DatasetDatasetDefinitionRelationships = datasetReferences.Select(_ => new DatasetDatasetDefinitionRelationship {
                    Dataset = _.Dataset, DatasetDefinition = _.DatasetDefinition
                })
            });
        }
        public void ResetCalculationForFieldDefinitionChanges_GivenCalculationRequiresResetButUpdatingCalculationFails_ThrowsException()
        {
            //Arrange
            const string specificationId = "spec-id";

            IEnumerable <DatasetSpecificationRelationshipViewModel> relationships = new[]
            {
                new DatasetSpecificationRelationshipViewModel
                {
                    Name = "Test Name"
                }
            };

            IEnumerable <string> currentFieldDefinitionNames = new[]
            {
                "Test Field"
            };

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calculations = new[]
            {
                new Calculation
                {
                    Current = new CalculationVersion
                    {
                        SourceCode = "return Datasets.TestName.TestField"
                    }
                }
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);
            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.BadRequest);

            CalculationService calculationService = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository);

            //Act
            Func <Task> test = async() => await calculationService.ResetCalculationForFieldDefinitionChanges(relationships, specificationId, currentFieldDefinitionNames);

            //Assert
            test
            .Should()
            .ThrowExactly <InvalidOperationException>()
            .Which
            .Message
            .Should()
            .Be($"Update calculation returned status code 'BadRequest' instead of OK");
        }
        public async Task <IActionResult> UpdateBuildProjectRelationships(HttpRequest request)
        {
            request.Query.TryGetValue("specificationId", out Microsoft.Extensions.Primitives.StringValues specId);

            string specificationId = specId.FirstOrDefault();

            if (string.IsNullOrWhiteSpace(specificationId))
            {
                _logger.Error("No specification Id was provided to UpdateBuildProjectRelationships");

                return(new BadRequestObjectResult("Null or empty specification Id provided"));
            }

            string json = await request.GetRawBodyStringAsync();

            DatasetRelationshipSummary relationship = JsonConvert.DeserializeObject <DatasetRelationshipSummary>(json);

            if (relationship == null)
            {
                _logger.Error("A null relationship message was provided to UpdateBuildProjectRelationships");

                return(new BadRequestObjectResult("Null relationship provided"));
            }

            BuildProject buildProject = await GetBuildProjectForSpecificationId(specificationId);

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

            buildProject.Build = _sourceCodeService.Compile(buildProject, calculations ?? Enumerable.Empty <Models.Calcs.Calculation>());

            if (!_featureToggle.IsDynamicBuildProjectEnabled())
            {
                await _buildProjectsRepositoryPolicy.ExecuteAsync(() => _buildProjectsRepository.UpdateBuildProject(buildProject));
            }

            await _sourceCodeService.SaveAssembly(buildProject);

            return(new OkObjectResult(buildProject));
        }
示例#9
0
        public override async Task Process(Message message)
        {
            Guard.ArgumentNotNull(message, nameof(message));

            string specificationId = UserPropertyFrom(message, "specification-id");

            IEnumerable <Calculation> calculations =
                (await _calculationRepositoryPolicy.ExecuteAsync(() =>
                                                                 _calculationsRepository.GetCalculationsBySpecificationId(specificationId)))
                .ToArraySafe();

            if (calculations.IsNullOrEmpty())
            {
                string calcNotFoundMessage = $"No calculations found for specification id: {specificationId}";

                _logger.Information(calcNotFoundMessage);

                return;
            }

            foreach (Calculation calculation in calculations)
            {
                calculation.Current.PublishStatus = Models.Versioning.PublishStatus.Approved;
            }

            ApiResponse <SpecModel.SpecificationSummary> specificationApiResponse =
                await _specificationsApiClientPolicy.ExecuteAsync(() => _specificationsApiClient.GetSpecificationSummaryById(specificationId));

            if (!specificationApiResponse.StatusCode.IsSuccess() || specificationApiResponse.Content == null)
            {
                throw new NonRetriableException("Specification not found");
            }

            SpecModel.SpecificationSummary specificationSummary = specificationApiResponse.Content;

            await _calculationRepositoryPolicy.ExecuteAsync(() => _calculationsRepository.UpdateCalculations(calculations));

            await UpdateSearch(calculations, specificationSummary);

            IEnumerable <Task> tasks = calculations.Select(_ => UpdateCalculationInCache(_.ToResponseModel()));

            await TaskHelper.WhenAllAndThrow(tasks.ToArraySafe());

            await UpdateCalculationsInCache(specificationSummary);
        }
示例#10
0
        public async Task IsCalculationNameValid_WhenSameCalculation_ThenReturnsOkResult()
        {
            // Arrange
            string specificationId = "spec1";
            string calcName        = "calc1";
            string calcSpecId      = "calc-1";

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, new SpecModel.SpecificationSummary {
                Id = specificationId
            }));

            List <Calculation> existingCalcs = new List <Calculation>
            {
                new Calculation
                {
                    Current = new CalculationVersion
                    {
                        Name           = calcName,
                        SourceCodeName = calcName
                    },

                    Id = "calc-1"
                }
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(existingCalcs);

            CalculationService service = CreateCalculationService(specificationsApiClient: specificationsApiClient, calculationsRepository: calculationsRepository);

            // Act
            IActionResult result = await service.IsCalculationNameValid(specificationId, calcName, calcSpecId);

            // Assert
            result
            .Should()
            .BeOfType <OkResult>();
        }
示例#11
0
        public async Task IsCalculationNameValid_WhenSameCalculation_ThenReturnsOkResult()
        {
            // Arrange
            string specificationId = "spec1";
            string calcName        = "calc1";
            string calcSpecId      = "calc-spec-id-1";

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new SpecificationSummary {
                Id = specificationId
            });

            List <Models.Calcs.Calculation> existingCalcs = new List <Models.Calcs.Calculation>
            {
                new Models.Calcs.Calculation
                {
                    Name                     = calcName,
                    SourceCodeName           = calcName,
                    Id                       = "calc-1",
                    CalculationSpecification = new Common.Models.Reference {
                        Id = calcSpecId
                    }
                }
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(existingCalcs);

            CalculationService service = CreateCalculationService(specificationRepository: specificationRepository, calculationsRepository: calculationsRepository);

            // Act
            IActionResult result = await service.IsCalculationNameValid(specificationId, calcName, calcSpecId);

            // Assert
            result
            .Should()
            .BeOfType <OkResult>();
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedFundingPeriodsButCalcculationsCouldNotBeFound_LogsAndReturns()
        {
            //Arrange
            const string specificationId = "spec-id";

            Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new Models.Specs.SpecificationVersion {
                    FundingPeriod = new Reference {
                        Id = "fp2"
                    }
                },
                Previous = new Models.Specs.SpecificationVersion {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns((IEnumerable <Calculation>)null);

            CalculationService service = CreateCalculationService(calculationsRepository, logger);

            //Act
            await service.UpdateCalculationsForSpecification(message);

            //Assert
            logger
            .Received(1)
            .Information(Arg.Is($"No calculations found for specification id: {specificationId}"));
        }
        public async Task CreateCalculation_GivenValidCalculationWithNullFundingStream_AndSavesLogs()
        {
            //Arrange
            Calculation calculation = CreateCalculation();

            calculation.FundingStream = null;

            IEnumerable <Calculation> calculations = new[]
            {
                calculation
            };

            IEnumerable <Models.Specs.Calculation> calculationSpecifications = new[]
            {
                new Models.Specs.Calculation
                {
                    Id = calculation.CalculationSpecification.Id
                }
            };

            string json = JsonConvert.SerializeObject(calculation);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ICalculationsRepository repository = CreateCalculationsRepository();

            repository
            .CreateDraftCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.Created);

            repository
            .GetCalculationsBySpecificationId(Arg.Is("any-spec-id"))
            .Returns(calculations);

            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary()
            {
                Id   = calculation.SpecificationId,
                Name = "Test Spec Name",
            };

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(specificationSummary);

            specificationRepository
            .GetCalculationSpecificationsForSpecification(Arg.Is(calculation.SpecificationId))
            .Returns(calculationSpecifications);

            ILogger logger = CreateLogger();

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            Build build = new Build
            {
                SourceFiles = new List <SourceFile> {
                    new SourceFile()
                }
            };

            ISourceCodeService sourceCodeService = CreateSourceCodeService();

            sourceCodeService
            .Compile(Arg.Any <BuildProject>(), Arg.Any <IEnumerable <Models.Calcs.Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(build);

            CalculationService service = CreateCalculationService(
                calculationsRepository: repository,
                logger: logger, searchRepository:
                searchRepository,
                specificationRepository: specificationRepository,
                sourceCodeService: sourceCodeService);

            //Act
            await service.CreateCalculation(message);

            //Assert
            logger
            .Received(1)
            .Information($"Calculation with id: {calculation.Id} was successfully saved to Cosmos Db");

            await
            repository
            .Received(1)
            .CreateDraftCalculation(Arg.Is <Calculation>(m =>
                                                         m.Id == CalculationId &&
                                                         m.Current.PublishStatus == PublishStatus.Draft &&
                                                         m.Current.Author.Id == UserId &&
                                                         m.Current.Author.Name == Username &&
                                                         m.Current.Date.Date == DateTimeOffset.Now.Date &&
                                                         m.Current.Version == 1 &&
                                                         m.Current.DecimalPlaces == 6
                                                         ));

            await
            searchRepository
            .Received(1)
            .Index(Arg.Is <List <CalculationIndex> >(
                       m => m.First().Id == CalculationId &&
                       m.First().Name == "Test Calc Name" &&
                       m.First().CalculationSpecificationId == "any-calc-id" &&
                       m.First().CalculationSpecificationName == "Test Calc Name" &&
                       m.First().SpecificationId == "any-spec-id" &&
                       m.First().SpecificationName == "Test Spec Name" &&
                       m.First().FundingPeriodId == "18/19" &&
                       m.First().FundingPeriodName == "2018/2019" &&
                       m.First().FundingStreamId == string.Empty &&
                       m.First().FundingStreamName == "No funding stream set" &&
                       m.First().AllocationLineId == "test-alloc-id" &&
                       m.First().AllocationLineName == "test-alloc-name" &&
                       m.First().PolicySpecificationIds.First() == "policy-id" &&
                       m.First().PolicySpecificationNames.First() == "policy-name"
                       ));
        }
示例#14
0
        async public Task GetCurrentCalculationsForSpecification_WhenCalculationsNotFoundInCache_ThenCalculationsReturnedFromRepository()
        {
            //Arrange
            const string specificationId = "specid";

            DateTimeOffset calc1DateTime = DateTimeOffset.Now;
            DateTimeOffset calc2DateTime = DateTimeOffset.Now;

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation()
                {
                    Id      = "one",
                    Current = new CalculationVersion()
                    {
                        SourceCode      = "Return 10",
                        PublishStatus   = PublishStatus.Draft,
                        Author          = new Reference("userId", "User Name"),
                        Version         = 1,
                        Date            = calc1DateTime,
                        Name            = "Calculation Name",
                        CalculationType = CalculationType.Template,
                    },
                    SpecificationId = specificationId,
                },
                new Calculation()
                {
                    Id      = "two",
                    Current = new CalculationVersion()
                    {
                        SourceCode      = "Return 50",
                        PublishStatus   = PublishStatus.Approved,
                        Author          = new Reference("userId", "User Name"),
                        Version         = 5,
                        Date            = calc2DateTime,
                        Name            = "Calculation Name Two",
                        CalculationType = CalculationType.Template,
                    },
                    SpecificationId = specificationId,
                }
            };

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <List <CalculationResponseModel> >($"{CacheKeys.CurrentCalculationsForSpecification}{specificationId}")
            .Returns((List <CalculationResponseModel>)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, cacheProvider: cacheProvider);

            //Act
            IActionResult result = await service.GetCurrentCalculationsForSpecification(specificationId);

            //Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeAssignableTo <IEnumerable <CalculationResponseModel> >()
            .Which
            .Should()
            .Contain(m => m.Id == "one" && m.Name == "Calculation Name" && m.SourceCode == "Return 10" && m.CalculationType == CalculationType.Template && m.Version == 1 && m.LastUpdated == calc1DateTime && m.SpecificationId == specificationId && m.PublishStatus == PublishStatus.Draft)
            .And.Contain(m => m.Id == "two" && m.Name == "Calculation Name Two" && m.SourceCode == "Return 50" && m.CalculationType == CalculationType.Template && m.Version == 5 && m.LastUpdated == calc2DateTime && m.SpecificationId == specificationId && m.PublishStatus == PublishStatus.Approved);

            await calculationsRepository
            .Received(1)
            .GetCalculationsBySpecificationId(Arg.Is(specificationId));

            await cacheProvider
            .Received(1)
            .GetAsync <List <CalculationResponseModel> >($"{CacheKeys.CurrentCalculationsForSpecification}{specificationId}");
        }
示例#15
0
        async public Task GetCalculationSummariesForSpecification_WhenCalculationsNotFoundInCache_ThenCalculationsReturnedFromRepository()
        {
            // Arrange
            const string specificationId = "specid";

            DateTimeOffset calc1DateTime = DateTimeOffset.Now;
            DateTimeOffset calc2DateTime = DateTimeOffset.Now;

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation()
                {
                    Id      = "one",
                    Name    = "Calculation Name",
                    Current = new CalculationVersion()
                    {
                        SourceCode    = "Return 10",
                        PublishStatus = PublishStatus.Draft,
                        Author        = new Reference("userId", "User Name"),
                        Version       = 1,
                        Date          = calc1DateTime,
                    },
                    CalculationSpecification = new Reference("specId", "Calculation Specification ID"),
                    CalculationType          = CalculationType.Funding,
                    FundingPeriod            = new Reference("fp1", "Funding Period 1"),
                    SpecificationId          = specificationId,
                },
                new Calculation()
                {
                    Id      = "two",
                    Name    = "Calculation Name Two",
                    Current = new CalculationVersion()
                    {
                        SourceCode    = "Return 50",
                        PublishStatus = PublishStatus.Published,
                        Author        = new Reference("userId", "User Name"),
                        Version       = 5,
                        Date          = calc2DateTime,
                    },
                    CalculationSpecification = new Reference("specId", "Calculation Specification ID"),
                    CalculationType          = CalculationType.Number,
                    FundingPeriod            = new Reference("fp2", "Funding Period Two"),
                    SpecificationId          = specificationId,
                }
            };

            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues(specificationId) }
            });

            HttpRequest request = Substitute.For <HttpRequest>();

            request
            .Query
            .Returns(queryStringValues);

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <List <CalculationSummaryModel> >($"{CacheKeys.CalculationsSummariesForSpecification}{specificationId}")
            .Returns((List <CalculationSummaryModel>)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, cacheProvider: cacheProvider);

            // Act
            IActionResult result = await service.GetCalculationSummariesForSpecification(request);

            // Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeAssignableTo <IEnumerable <CalculationSummaryModel> >()
            .Which
            .ShouldAllBeEquivalentTo(new List <CalculationSummaryModel>()
            {
                new CalculationSummaryModel()
                {
                    Id              = "one",
                    Name            = "Calculation Name",
                    CalculationType = CalculationType.Funding
                },
                new CalculationSummaryModel()
                {
                    Id              = "two",
                    Name            = "Calculation Name Two",
                    CalculationType = CalculationType.Number,
                }
            });

            await calculationsRepository
            .Received(1)
            .GetCalculationsBySpecificationId(Arg.Is(specificationId));

            await cacheProvider
            .Received(1)
            .GetAsync <List <CalculationSummaryModel> >($"{CacheKeys.CalculationsSummariesForSpecification}{specificationId}");
        }
        public async Task ResetCalculationForFieldDefinitionChanges_GivenCalculationRequiresReset_UpdatesCalculationsAndDeletesAssembly()
        {
            //Arrange
            const string specificationId = "spec-id";

            IEnumerable <DatasetSpecificationRelationshipViewModel> relationships = new[]
            {
                new DatasetSpecificationRelationshipViewModel
                {
                    Name = "Test Name"
                }
            };

            IEnumerable <string> currentFieldDefinitionNames = new[]
            {
                "Test Field"
            };

            ILogger logger = CreateLogger();

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = "return Datasets.TestName.TestField",
                Date       = DateTimeOffset.Now
            };

            IEnumerable <Calculation> calculations = new[]
            {
                new Calculation
                {
                    Current                  = calculationVersion,
                    SpecificationId          = specificationId,
                    CalculationSpecification = new Reference("calc-spac-id", "calc spec name"),
                    FundingPeriod            = new Reference("fp1", "fp 1"),
                    FundingStream            = new Reference("fs1", "fs 1"),
                    Policies                 = new List <Reference> {
                        new Reference {
                            Id = "policy-1", Name = "policy 1"
                        }
                    }
                }
            };

            IEnumerable <Models.Specs.Calculation> calculationSpecifications = new[]
            {
                new Models.Specs.Calculation
                {
                    Id = "calc-spec-id"
                }
            };

            BuildProject buildProject = new BuildProject();

            Build build = new Build
            {
                SourceFiles = new List <SourceFile>()
            };

            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);
            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetCalculationSpecificationsForSpecification(Arg.Is(specificationId))
            .Returns(calculationSpecifications);

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(specificationSummary);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            ISourceCodeService sourceCodeService = CreateSourceCodeService();

            sourceCodeService
            .Compile(Arg.Is(buildProject), Arg.Any <IEnumerable <Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(build);

            IVersionRepository <CalculationVersion> calculationVersionRepository = CreateCalculationVersionRepository();

            calculationVersionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            ICacheProvider cacheProvider = CreateCacheProvider();

            CalculationService calculationService = CreateCalculationService(
                logger: logger,
                calculationsRepository: calculationsRepository,
                specificationRepository: specificationRepository,
                buildProjectsService: buildProjectsService,
                sourceCodeService: sourceCodeService,
                calculationVersionRepository: calculationVersionRepository,
                cacheProvider: cacheProvider);

            //Act
            await calculationService.ResetCalculationForFieldDefinitionChanges(relationships, specificationId, currentFieldDefinitionNames);

            //Assert
            await
            sourceCodeService
            .Received(1)
            .DeleteAssembly(Arg.Is(specificationId));

            await
            cacheProvider
            .Received(1)
            .RemoveAsync <List <DatasetSchemaRelationshipModel> >(Arg.Is($"{CacheKeys.DatasetRelationshipFieldsForSpecification}{specificationId}"));
        }
示例#17
0
        public async Task UpdateCalculationCodeOnCalculationChange_WhenCalculationsFoundReferencingCalculationToBeUpdated_ThenSourceCodeUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationsApiClient specificationsApiClient          = CreateSpecificationsApiClient();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();
            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();
            ISourceCodeService    sourceCodeService    = CreateSourceCodeService();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationsApiClient: specificationsApiClient,
                                                                  calculationVersionRepository: versionRepository,
                                                                  buildProjectsService: buildProjectsService,
                                                                  sourceCodeService: sourceCodeService);

            const string specificationId    = "specId";
            const string calculationId      = "updatedCalc";
            const string originalCodeUpdate = @"Dim test as OriginalNameOptions? 
                                                OriginalNameOptions.enumName 
                                                Return Calculations.OriginalName()";
            const string newCodeUpdated     = @"Dim test as CalculationToUpdateOptions? 
                                                CalculationToUpdateOptions.enumName 
                                                Return Calculations.CalculationToUpdate()";
            const string originalCodeIgnore = "Return 10";
            const string fundingStreamId    = "fundingstreamid";

            CalculationVersionComparisonModel comparison = new CalculationVersionComparisonModel()
            {
                CalculationId       = calculationId,
                CurrentName         = "Calculation To Update",
                PreviousName        = "Original Name",
                SpecificationId     = specificationId,
                CalculationDataType = CalculationDataType.Enum,
                Namespace           = "Calculations"
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>
            {
                new Calculation
                {
                    Id = calculationId,
                    SpecificationId = specificationId,
                    FundingStreamId = fundingStreamId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = originalCodeIgnore,
                        Name            = "Calculation to Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description",
                        DataType        = CalculationDataType.Enum
                    }
                },
                new Calculation
                {
                    Id = "referenceCalc",
                    SpecificationId = specificationId,
                    FundingStreamId = fundingStreamId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = originalCodeUpdate,
                        Name            = "Calling Calculation To Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description"
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            SpecModel.SpecificationSummary specification = new SpecModel.SpecificationSummary()
            {
                Id             = specificationId,
                Name           = "Specification Name",
                FundingStreams = new [] { new Reference(fundingStreamId, "fundingStreamName"), }
            };

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specification));

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = newCodeUpdated,
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Is <CalculationVersion>(_ => _.SourceCode == newCodeUpdated), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            buildProjectsService
            .GetBuildProjectForSpecificationId(specificationId)
            .Returns(new BuildProject());

            sourceCodeService
            .Compile(Arg.Any <BuildProject>(), Arg.Any <IEnumerable <Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(new Build());

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(1);

            Calculation calculation = updatedCalculations.Single();

            calculation.Current.SourceCode
            .Should()
            .Be(newCodeUpdated);


            calculation.Current.Version
            .Should()
            .Be(2);

            calculation.Id
            .Should()
            .Be("referenceCalc");
        }
示例#18
0
        public async Task UpdateCalculationCodeOnCalculationChange_WhenNoCalculationsFoundReferencingCalculationToBeUpdated_ThenNoCalculationsUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationsApiClient specificationsApiClient          = CreateSpecificationsApiClient();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationsApiClient: specificationsApiClient,
                                                                  calculationVersionRepository: versionRepository);

            const string specificationId = "specId";
            const string calculationId   = "updatedCalc";

            CalculationVersionComparisonModel comparison = new CalculationVersionComparisonModel()
            {
                CalculationId   = calculationId,
                CurrentName     = "Calculation To Update",
                PreviousName    = "Original Name",
                SpecificationId = specificationId,
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation
                {
                    Id = calculationId,
                    SpecificationId = specificationId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = "Return 10",
                        Name            = "Calculation to Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description"
                    }
                },
                new Calculation
                {
                    Id = "referenceCalc",
                    SpecificationId = specificationId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = "Return 50",
                        Name            = "Calling Calculation To Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description",
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            SpecModel.SpecificationSummary specification = new SpecModel.SpecificationSummary()
            {
                Id   = specificationId,
                Name = "Specification Name",
            };

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specification));

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = "Return CalculationToUpdate()",
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(0);
        }
示例#19
0
        public async Task <IActionResult> Compile(PreviewRequest previewRequest)
        {
            if (previewRequest == null)
            {
                _logger.Error("A null preview request was supplied");

                return(new BadRequestObjectResult("A null preview request was provided"));
            }

            FluentValidation.Results.ValidationResult validationResult = await _previewRequestValidator.ValidateAsync(previewRequest);

            if (!validationResult.IsValid)
            {
                string errors = string.Join(";", validationResult.Errors.Select(m => m.ErrorMessage).ToArraySafe());

                _logger.Warning($"The preview request failed to validate with errors: {errors}");

                return(new BadRequestObjectResult("The preview request failed to validate"));
            }

            Task <IEnumerable <Calculation> > calculationsTask = _calculationsRepository.GetCalculationsBySpecificationId(previewRequest.SpecificationId);

            Task <BuildProject>    buildProjectTask    = _buildProjectsService.GetBuildProjectForSpecificationId(previewRequest.SpecificationId);
            Task <CompilerOptions> compilerOptionsTask = _calculationsRepository.GetCompilerOptions(previewRequest.SpecificationId);

            await TaskHelper.WhenAllAndThrow(calculationsTask, buildProjectTask, compilerOptionsTask);

            BuildProject buildProject = buildProjectTask.Result;

            if (buildProject == null)
            {
                _logger.Warning($"Build project for specification '{previewRequest.SpecificationId}' could not be found");

                return(new PreconditionFailedResult($"Build project for specification '{previewRequest.SpecificationId}' could not be found"));
            }

            List <Calculation> allSpecCalculations = new List <Calculation>(calculationsTask.Result);

            Calculation calculationToPreview = allSpecCalculations.SingleOrDefault(m => m.Id == previewRequest.CalculationId);

            if (calculationToPreview == null)
            {
                calculationToPreview = GenerateTemporaryCalculationForPreview(previewRequest);

                allSpecCalculations.Add(calculationToPreview);
            }
            else
            {
                ApplyChangesToCurrentCalculationForPreview(previewRequest, calculationToPreview);
            }

            Build buildForDatasetAggregationCheck = await CheckDatasetValidAggregations(previewRequest);

            if (buildForDatasetAggregationCheck != null && buildForDatasetAggregationCheck.CompilerMessages.Any(m => m.Severity == Severity.Error))
            {
                PreviewResponse response = new PreviewResponse
                {
                    Calculation    = calculationToPreview.ToResponseModel(),
                    CompilerOutput = buildForDatasetAggregationCheck
                };

                return(new OkObjectResult(response));
            }

            CompilerOptions compilerOptions = compilerOptionsTask.Result ?? new CompilerOptions {
                SpecificationId = buildProject.SpecificationId
            };

            return(await GenerateAndCompile(buildProject, calculationToPreview, allSpecCalculations, compilerOptions, previewRequest));
        }
示例#20
0
        public async Task ProcessChanges_GivenChangeModelWithAggregableFieldChanges_CallsResetCalculationForFieldDefinitionChanges(FieldDefinitionChangeType fieldDefinitionChangeType)
        {
            //Arrange
            string definitionId    = "df-id-1";
            string specificationId = "spec-1";

            IEnumerable <Calculation> calculations = new[]
            {
                new Calculation
                {
                    Current = new CalculationVersion
                    {
                        SourceCode = "return Sum(Datasets.TestRelationship.TestField1)"
                    }
                }
            };

            DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges
            {
                Id = definitionId,
            };

            FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges
            {
                FieldDefinition = new FieldDefinition
                {
                    Id = "field1"
                },
                ExistingFieldDefinition = new FieldDefinition {
                    Name = "test field 1"
                }
            };

            fieldDefinitionChanges.ChangeTypes.Add(fieldDefinitionChangeType);

            TableDefinitionChanges tableDefinitionChanges = new TableDefinitionChanges();

            tableDefinitionChanges.FieldChanges.Add(fieldDefinitionChanges);

            datasetDefinitionChanges.TableDefinitionChanges.Add(tableDefinitionChanges);

            string json = JsonConvert.SerializeObject(datasetDefinitionChanges);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            ILogger logger = CreateLogger();

            IEnumerable <string> relationshipSpecificationIds = new[] { specificationId };

            IEnumerable <Common.ApiClient.DataSets.Models.DatasetSpecificationRelationshipViewModel> relationshipViewModels = new[]
            {
                new Common.ApiClient.DataSets.Models.DatasetSpecificationRelationshipViewModel
                {
                    Name = "Test Relationship"
                }
            };

            IEnumerable <DatasetSpecificationRelationshipViewModel> relationshipViewModel = new[]
            {
                new DatasetSpecificationRelationshipViewModel
                {
                    Name = "Test Relationship"
                }
            };

            IDatasetsApiClient datasetRepository = CreateDatasetRepository();

            datasetRepository
            .GetSpecificationIdsForRelationshipDefinitionId(Arg.Is(definitionId))
            .Returns(new ApiResponse <IEnumerable <string> >(HttpStatusCode.OK, relationshipSpecificationIds));
            datasetRepository
            .GetCurrentRelationshipsBySpecificationIdAndDatasetDefinitionId(Arg.Is(specificationId), Arg.Is(definitionId))
            .Returns(new ApiResponse <IEnumerable <Common.ApiClient.DataSets.Models.DatasetSpecificationRelationshipViewModel> >(HttpStatusCode.OK, relationshipViewModels));


            ICalculationService calculationService = CreateCalculationService();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            IMapper mapper = CreateMapper();

            DatasetDefinitionFieldChangesProcessor processor = CreateProcessor(
                logger: logger,
                datasetRepository: datasetRepository,
                calculationService: calculationService,
                calculationsRepository: calculationsRepository,
                mapper: mapper);

            //Act
            await processor.Run(message);

            //Assert
            await
            calculationService
            .Received(1)
            .ResetCalculationForFieldDefinitionChanges(Arg.Is <IEnumerable <Models.Datasets.ViewModels.DatasetSpecificationRelationshipViewModel> >(_ => _.First().Id == relationshipViewModel.First().Id), Arg.Is(specificationId), Arg.Is <IEnumerable <string> >(m => m.First() == "test field 1"));
        }
        private async Task ProcessFieldChanges(string datasetDefinitionId, IEnumerable <FieldDefinitionChanges> fieldChanges, IEnumerable <string> relationshipSpecificationIds)
        {
            Guard.IsNullOrWhiteSpace(datasetDefinitionId, nameof(datasetDefinitionId));
            Guard.ArgumentNotNull(fieldChanges, nameof(fieldChanges));
            Guard.ArgumentNotNull(relationshipSpecificationIds, nameof(relationshipSpecificationIds));

            IEnumerable <IGrouping <string, FieldDefinitionChanges> > groupedFieldChanges = fieldChanges.GroupBy(f => f.FieldDefinition.Id);

            IList <FieldDefinitionChanges> fieldDefinitionChanges = new List <FieldDefinitionChanges>();

            bool shouldResetCalculation = false;

            foreach (IGrouping <string, FieldDefinitionChanges> grouping in groupedFieldChanges)
            {
                FieldDefinitionChanges fieldDefinitionChange = grouping.FirstOrDefault(m => m.ChangeTypes.Any(
                                                                                           c => c == FieldDefinitionChangeType.FieldName) || m.RequiresRemap);

                if (fieldDefinitionChange != null)
                {
                    fieldDefinitionChanges.Add(fieldDefinitionChange);
                }

                shouldResetCalculation = true;
            }

            if (!shouldResetCalculation)
            {
                return;
            }

            foreach (string specificationId in relationshipSpecificationIds)
            {
                IEnumerable <DatasetSpecificationRelationshipViewModel> relationships = await _datasetRepositoryPolicy.ExecuteAsync(() => _datasetRepository.GetCurrentRelationshipsBySpecificationIdAndDatasetDefinitionId(specificationId, datasetDefinitionId));

                if (relationships.IsNullOrEmpty())
                {
                    throw new RetriableException($"No relationships found for specificationId '{specificationId}' and dataset definition id '{datasetDefinitionId}'");
                }

                IEnumerable <Calculation> calculations = (await _calculationsRepositoryPolicy.ExecuteAsync(() => _calculationsRepository.GetCalculationsBySpecificationId(specificationId))).ToList();

                IEnumerable <string> aggregateParameters = calculations.SelectMany(m => SourceCodeHelpers.GetDatasetAggregateFunctionParameters(m.Current.SourceCode));

                HashSet <string> fieldNames = new HashSet <string>();

                foreach (FieldDefinitionChanges changes in fieldDefinitionChanges)
                {
                    //Check if only aggregable changes
                    if (!changes.ChangeTypes.Contains(FieldDefinitionChangeType.FieldType) && !changes.ChangeTypes.Contains(FieldDefinitionChangeType.FieldName))
                    {
                        foreach (DatasetSpecificationRelationshipViewModel datasetSpecificationRelationshipViewModel in relationships)
                        {
                            if (aggregateParameters.Contains($"Datasets.{VisualBasicTypeGenerator.GenerateIdentifier(datasetSpecificationRelationshipViewModel.Name)}.{VisualBasicTypeGenerator.GenerateIdentifier(changes.ExistingFieldDefinition.Name)}"))
                            {
                                fieldNames.Add(changes.ExistingFieldDefinition.Name);
                            }
                        }
                    }
                    else
                    {
                        fieldNames.Add(changes.ExistingFieldDefinition.Name);
                    }
                }

                if (fieldNames.Any())
                {
                    await _calculationService.ResetCalculationForFieldDefinitionChanges(relationships, specificationId, fieldNames);
                }
            }
        }
示例#22
0
        public async Task UpdateCalculationCodeOnCalculationSpecificationChange_WhenNoCalculationsFoundReferencingCalculationToBeUpdated_ThenNoCalculationsUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationRepository specificationRepository          = CreateSpecificationRepository();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();
            ICalculationCodeReferenceUpdate         calculationCodeReferenceUpdate = FakeCalculationCodeReferenceUpdate();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationRepository: specificationRepository,
                                                                  calculationVersionRepository: versionRepository,
                                                                  calculationCodeReferenceUpdate: calculationCodeReferenceUpdate);

            const string specificationId = "specId";
            const string calculationId   = "updatedCalc";

            Models.Specs.CalculationVersionComparisonModel comparison = new Models.Specs.CalculationVersionComparisonModel()
            {
                CalculationId = calculationId,
                Current       = new Models.Specs.Calculation
                {
                    Id              = "calcSpec1",
                    Name            = "Calculation to update",
                    CalculationType = Models.Specs.CalculationType.Funding,
                },
                Previous = new Models.Specs.Calculation
                {
                    Id              = "calcSpec1",
                    Name            = "Original Name",
                    CalculationType = Models.Specs.CalculationType.Funding,
                },
                SpecificationId = specificationId,
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation
                {
                    Id                       = calculationId,
                    Name                     = "Calculation to Update",
                    SpecificationId          = specificationId,
                    FundingPeriod            = new Reference("fp1", "Funding Period"),
                    CalculationSpecification = new Reference("calcSpec1", "Calculation to Update"),
                    CalculationType          = CalculationType.Funding,
                    Description              = "Calculation Description",
                    BuildProjectId           = "bpC1",
                    Policies                 = new List <Reference>(),
                    Current                  = new CalculationVersion
                    {
                        SourceCode    = "Return 10",
                        DecimalPlaces = 6,
                    }
                },
                new Calculation
                {
                    Id                       = "referenceCalc",
                    Name                     = "Calling Calculation To Update",
                    SpecificationId          = specificationId,
                    FundingPeriod            = new Reference("fp1", "Funding Period"),
                    CalculationSpecification = new Reference("calcSpec1", "Calculation to Update"),
                    CalculationType          = CalculationType.Funding,
                    Description              = "Calculation Description",
                    BuildProjectId           = "bpC1",
                    Policies                 = new List <Reference>(),
                    Current                  = new CalculationVersion
                    {
                        SourceCode    = "Return 50",
                        DecimalPlaces = 6,
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            Models.Specs.SpecificationSummary specification = new Models.Specs.SpecificationSummary()
            {
                Id   = specificationId,
                Name = "Specification Name",
            };

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(specification);

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = "Return CalculationToUpdate()",
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationSpecificationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(0);

            calculationCodeReferenceUpdate
            .Received(calculations.Count)
            .ReplaceSourceCodeReferences(Arg.Any <string>(),
                                         VisualBasicTypeGenerator.GenerateIdentifier(comparison.Previous.Name),
                                         VisualBasicTypeGenerator.GenerateIdentifier(comparison.Current.Name));

            foreach (Calculation calculation in calculations)
            {
                calculationCodeReferenceUpdate
                .Received(1)
                .ReplaceSourceCodeReferences(calculation.Current.SourceCode,
                                             VisualBasicTypeGenerator.GenerateIdentifier(comparison.Previous.Name),
                                             VisualBasicTypeGenerator.GenerateIdentifier(comparison.Current.Name));
            }
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameButCreatingJobReturnsNull_LogsError()
        {
            // Arrange
            const string specificationId = "spec-id";

            Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name     = "any-name",
                    Policies = new[] { new Models.Specs.Policy {
                                           Id = "pol-id", Name = "policy2"
                                       } }
                },
                Previous = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Policies = new[] { new Models.Specs.Policy {
                                           Id = "pol-id", Name = "policy1"
                                       } }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Name            = "any name",
                    Id = "any-id",
                    CalculationSpecification = new Reference("any name", "any-id"),
                    FundingPeriod            = new Reference("18/19", "2018/2019"),
                    CalculationType          = CalculationType.Number,
                    FundingStream            = new Reference("fp1", "fs1-111"),
                    Current = new CalculationVersion
                    {
                        Author        = new Reference(UserId, Username),
                        Date          = DateTimeOffset.Now,
                        PublishStatus = PublishStatus.Draft,
                        SourceCode    = "source code",
                        Version       = 1
                    },
                    Policies = new List <Reference> {
                        new Reference {
                            Id = "pol-id", Name = "policy1"
                        }
                    }
                }
            };

            BuildProject buildProject = new BuildProject
            {
                Id = "build-project-1",
                SpecificationId = specificationId
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            IJobsApiClient jobsApiClient = CreateJobsApiClient();

            jobsApiClient
            .CreateJob(Arg.Any <JobCreateModel>())
            .Returns((Job)null);

            CalculationService service = CreateCalculationService(
                calculationsRepository,
                logger,
                buildProjectsService: buildProjectsService,
                searchRepository: searchRepository,
                jobsApiClient: jobsApiClient);

            // Act
            Func <Task> test = async() => await service.UpdateCalculationsForSpecification(message);

            // Assert
            test
            .Should()
            .ThrowExactly <RetriableException>()
            .Which
            .Message
            .Should()
            .Be($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'");

            await
            jobsApiClient
            .Received(1)
            .CreateJob(Arg.Is <JobCreateModel>(
                           m =>
                           m.InvokerUserDisplayName == Username &&
                           m.InvokerUserId == UserId &&
                           m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob &&
                           m.Properties["specification-id"] == specificationId &&
                           m.Trigger.EntityId == specificationId &&
                           m.Trigger.EntityType == nameof(Models.Specs.Specification) &&
                           m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                           ));

            logger
            .Received(1)
            .Error(Arg.Is($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'"));
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameAndGraphEnabled_SavesChangesEnsuresJobCreated()
        {
            // Arrange
            const string specificationId = "spec-id";

            SpecificationVersionComparisonModel specificationVersionComparison = new SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name = "any-name"
                },
                Previous = new SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Id      = "any-id",
                    Current = new CalculationVersion
                    {
                        Author          = new Reference(UserId, Username),
                        Date            = DateTimeOffset.Now,
                        PublishStatus   = PublishStatus.Draft,
                        SourceCode      = "source code",
                        Version         = 1,
                        Name            = "any name",
                        CalculationType = CalculationType.Template,
                    }
                }
            };

            BuildProject buildProject = new BuildProject
            {
                Id = "build-project-1",
                SpecificationId = specificationId
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            IJobManagement jobManagement = CreateJobManagement();

            jobManagement
            .QueueJob(Arg.Is <JobCreateModel>(_ => _.JobDefinitionId == JobConstants.DefinitionNames.GenerateGraphAndInstructAllocationJob))
            .Returns(new Job {
                Id = "job-id-1", JobDefinitionId = JobConstants.DefinitionNames.GenerateGraphAndInstructAllocationJob
            });

            jobManagement
            .QueueJob(Arg.Is <JobCreateModel>(_ => _.JobDefinitionId == JobConstants.DefinitionNames.ReIndexSpecificationCalculationRelationshipsJob))
            .Returns(new Job {
                Id = "job-id-2", JobDefinitionId = JobConstants.DefinitionNames.ReIndexSpecificationCalculationRelationshipsJob
            });

            IMapper mapper = Substitute.For <IMapper>();

            ICalculationsFeatureFlag calculationsFeatureFlag = CreateCalculationsFeatureFlag(true);

            CalculationService service = CreateCalculationService(
                calculationsRepository,
                logger,
                buildProjectsService: buildProjectsService,
                searchRepository: searchRepository,
                jobManagement: jobManagement,
                calculationsFeatureFlag: calculationsFeatureFlag);

            // Act
            await service.Run(message);

            // Assert
            await
            jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(
                          m =>
                          m.InvokerUserDisplayName == Username &&
                          m.InvokerUserId == UserId &&
                          m.JobDefinitionId == JobConstants.DefinitionNames.ReIndexSpecificationCalculationRelationshipsJob &&
                          m.Properties["specification-id"] == specificationId &&
                          m.Trigger.EntityId == specificationId &&
                          m.Trigger.EntityType == "Specification" &&
                          m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                          ));

            await
            jobManagement
            .Received(1)
            .QueueJob(Arg.Is <JobCreateModel>(
                          m =>
                          m.InvokerUserDisplayName == Username &&
                          m.InvokerUserId == UserId &&
                          m.JobDefinitionId == JobConstants.DefinitionNames.GenerateGraphAndInstructAllocationJob &&
                          m.Properties["specification-id"] == specificationId &&
                          m.Trigger.EntityId == specificationId &&
                          m.Trigger.EntityType == "Specification" &&
                          m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                          ));

            logger
            .Received(1)
            .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.GenerateGraphAndInstructAllocationJob}' created with id: 'job-id-1'"));

            logger
            .Received(1)
            .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.ReIndexSpecificationCalculationRelationshipsJob}' created with id: 'job-id-2'"));
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedFundingStreams_SetsTheAllocationLineAndFundingStreamToNull()
        {
            //Arrange
            const string specificationId = "spec-id";

            Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name           = "any-name",
                    FundingStreams = new List <Reference> {
                        new Reference {
                            Id = "fs2"
                        }
                    }
                },
                Previous = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    FundingStreams = new List <Reference> {
                        new Reference {
                            Id = "fs1"
                        }
                    }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Name            = "any name",
                    Id = "any-id",
                    CalculationSpecification = new Reference("any name", "any-id"),
                    FundingPeriod            = new Reference("18/19", "2018/2019"),
                    CalculationType          = CalculationType.Number,
                    FundingStream            = new Reference("fs1", "fs1-111"),
                    Current = new CalculationVersion
                    {
                        Author        = new Reference(UserId, Username),
                        Date          = DateTimeOffset.Now,
                        PublishStatus = PublishStatus.Draft,
                        SourceCode    = "source code",
                        Version       = 1
                    },
                    Policies = new List <Reference>()
                }
            };

            BuildProject buildProject = new BuildProject();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            IJobsApiClient jobsApiClient = CreateJobsApiClient();

            jobsApiClient
            .CreateJob(Arg.Any <JobCreateModel>())
            .Returns(new Job {
                Id = "job-id-1"
            });

            CalculationService service = CreateCalculationService(calculationsRepository, logger, buildProjectsService: buildProjectsService, searchRepository: searchRepository, jobsApiClient: jobsApiClient);

            //Act
            await service.UpdateCalculationsForSpecification(message);

            //Assert
            calcs
            .First()
            .FundingStream
            .Should()
            .BeNull();

            calcs
            .First()
            .AllocationLine
            .Should()
            .BeNull();

            await searchRepository
            .Received(1)
            .Index(Arg.Is <IEnumerable <CalculationIndex> >(c =>
                                                            c.First().Id == calcs.First().Id&&
                                                            c.First().FundingStreamId == "" &&
                                                            c.First().FundingStreamName == "No funding stream set"));
        }
        public async Task CreateCalculation_GivenValidCalculation_ButFailedToSave_DoesNotUpdateSearch()
        {
            //Arrange
            Calculation calculation = CreateCalculation();

            IEnumerable <Calculation> calculations = new[]
            {
                calculation
            };

            IEnumerable <Models.Specs.Calculation> calculationSpecifications = new[]
            {
                new Models.Specs.Calculation
                {
                    Id = calculation.CalculationSpecification.Id
                }
            };

            string json = JsonConvert.SerializeObject(calculation);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ICalculationsRepository repository = CreateCalculationsRepository();

            repository
            .CreateDraftCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.BadRequest);

            repository
            .GetCalculationsBySpecificationId(Arg.Is("any-spec-id"))
            .Returns(calculations);

            ILogger logger = CreateLogger();

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary()
            {
                Id   = calculation.SpecificationId,
                Name = "Test Spec Name",
            };

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(specificationSummary);

            specificationRepository
            .GetCalculationSpecificationsForSpecification(Arg.Is(calculation.SpecificationId))
            .Returns(calculationSpecifications);

            CalculationService service = CreateCalculationService(calculationsRepository: repository, logger: logger, searchRepository: searchRepository, specificationRepository: specificationRepository);

            //Act
            await service.CreateCalculation(message);

            //Assert
            logger
            .Received(1)
            .Error($"There was problem creating a new calculation with id {calculation.Id} in Cosmos Db with status code 400");

            await
            repository
            .Received(1)
            .CreateDraftCalculation(Arg.Is <Calculation>(m =>
                                                         m.Id == CalculationId &&
                                                         m.Current.PublishStatus == PublishStatus.Draft &&
                                                         m.Current.Author.Id == UserId &&
                                                         m.Current.Author.Name == Username &&
                                                         m.Current.Date.Date == DateTimeOffset.Now.Date &&
                                                         m.Current.Version == 1 &&
                                                         m.Current.DecimalPlaces == 6
                                                         ));

            await
            searchRepository
            .DidNotReceive()
            .Index(Arg.Any <List <CalculationIndex> >());
        }
        public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameAndSourceCodeContainsCalculationAggregate_SavesChangesEnsuresGenerateAggregationsJobCreated()
        {
            // Arrange
            const string specificationId = "spec-id";

            Models.Specs.SpecificationVersionComparisonModel specificationVersionComparison = new Models.Specs.SpecificationVersionComparisonModel()
            {
                Id      = specificationId,
                Current = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Name     = "any-name",
                    Policies = new[] { new Models.Specs.Policy {
                                           Id = "pol-id", Name = "policy2"
                                       } }
                },
                Previous = new Models.Specs.SpecificationVersion
                {
                    FundingPeriod = new Reference {
                        Id = "fp1"
                    },
                    Policies = new[] { new Models.Specs.Policy {
                                           Id = "pol-id", Name = "policy1"
                                       } }
                }
            };

            string json = JsonConvert.SerializeObject(specificationVersionComparison);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            message.UserProperties.Add("user-id", UserId);
            message.UserProperties.Add("user-name", Username);

            ILogger logger = CreateLogger();

            IEnumerable <Calculation> calcs = new[]
            {
                new Calculation
                {
                    SpecificationId = "spec-id",
                    Name            = "any name",
                    Id = "any-id",
                    CalculationSpecification = new Reference("any name", "any-id"),
                    FundingPeriod            = new Reference("18/19", "2018/2019"),
                    CalculationType          = CalculationType.Number,
                    FundingStream            = new Reference("fp1", "fs1-111"),
                    Current = new CalculationVersion
                    {
                        Author        = new Reference(UserId, Username),
                        Date          = DateTimeOffset.Now,
                        PublishStatus = PublishStatus.Draft,
                        SourceCode    = "return Min(calc1)",
                        Version       = 1
                    },
                    Policies = new List <Reference> {
                        new Reference {
                            Id = "pol-id", Name = "policy1"
                        }
                    }
                }
            };

            BuildProject buildProject = new BuildProject
            {
                Id = "build-project-1",
                SpecificationId = specificationId
            };

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calcs);

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(specificationId))
            .Returns(buildProject);

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            IJobsApiClient jobsApiClient = CreateJobsApiClient();

            jobsApiClient
            .CreateJob(Arg.Any <JobCreateModel>())
            .Returns(new Job {
                Id = "job-id-1", JobDefinitionId = JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob
            });

            CalculationService service = CreateCalculationService(
                calculationsRepository,
                logger,
                buildProjectsService: buildProjectsService,
                searchRepository: searchRepository,
                jobsApiClient: jobsApiClient);

            // Act
            await service.UpdateCalculationsForSpecification(message);

            // Assert
            await
            jobsApiClient
            .Received(1)
            .CreateJob(Arg.Is <JobCreateModel>(
                           m =>
                           m.InvokerUserDisplayName == Username &&
                           m.InvokerUserId == UserId &&
                           m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob &&
                           m.Properties["specification-id"] == specificationId &&
                           m.Trigger.EntityId == specificationId &&
                           m.Trigger.EntityType == nameof(Models.Specs.Specification) &&
                           m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'"
                           ));

            logger
            .Received(1)
            .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob}' created with id: 'job-id-1'"));
        }
        public async Task ProcessChanges_GivenChangeModelWithAggregableFieldChangesButNoAggregateParanetersFound_DoesNotResetCalculationForFieldDefinitionChanges(FieldDefinitionChangeType fieldDefinitionChangeType)
        {
            //Arrange
            string definitionId    = "df-id-1";
            string specificationId = "spec-1";

            IEnumerable <Calculation> calculations = new[]
            {
                new Calculation
                {
                    Current = new CalculationVersion
                    {
                        SourceCode = "return 2 + Datasets.TestRelationship.TestField1"
                    }
                }
            };

            DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges
            {
                Id = definitionId,
            };

            FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges
            {
                FieldDefinition = new FieldDefinition
                {
                    Id = "field1"
                },
                ExistingFieldDefinition = new FieldDefinition {
                    Name = "test field 1"
                }
            };

            fieldDefinitionChanges.ChangeTypes.Add(fieldDefinitionChangeType);

            TableDefinitionChanges tableDefinitionChanges = new TableDefinitionChanges();

            tableDefinitionChanges.FieldChanges.Add(fieldDefinitionChanges);

            datasetDefinitionChanges.TableDefinitionChanges.Add(tableDefinitionChanges);

            string json = JsonConvert.SerializeObject(datasetDefinitionChanges);

            Message message = new Message(Encoding.UTF8.GetBytes(json));

            ILogger logger = CreateLogger();

            IEnumerable <string> relationshipSpecificationIds = new[] { specificationId };

            IEnumerable <DatasetSpecificationRelationshipViewModel> relationshipViewModels = new[]
            {
                new DatasetSpecificationRelationshipViewModel
                {
                    Name = "Test Relationship"
                }
            };

            IDatasetRepository datasetRepository = CreateDatasetRepository();

            datasetRepository
            .GetRelationshipSpecificationIdsByDatasetDefinitionId(Arg.Is(definitionId))
            .Returns(relationshipSpecificationIds);
            datasetRepository
            .GetCurrentRelationshipsBySpecificationIdAndDatasetDefinitionId(Arg.Is(specificationId), Arg.Is(definitionId))
            .Returns(relationshipViewModels);

            ICalculationService calculationService = CreateCalculationService();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            DatasetDefinitionFieldChangesProcessor processor = CreateProcessor(
                logger: logger,
                datasetRepository: datasetRepository,
                calculationService: calculationService,
                calculationsRepository: calculationsRepository);

            //Act
            await processor.ProcessChanges(message);

            //Assert
            await
            calculationService
            .DidNotReceive()
            .ResetCalculationForFieldDefinitionChanges(Arg.Any <IEnumerable <DatasetSpecificationRelationshipViewModel> >(), Arg.Any <string>(), Arg.Any <IEnumerable <string> >());
        }
示例#29
0
        private async Task EnsureAllExistingCalculationsModified(TemplateMappingItem[] mappingsWithCalculations,
                                                                 SpecificationSummary specification,
                                                                 string correlationId,
                                                                 Reference author,
                                                                 IDictionary <uint, Calculation> uniqueTemplateCalculations,
                                                                 int startingItemCount)
        {
            if (!mappingsWithCalculations.Any())
            {
                return;
            }

            bool madeChanges = false;

            IEnumerable <Models.Calcs.Calculation> existingCalculations = await _calculationsRepositoryPolicy.ExecuteAsync(() => _calculationsRepository.GetCalculationsBySpecificationId(specification.Id));

            IDictionary <string, Models.Calcs.Calculation> existingCalculationsById = existingCalculations.ToDictionary(_ => _.Id);

            // filter out unchanged calculations
            (Calculation TemplateCalculation, Models.Calcs.Calculation Calculation)[] AllCalculation = GetAllCalculations(mappingsWithCalculations, uniqueTemplateCalculations, existingCalculationsById).ToArray();
 private void AndTheCalculations(IEnumerable <Calculation> calculations)
 {
     _calculationsRepository.GetCalculationsBySpecificationId(_specificationId)
     .Returns(calculations);
 }