public CalculationBuilder WithDataType(CalculationDataType calculationDataType)
 {
     _calculationDataType = calculationDataType;
     return this;
 }
        public void CompileBuildProject_WhenBuildingCalculation_ThenCompilationUsesSourceCodeName(CalculationDataType calculationDataType, string sourceCode, string expectedType)
        {
            // Arrange
            string             specificationId = "test-spec1";
            List <Calculation> calculations    = new List <Calculation>
            {
                new Calculation
                {
                    Id      = "calcId1",
                    Current = new CalculationVersion
                    {
                        SourceCode            = sourceCode,
                        Name                  = "calc 1",
                        SourceCodeName        = "differentCalcName",
                        Description           = "test calc",
                        DataType              = calculationDataType,
                        AllowedEnumTypeValues = calculationDataType == CalculationDataType.Enum ? new List <string>()
                        {
                            "T1", "T2", "T3"
                        } : null
                    }
                }
            };

            SourceCodeService sourceCodeService = CreateServiceWithRealCompiler();

            BuildProject buildProject = new BuildProject
            {
                SpecificationId = specificationId,
                Id           = Guid.NewGuid().ToString(),
                Name         = specificationId,
                FundingLines = new Dictionary <string, Funding>()
            };

            CompilerOptions compilerOptions = new CompilerOptions();

            // Act
            Build build = sourceCodeService.Compile(buildProject, calculations, compilerOptions);

            // Assert
            build.Success.Should().BeTrue();

            string calcSourceCode = build.SourceFiles.First(s => s.FileName == "Calculations.vb").SourceCode;

            calcSourceCode.Should().Contain($"Public differentCalcName As Func(Of {expectedType}) = Nothing");
            calcSourceCode.Should().NotContain($"Public calc1 As Func(Of {expectedType}) = Nothing");
            calcSourceCode.Should().Contain($"differentCalcName()");
            calcSourceCode.Should().NotContain($"calc1()");
        }
 private string GetDataType(CalculationDataType calculationDataType, string calculationName) => calculationDataType switch
 {
Example #4
0
        public async Task <CreateCalculationResponse> CreateCalculation(string specificationId,
                                                                        CalculationCreateModel model,
                                                                        CalculationNamespace calculationNamespace,
                                                                        CalculationType calculationType,
                                                                        Reference author,
                                                                        string correlationId,
                                                                        CalculationDataType calculationDataType = CalculationDataType.Decimal,
                                                                        bool initiateCalcRun = true,
                                                                        IEnumerable <string> allowedEnumTypeValues = null)
        {
            Guard.ArgumentNotNull(model, nameof(model));
            Guard.ArgumentNotNull(author, nameof(author));

            if (string.IsNullOrWhiteSpace(model.Id))
            {
                model.Id = Guid.NewGuid().ToString();
            }

            model.SpecificationId = specificationId;
            model.CalculationType = calculationType;

            ValidationResult validationResult = await _calculationCreateModelValidator.ValidateAsync(model);

            if (!validationResult.IsValid)
            {
                return(new CreateCalculationResponse
                {
                    ValidationResult = validationResult,
                    ErrorType = CreateCalculationErrorType.InvalidRequest
                });
            }

            Calculation calculation = new Calculation
            {
                Id = model.Id,
                FundingStreamId = model.FundingStreamId,
                SpecificationId = model.SpecificationId
            };

            CalculationVersion calculationVersion = new CalculationVersion
            {
                CalculationId          = calculation.Id,
                PublishStatus          = PublishStatus.Draft,
                Author                 = author,
                Date                   = DateTimeOffset.Now.ToLocalTime(),
                Version                = 1,
                SourceCode             = model.SourceCode,
                Description            = model.Description,
                ValueType              = model.ValueType.Value,
                CalculationType        = calculationType,
                WasTemplateCalculation = false,
                Namespace              = calculationNamespace,
                Name                   = model.Name,
                DataType               = calculationDataType,
                AllowedEnumTypeValues  = allowedEnumTypeValues != null ? new List <string>(allowedEnumTypeValues) : Enumerable.Empty <string>()
            };

            calculation.Current = calculationVersion;

            bool?nameValidResult = await _calculationNameInUseCheck.IsCalculationNameInUse(calculation.SpecificationId, calculation.Name, null);

            if (nameValidResult == true)
            {
                string error =
                    $"Calculation with the same generated source code name already exists in this specification. Calculation Name {calculation.Name} and Specification {calculation.SpecificationId}";

                _logger.Error(error);

                return(new CreateCalculationResponse
                {
                    ErrorMessage = error,
                    ErrorType = CreateCalculationErrorType.InvalidRequest
                });
            }

            calculation.Current.SourceCodeName = _typeIdentifierGenerator.GenerateIdentifier(calculation.Name);

            HttpStatusCode result = await _calculationRepositoryPolicy.ExecuteAsync(() => _calculationsRepository.CreateDraftCalculation(calculation));

            if (result.IsSuccess())
            {
                await _calculationVersionsRepositoryPolicy.ExecuteAsync(() => _calculationVersionRepository.SaveVersion(calculationVersion));

                await UpdateSearch(calculation, model.SpecificationName, model.FundingStreamName);

                string cacheKey = $"{CacheKeys.CalculationsMetadataForSpecification}{specificationId}";

                await _cachePolicy.ExecuteAsync(() => _cacheProvider.RemoveAsync <List <CalculationMetadata> >(cacheKey));

                if (!initiateCalcRun)
                {
                    return(new CreateCalculationResponse
                    {
                        Succeeded = true,
                        Calculation = calculation
                    });
                }

                try
                {
                    Job job = await SendInstructAllocationsToJobService(calculation.SpecificationId, author.Id, author.Name, new Trigger
                    {
                        EntityId   = calculation.Id,
                        EntityType = nameof(Calculation),
                        Message    = $"Saving calculation: '{calculation.Id}' for specification: '{calculation.SpecificationId}'"
                    }, correlationId);

                    if (job != null)
                    {
                        _logger.Information($"New job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' created with id: '{job.Id}'");

                        return(new CreateCalculationResponse
                        {
                            Succeeded = true,
                            Calculation = calculation
                        });
                    }
                    else
                    {
                        string errorMessage = $"Failed to create job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' on specification '{calculation.SpecificationId}'";

                        _logger.Error(errorMessage);

                        return(new CreateCalculationResponse
                        {
                            ErrorType = CreateCalculationErrorType.Exception,
                            ErrorMessage = errorMessage
                        });
                    }
                }
                catch (Exception ex)
                {
                    return(new CreateCalculationResponse
                    {
                        ErrorMessage = ex.Message,
                        ErrorType = CreateCalculationErrorType.Exception
                    });
                }
            }
            else
            {
                string errorMessage = $"There was problem creating a new calculation with name {calculation.Name} in Cosmos Db with status code {(int)result}";

                _logger.Error(errorMessage);

                return(new CreateCalculationResponse
                {
                    ErrorMessage = errorMessage,
                    ErrorType = CreateCalculationErrorType.Exception
                });
            }
        }