public void EditSpecification_GivenProviderVersionChangesAndRegenerateScopedProvidersFails_ExceptionThrown() { //Arrange var existingFundingStreams = _specification.Current.FundingStreams; SpecificationEditModel specificationEditModel = new SpecificationEditModel { FundingPeriodId = "fp10", Name = "new spec name" }; PolicyModels.FundingStream fundingStream = new PolicyModels.FundingStream { Id = existingFundingStreams.First().Id }; Models.Specs.SpecificationVersion newSpecVersion = _specification.Current.Clone() as Models.Specs.SpecificationVersion; newSpecVersion.Name = specificationEditModel.Name; newSpecVersion.FundingPeriod.Id = specificationEditModel.FundingPeriodId; newSpecVersion.FundingStreams = new[] { new Reference { Id = "fs11" } }; newSpecVersion.ProviderVersionId = "Provider version 2"; _providersApiClient.RegenerateProviderSummariesForSpecification(_specification.Id, true) .Returns(new ApiResponse <bool>(HttpStatusCode.BadRequest)); var service = CreateSpecificationsService(newSpecVersion); //Act Func <Task> invocation = async() => await service.EditSpecification(SpecificationId, specificationEditModel, null, null); //Arrange invocation.Should() .Throw <RetriableException>() .WithMessage($"Unable to re-generate scoped providers while editing specification '{_specification.Id}' with status code: {HttpStatusCode.BadRequest}"); }
public async Task EditSpecification_GivenFailsToUpdateCosmosWithBadRequest_ReturnsBadRequest() { //Arrange IEnumerable <Reference> existingFundingStreams = _specification.Current.FundingStreams; SpecificationEditModel specificationEditModel = new SpecificationEditModel { FundingPeriodId = "fp10", ProviderVersionId = _specification.Current.ProviderVersionId }; PolicyModels.FundingStream fundingStream = new PolicyModels.FundingStream { Id = existingFundingStreams.First().Id, Name = existingFundingStreams.First().Name }; ApiResponse <PolicyModels.FundingStream> fundingStreamResponse = new ApiResponse <PolicyModels.FundingStream>(HttpStatusCode.OK, fundingStream); _specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(_specification); _policiesApiClient .GetFundingPeriodById(Arg.Is(_fundingPeriod.Id)) .Returns(_fundingPeriodResponse); _policiesApiClient .GetFundingStreamById(Arg.Is(fundingStream.Id)) .Returns(fundingStreamResponse); _specificationsRepository .UpdateSpecification(Arg.Any <Specification>()) .Returns(HttpStatusCode.BadRequest); AndGetFundingConfiguration( _specification.Current.FundingStreams.FirstOrDefault().Id, specificationEditModel.FundingPeriodId); SpecificationsService service = CreateService(mapper: _mapper, logs: _logger, specificationsRepository: _specificationsRepository, policiesApiClient: _policiesApiClient); //Act IActionResult result = await service.EditSpecification(SpecificationId, specificationEditModel, null, null); //Assert result .Should() .BeOfType <StatusCodeResult>() .Which .StatusCode .Should() .Be(400); }
private void ThenFundingStreamResultMatches(IEnumerable <PoliciesApiModels.FundingStream> fundingStreams) { fundingStreams .Count() .Should() .Be(1); fundingStreams .FirstOrDefault() .Should() .NotBeNull(); PoliciesApiModels.FundingStream fundingStream = fundingStreams.FirstOrDefault(); fundingStream .Id .Should() .Be(_fundingStreamId); fundingStream .Name .Should() .Be(_fundingStreamName); }
private async Task <IActionResult> SaveDatasetDefinition(DatasetDefinition definition, string correlationId, Reference user) { DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges(); DatasetDefinition existingDefinition = await _datasetsRepositoryPolicy.ExecuteAsync(() => _datasetsRepository.GetDatasetDefinition(definition.Id)); IEnumerable <string> relationships = null; if (existingDefinition != null) { datasetDefinitionChanges = _definitionChangesDetectionService.DetectChanges(definition, existingDefinition); relationships = await _datasetsRepositoryPolicy.ExecuteAsync(() => _datasetsRepository.GetDistinctRelationshipSpecificationIdsForDatasetDefinitionId(datasetDefinitionChanges.Id)); IEnumerable <FieldDefinitionChanges> fieldDefinitionChanges = datasetDefinitionChanges.TableDefinitionChanges.SelectMany(m => m.FieldChanges); if (!relationships.IsNullOrEmpty() && !fieldDefinitionChanges.IsNullOrEmpty()) { if (fieldDefinitionChanges.Any(m => m.ChangeTypes.Any(c => c == FieldDefinitionChangeType.RemovedField))) { return(new BadRequestObjectResult("Unable to remove a field as there are currently relationships setup against this schema")); } if (fieldDefinitionChanges.Any(m => m.ChangeTypes.Any(c => c == FieldDefinitionChangeType.IdentifierType))) { return(new BadRequestObjectResult("Unable to change provider identifier as there are currently relationships setup against this schema")); } } } try { HttpStatusCode result = await _datasetsRepositoryPolicy.ExecuteAsync(() => _datasetsRepository.SaveDefinition(definition)); if (!result.IsSuccess()) { int statusCode = (int)result; _logger.Error($"Failed to save dataset definition - {definition.Name} to cosmos db with status {statusCode}"); return(new StatusCodeResult(statusCode)); } IEnumerable <PoliciesApiModels.FundingStream> fundingStreams = await _policyRepository.GetFundingStreams(); PoliciesApiModels.FundingStream fundingStream = fundingStreams.SingleOrDefault(_ => _.Id == definition.FundingStreamId); await IndexDatasetDefinition(definition, fundingStream); } catch (Exception exception) { string errorMessage = $"Exception occurred writing dataset definition - {definition.Name} to cosmos db"; _logger.Error(exception, errorMessage); return(new InternalServerErrorResult(errorMessage)); } byte[] excelAsBytes = _excelWriter.Write(definition); if (excelAsBytes == null || excelAsBytes.Length == 0) { string errorMessage = $"Failed to generate excel file for {definition.Name}"; _logger.Error(errorMessage); return(new InternalServerErrorResult(errorMessage)); } try { await SaveToBlobStorage(excelAsBytes, definition.Name); } catch (Exception ex) { return(new InternalServerErrorResult(ex.Message)); } _logger.Information($"Successfully saved dataset definition - {definition.Name} to cosmos db"); if (existingDefinition != null && datasetDefinitionChanges.HasChanges) { if (!relationships.IsNullOrEmpty()) { Task <ApiResponse <CalcJob> >[] updateCodeContextJobs = relationships.Select(specificationId => _calculationsResilience.ExecuteAsync(() => _calculations.QueueCodeContextUpdate(specificationId))).ToArray(); await TaskHelper.WhenAllAndThrow(updateCodeContextJobs); } IDictionary <string, string> properties = MessageExtensions.BuildMessageProperties(correlationId, user); await _messengerService.SendToTopic(ServiceBusConstants.TopicNames.DataDefinitionChanges, datasetDefinitionChanges, properties); } return(new OkResult()); }
private async Task <IEnumerable <IndexError> > IndexDatasetDefinition(DatasetDefinition definition, PoliciesApiModels.FundingStream fundingStream) { // Calculate hash for model to see if there are changes string modelJson = JsonConvert.SerializeObject(definition); string hashCode = ""; using (SHA256 sha256Generator = SHA256Managed.Create()) { byte[] modelBytes = UTF8Encoding.UTF8.GetBytes(modelJson); foreach (byte hashByte in sha256Generator.ComputeHash(modelBytes)) { hashCode += string.Format("{0:X2}", hashByte); } } DatasetDefinitionIndex datasetDefinitionIndex = new DatasetDefinitionIndex() { Id = definition.Id, Name = definition.Name, Description = definition.Description, LastUpdatedDate = DateTimeOffset.Now, ProviderIdentifier = definition.TableDefinitions.FirstOrDefault()?.FieldDefinitions?.Where(f => f.IdentifierFieldType.HasValue)?.Select(f => Enum.GetName(typeof(IdentifierFieldType), f.IdentifierFieldType.Value)).FirstOrDefault(), ModelHash = hashCode, FundingStreamId = fundingStream.Id, FundingStreamName = fundingStream.Name }; if (string.IsNullOrWhiteSpace(datasetDefinitionIndex.ProviderIdentifier)) { datasetDefinitionIndex.ProviderIdentifier = "None"; } bool updateIndex = true; // Only update index if metadata or model has changed, this is to preserve the LastUpdateDate DatasetDefinitionIndex existingIndex = await _datasetDefinitionSearchRepositoryPolicy.ExecuteAsync(() => _datasetDefinitionSearchRepository.SearchById(definition.Id)); if (existingIndex != null) { if (existingIndex.ModelHash == hashCode && existingIndex.Description == definition.Description && existingIndex.Name == definition.Name && existingIndex.ProviderIdentifier == datasetDefinitionIndex.ProviderIdentifier) { updateIndex = false; } } if (updateIndex) { return(await _datasetDefinitionSearchRepositoryPolicy.ExecuteAsync(() => _datasetDefinitionSearchRepository.Index(new DatasetDefinitionIndex[] { datasetDefinitionIndex }))); } return(Enumerable.Empty <IndexError>()); }