Esempio n. 1
0
        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);
            }
        }
Esempio n. 2
0
        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);
        }