public void ProcessChanges_GivenChangeModelWithFieldNameChangesButNoRelationshipsFound_ThrowsRetriableException() { //Arrange string definitionId = "df-id-1"; string specificationId = "spec-1"; DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges { Id = definitionId, }; FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges { FieldDefinition = new FieldDefinition { Id = "field1" } }; fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.FieldName); 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 }; 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, Enumerable.Empty <Common.ApiClient.DataSets.Models.DatasetSpecificationRelationshipViewModel>())); DatasetDefinitionFieldChangesProcessor processor = CreateProcessor(logger: logger, datasetRepository: datasetRepository); //Act Func <Task> test = async() => await processor.Run(message); //Assert test .Should() .ThrowExactly <RetriableException>() .Which .Message .Should() .Be($"No relationships found for specificationId '{specificationId}' and dataset definition id '{definitionId}'"); }
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) { ApiResponse <IEnumerable <Common.ApiClient.DataSets.Models.DatasetSpecificationRelationshipViewModel> > datasetsApiClientResponse = await _datasetsApiClientPolicy.ExecuteAsync(() => _datasetsApiClient.GetCurrentRelationshipsBySpecificationIdAndDatasetDefinitionId(specificationId, datasetDefinitionId)); if (!datasetsApiClientResponse.StatusCode.IsSuccess() || datasetsApiClientResponse.Content.IsNullOrEmpty()) { throw new RetriableException($"No relationships found for specificationId '{specificationId}' and dataset definition id '{datasetDefinitionId}'"); } IEnumerable <DatasetSpecificationRelationshipViewModel> relationships = _mapper.Map <IEnumerable <DatasetSpecificationRelationshipViewModel> >(datasetsApiClientResponse.Content); if (relationships.IsNullOrEmpty()) { throw new RetriableException($"No relationships found for specificationId '{specificationId}' and dataset definition id '{datasetDefinitionId}'"); } await _scenariosService.ResetScenarioForFieldDefinitionChanges(relationships, specificationId, fieldChanges.Select(m => m.ExistingFieldDefinition.Name)); } }
public async Task ProcessChanges_GivenChangeModelWithFieldChangesButNoRelationshipsExist_LogsAndReturns() { //Arrange string definitionId = "df-id-1"; DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges { Id = definitionId, }; FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges(); fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.FieldName); 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(); IDatasetsApiClient datasetRepository = CreateDatasetRepository(); datasetRepository .GetSpecificationIdsForRelationshipDefinitionId(Arg.Is(definitionId)) //.Returns(Enumerable.Empty<string>()); .Returns(new ApiResponse <IEnumerable <string> >(HttpStatusCode.OK, Enumerable.Empty <string>())); DatasetDefinitionFieldChangesProcessor processor = CreateProcessor(logger: logger, datasetRepository: datasetRepository); //Act await processor.Process(message); //Assert logger .Received(1) .Information(Arg.Is($"No dataset definition specification relationships exists for definition id '{definitionId}'")); }
async public Task SaveDefinition_GivenUpdatedYamlWithChangedIdentifierTypeFieldButAlreadyUsedInRelationship_ReturnsBadRequest() { //Arrange IEnumerable <string> specificationIds = new[] { "spec-1" }; string definitionId = "9183"; string yaml = CreateRawDefinition(); byte[] byteArray = Encoding.UTF8.GetBytes(yaml); MemoryStream stream = new MemoryStream(byteArray); IHeaderDictionary headerDictionary = new HeaderDictionary(); headerDictionary .Add("yaml-file", new StringValues(yamlFile)); HttpRequest request = Substitute.For <HttpRequest>(); request .Headers .Returns(headerDictionary); request .Body .Returns(stream); ILogger logger = CreateLogger(); IDatasetRepository datasetRepository = CreateDataSetsRepository(); datasetRepository .GetDistinctRelationshipSpecificationIdsForDatasetDefinitionId(Arg.Is(definitionId)) .Returns(specificationIds); datasetRepository .GetDatasetDefinition(Arg.Is(definitionId)) .Returns(new DatasetDefinition()); DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges { Id = definitionId, }; FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges(); fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.IdentifierType); TableDefinitionChanges tableDefinitionChanges = new TableDefinitionChanges(); tableDefinitionChanges.FieldChanges.Add(fieldDefinitionChanges); datasetDefinitionChanges.TableDefinitionChanges.Add(tableDefinitionChanges); IDefinitionChangesDetectionService definitionChangesDetectionService = CreateChangesDetectionService(); definitionChangesDetectionService .DetectChanges(Arg.Any <DatasetDefinition>(), Arg.Any <DatasetDefinition>()) .Returns(datasetDefinitionChanges); DefinitionsService service = CreateDefinitionsService(logger, definitionChangesDetectionService: definitionChangesDetectionService, datasetsRepository: datasetRepository); //Act IActionResult result = await service.SaveDefinition(request); //Assert result .Should() .BeOfType <BadRequestObjectResult>() .Which .Value .Should() .Be("Unable to change provider identifier as there are currently relationships setup against this schema"); }
private IEnumerable <FieldDefinitionChanges> DetectFieldDefinitionChanges(TableDefinition existingTableDefinition, TableDefinition newTableDefinition) { List <FieldDefinitionChanges> allFieldDefinitionChanges = new List <FieldDefinitionChanges>(); IEnumerable <FieldDefinition> newFieldDefinitions = newTableDefinition.FieldDefinitions; IEnumerable <FieldDefinition> existingFieldDefinitions = existingTableDefinition.FieldDefinitions; IEnumerable <FieldDefinitionChanges> extraFieldDefinitionChanges = newFieldDefinitions.Except(existingFieldDefinitions, new FieldDefinitionComparer()) .Select(m => new FieldDefinitionChanges(FieldDefinitionChangeType.AddedField) { FieldDefinition = m, }); allFieldDefinitionChanges.AddRange(extraFieldDefinitionChanges); IEnumerable <FieldDefinitionChanges> removedFieldDefinitionChanges = existingFieldDefinitions.Except(newFieldDefinitions, new FieldDefinitionComparer()) .Select(m => new FieldDefinitionChanges(FieldDefinitionChangeType.RemovedField) { FieldDefinition = m }); allFieldDefinitionChanges.AddRange(removedFieldDefinitionChanges); foreach (FieldDefinition newFieldDefinition in newFieldDefinitions) { string newFieldDefinitionId = newFieldDefinition.Id; if (extraFieldDefinitionChanges.AnyWithNullCheck(m => m.FieldDefinition.Id == newFieldDefinitionId) || removedFieldDefinitionChanges.AnyWithNullCheck(m => m.FieldDefinition.Id == newFieldDefinitionId)) { continue; } FieldDefinition existingFieldDefinition = existingFieldDefinitions.FirstOrDefault(m => m.Id == newFieldDefinitionId); FieldDefinitionChanges fieldDefinitionChanges = new FieldDefinitionChanges { FieldDefinition = newFieldDefinition, ExistingFieldDefinition = existingFieldDefinition }; if (existingFieldDefinition != null) { if (!string.Equals(newFieldDefinition.Name, existingFieldDefinition.Name)) { fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.FieldName); } if (newFieldDefinition.IsAggregable && !existingFieldDefinition.IsAggregable) { fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.IsAggregable); } if (!newFieldDefinition.IsAggregable && existingFieldDefinition.IsAggregable) { fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.IsNotAggregable); } if (newFieldDefinition.Type != existingFieldDefinition.Type) { fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.FieldType); } if (newFieldDefinition.IdentifierFieldType != existingFieldDefinition.IdentifierFieldType) { fieldDefinitionChanges.ChangeTypes.Add(FieldDefinitionChangeType.IdentifierType); } } if (fieldDefinitionChanges.HasChanges) { allFieldDefinitionChanges.Add(fieldDefinitionChanges); } } return(allFieldDefinitionChanges); }
public async Task ProcessChanges_GivenChangeModelWithMultipleFieldNameChanges_CallsResetCalculationForFieldDefinitionChanges() { //Arrange string definitionId = "df-id-1"; string specificationId = "spec-1"; DatasetDefinitionChanges datasetDefinitionChanges = new DatasetDefinitionChanges { Id = definitionId, }; FieldDefinitionChanges fieldDefinitionChanges1 = new FieldDefinitionChanges { FieldDefinition = new FieldDefinition { Id = "field1" }, ExistingFieldDefinition = new FieldDefinition { Name = "test field 1" } }; FieldDefinitionChanges fieldDefinitionChanges2 = new FieldDefinitionChanges { FieldDefinition = new FieldDefinition { Id = "field2" }, ExistingFieldDefinition = new FieldDefinition { Name = "test field 2" } }; fieldDefinitionChanges1.ChangeTypes.Add(FieldDefinitionChangeType.FieldName); fieldDefinitionChanges2.ChangeTypes.Add(FieldDefinitionChangeType.FieldName); TableDefinitionChanges tableDefinitionChanges = new TableDefinitionChanges(); tableDefinitionChanges.FieldChanges.AddRange(new[] { fieldDefinitionChanges1, fieldDefinitionChanges2 }); 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() }; IDatasetRepository datasetRepository = CreateDatasetRepository(); datasetRepository .GetRelationshipSpecificationIdsByDatasetDefinitionId(Arg.Is(definitionId)) .Returns(relationshipSpecificationIds); datasetRepository .GetCurrentRelationshipsBySpecificationIdAndDatasetDefinitionId(Arg.Is(specificationId), Arg.Is(definitionId)) .Returns(relationshipViewModels); ICalculationService calculationService = CreateCalculationService(); DatasetDefinitionFieldChangesProcessor processor = CreateProcessor( logger: logger, datasetRepository: datasetRepository, calculationService: calculationService); //Act await processor.ProcessChanges(message); //Assert await calculationService .Received(1) .ResetCalculationForFieldDefinitionChanges(Arg.Is(relationshipViewModels), Arg.Is(specificationId), Arg.Is <IEnumerable <string> >( m => m.Count() == 2 && m.ElementAt(0) == "test field 1" && m.ElementAt(1) == "test field 2")); }
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> >()); }
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); } } }
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")); }