public async void GetTagAllocations_GivenNullTransactionTags_Returns1MatchingAllocation() { //Arrange _mockPexApiClient.Setup(api => api.GetTags(It.IsAny <string>(), It.IsAny <CancellationToken>())).ThrowsAsync(new PexApiClientException(HttpStatusCode.Forbidden, "This business does not support the Tags Feature")); var transactions = new List <TransactionModel> { new TransactionModel { TransactionId = 419086499, TransactionAmount = -3.50M, } }; //Act Dictionary <long, List <AllocationTagValue> > actualAllocations = await _mockPexApiClient.Object.GetTagAllocations("d5fd5a3ba8324c1589c02d5414cb4358", transactions); //Assert Assert.NotNull(actualAllocations); Assert.Equal(transactions.Count, actualAllocations.Count); foreach (TransactionModel transaction in transactions) { Assert.NotNull(transaction); Assert.True(actualAllocations.ContainsKey(transaction.TransactionId)); if (!actualAllocations.TryGetValue(transaction.TransactionId, out List <AllocationTagValue> actualAllocation)) { throw new XunitException($"Could not find allocation for {nameof(transaction.TransactionId)} '{transaction.TransactionId}'."); } Assert.NotNull(actualAllocation); Assert.Single(actualAllocation); AllocationTagValue actualDefaultAllocation = actualAllocation.Single(); Assert.NotNull(actualDefaultAllocation); Assert.Null(actualDefaultAllocation.TagId); Assert.Empty(actualDefaultAllocation.Allocation); Assert.Equal(transaction.TransactionAmount, -actualDefaultAllocation.Amount); } }
public async void GetTagAllocations_Given4TagsAllocated1Way_Returns1Allocation() { //Arrange string dropdownTagId1 = "5e01e1e8aa53821e006da8ff"; string dropdownTagId2 = "5e01e1fcaa53821e006da901"; string dropdownTagId3 = "5e01e209aa53821e006da903"; string dropdownTagId4 = "5de64845aa53810dc4b3541b"; var tagDetails = new List <TagDetailsModel> { new TagDetailsModel { Id = dropdownTagId1, Type = CustomFieldType.Dropdown, }, new TagDetailsModel { Id = dropdownTagId2, Type = CustomFieldType.Dropdown, }, new TagDetailsModel { Id = dropdownTagId3, Type = CustomFieldType.Dropdown, }, new TagDetailsModel { Id = dropdownTagId4, Type = CustomFieldType.Dropdown, }, }; _mockPexApiClient.Setup(api => api.GetTags(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(tagDetails); var transactions = new List <TransactionModel> { new TransactionModel { TransactionId = 419086499, TransactionAmount = -3.50M, TransactionTags = new TransactionTagsModel { Tags = new List <TransactionTagModel> { new TransactionTagModel { FieldId = dropdownTagId1, Value = $"225756", Name = "Aplos Fund", }, new TransactionTagModel { FieldId = dropdownTagId2, Value = $"5708502", Name = "Aplos Contact", }, new TransactionTagModel { FieldId = dropdownTagId3, Value = $"5001", Name = "Aplos Account", }, new TransactionTagModel { FieldId = dropdownTagId4, Value = $"Equipment Rental", Name = "QBO Expense Category", }, }, State = FieldsState.Selected, FieldsVersion = "5e95c13baa53822810081e56", }, } }; //var chTransactions = new CardholderTransactions(transactions); //Act Dictionary <long, List <AllocationTagValue> > actualAllocations = await _mockPexApiClient.Object.GetTagAllocations("d5fd5a3ba8324c1589c02d5414cb4358", transactions); //Assert Assert.NotNull(actualAllocations); Assert.Equal(transactions.Count, actualAllocations.Count); foreach (TransactionModel transaction in transactions) { Assert.NotNull(transaction); Assert.True(actualAllocations.ContainsKey(transaction.TransactionId)); if (!actualAllocations.TryGetValue(transaction.TransactionId, out List <AllocationTagValue> actualAllocation)) { throw new XunitException($"Could not find allocation for {nameof(transaction.TransactionId)} '{transaction.TransactionId}'."); } Assert.NotNull(actualAllocation); Assert.NotNull(transaction.TransactionTags); Assert.NotNull(transaction.TransactionTags.Tags); Assert.Single(actualAllocation); AllocationTagValue actualDefaultAllocation = actualAllocation.Single(); Assert.NotNull(actualDefaultAllocation); Assert.Null(actualDefaultAllocation.TagId); Assert.NotEmpty(actualDefaultAllocation.Allocation); Assert.Equal(transaction.TransactionAmount, -actualDefaultAllocation.Amount); var expectedAllocation = new List <AllocationTagValue>(); var expectedAllocationValues = new List <TagValueItem>(); foreach (TransactionTagModel tag in transaction.TransactionTags.Tags) { expectedAllocationValues.Add(new TagValueItem { TagId = tag.FieldId, Value = tag.Value, }); } expectedAllocation.Add(new AllocationTagValue { TagId = null, Allocation = expectedAllocationValues, Amount = -transaction.TransactionAmount, }); foreach (AllocationTagValue expectedAllocationValue in expectedAllocation) { //For each expectedAllocation, find a matching actualAllocation. Assert.Contains(actualAllocation, aav => aav.TagId == expectedAllocationValue.TagId && aav.Amount == expectedAllocationValue.Amount && aav.Allocation.All(aaa => expectedAllocationValue.Allocation.Any(eaa => eaa.TagId == aaa.TagId && eaa.Value.Equals(aaa.Value)))); } foreach (AllocationTagValue actualAllocationValue in actualAllocation) { //For each actualAllocation, find a matching expectedAllocation. Assert.Contains(expectedAllocation, eav => eav.TagId == actualAllocationValue.TagId && eav.Amount == actualAllocationValue.Amount && eav.Allocation.All(eaa => actualAllocationValue.Allocation.Any(aaa => aaa.TagId == eaa.TagId && aaa.Value.Equals(eaa.Value)))); } //Opted to not go with the collection assert to make debugging easier. //Assert.Equal(expectedAllocation, actualAllocation); } }
public static async Task <Dictionary <long, List <AllocationTagValue> > > GetTagAllocations( this IPexApiClient pexApiClient, string externalToken, List <TransactionModel> transactions, List <TagDetailsModel> tagDefinitions) { if (pexApiClient is null) { throw new ArgumentNullException(nameof(pexApiClient)); } if (externalToken is null) { throw new ArgumentNullException(nameof(externalToken)); } if (transactions is null) { throw new ArgumentNullException(nameof(transactions)); } if (tagDefinitions is null) { throw new ArgumentNullException(nameof(tagDefinitions)); } var result = new Dictionary <long, List <AllocationTagValue> >(); Dictionary <string, TagDetailsModel> hashedTagDefinitions = tagDefinitions.ToDictionary(key => key.Id, value => value); foreach (TransactionModel transaction in transactions) { var allocations = new List <AllocationTagValue>(); var defaultAllocation = new AllocationTagValue { TagId = null, Allocation = new List <TagValueItem>(), Amount = Math.Abs(transaction.TransactionAmount), }; if (transaction.TransactionTags?.Tags != null) { foreach (TransactionTagModel tag in transaction.TransactionTags.Tags) { if (!hashedTagDefinitions.TryGetValue(tag.FieldId, out TagDetailsModel tagDefinition)) { throw new KeyNotFoundException($"Unable to find tag defintion for {nameof(TagDetailsModel.Id)} '{tag.FieldId}'."); } if (tagDefinition.Type == CustomFieldType.Allocation) { //Split tags var allocation = JsonConvert.DeserializeObject <AllocationTagValue>(tag.Value.ToString()); allocations.Add(allocation); } else { //Non-split tags defaultAllocation.Allocation.Add(new TagValueItem { TagId = tag.FieldId, Value = tag.Value, }); } } } if (!allocations.Any()) { //Ensure each transaction has at least one allocation allocations.Add(defaultAllocation); } result.Add(transaction.TransactionId, allocations); } return(result); }