private async Task PerformTest(UserType userType)
        {
            this.apiKeyRepository.Setup(v => v.GetApiKey(userType)).Returns(ApiKey);

            var expectedInput = new CreateRefundIn
            {
                Amount   = AmountInMinorDenomination.Create(RefundCreditAmount).ToMajorDenomination(),
                CustomId = CreateTaxamoTransaction.CustomId
            };

            CreateRefundIn actualInput = null;

            this.taxamoService.Setup(v => v.CreateRefundAsync(TaxamoTransactionKey, It.IsAny <CreateRefundIn>(), ApiKey))
            .Callback <string, CreateRefundIn, string>((a, b, c) => actualInput = b)
            .ReturnsAsync(new CreateRefundOut
            {
                TotalAmount = 0.12m,
                TaxAmount   = 0.02m,
            });

            var result = await this.target.ExecuteAsync(TaxamoTransactionKey, RefundCreditAmount, userType);

            Assert.AreEqual(
                new CreateTaxamoRefund.TaxamoRefundResult(
                    PositiveInt.Parse(12),
                    NonNegativeInt.Parse(2)),
                result);

            Assert.AreEqual(
                JsonConvert.SerializeObject(expectedInput, Formatting.None),
                JsonConvert.SerializeObject(actualInput, Formatting.None));
        }
Ejemplo n.º 2
0
        public async Task WhenTaxamoAmountDoesNotEqualExpectedAmount_AndUserTypeIsTestUser_ItShouldCancelTransactionAndAbort()
        {
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(UserId)).ReturnsAsync(Origin);

            this.createTaxamoTransaction.Setup(v => v.ExecuteAsync(
                                                   Amount,
                                                   Origin.CountryCode,
                                                   Origin.CreditCardPrefix,
                                                   Origin.IpAddress,
                                                   Origin.OriginalTaxamoTransactionKey,
                                                   UserType.TestUser))
            .ReturnsAsync(TaxamoTransaction);

            this.deleteTaxamoTransaction.Setup(v => v.ExecuteAsync(TaxamoTransaction.Key, UserType.TestUser))
            .Returns(Task.FromResult(0))
            .Verifiable();

            await ExpectedException.AssertExceptionAsync <BadRequestException>(
                () => this.target.HandleAsync(
                    UserId,
                    PositiveInt.Parse(10),
                    PositiveInt.Parse(11),
                    UserType.TestUser));

            this.deleteTaxamoTransaction.Verify();
        }
 public async Task WhenAmountIsLessThanMinimumPaymentAmount_ItShouldThrowAnException()
 {
     await this.target.HandleAsync(new ApplyCreditRequestCommand(
                                       Requester,
                                       UserId,
                                       Now,
                                       TransactionReference,
                                       PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount - 1),
                                       Command.ExpectedTotalAmount));
 }
 public async Task WhenTotalAmountIsLessThanCreditAmount_ItShouldThrowAnException()
 {
     await this.target.ExecuteAsync(
         EnactingUserId,
         UserId,
         Timestamp,
         TotalAmount,
         PositiveInt.Parse(TotalAmount.Value + 1),
         TransactionReference,
         StripeChargeId,
         TaxamoTransactionKey,
         Comment);
 }
        public async Task WhenLocationDataSupplied_ItShouldNotRequestOrigin()
        {
            this.requesterSecurity.Setup(v => v.IsInRoleAsync(Requester, FifthweekRole.TestUser)).ReturnsAsync(false);

            this.getUserWeeklySubscriptionCost.Setup(v => v.ExecuteAsync(UserId)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1);

            this.getTaxInformation
            .Setup(v => v.ExecuteAsync(
                       PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1),
                       QueryWithOverride.LocationDataOverride.CountryCode.Value,
                       QueryWithOverride.LocationDataOverride.CreditCardPrefix.Value,
                       QueryWithOverride.LocationDataOverride.IpAddress.Value,
                       null,
                       UserType.StandardUser))
            .ReturnsAsync(TaxamoTransaction);

            var result = await this.target.HandleAsync(QueryWithOverride);

            Assert.AreEqual(
                new CreditRequestSummary(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1, TaxamoTransaction),
                result);
        }
Ejemplo n.º 6
0
        public async Task <CreditRequestSummary> HandleAsync(GetCreditRequestSummaryQuery query)
        {
            query.AssertNotNull("query");

            await this.requesterSecurity.AuthenticateAsAsync(query.Requester, query.UserId);

            var userType = await this.requesterSecurity.GetUserTypeAsync(query.Requester);

            var subscriptionsAmount = await this.getUserWeeklySubscriptionsCost.ExecuteAsync(query.UserId);

            var amountToCharge = Math.Max(TopUpUserAccountsWithCredit.MinimumPaymentAmount, subscriptionsAmount);

            UserPaymentOriginResult origin;

            if (query.LocationDataOverride == null)
            {
                origin = await this.getUserPaymentOrigin.ExecuteAsync(query.UserId);
            }
            else
            {
                origin = new UserPaymentOriginResult(
                    query.LocationDataOverride.CountryCode == null ? null : query.LocationDataOverride.CountryCode.Value,
                    query.LocationDataOverride.CreditCardPrefix == null ? null : query.LocationDataOverride.CreditCardPrefix.Value,
                    query.LocationDataOverride.IpAddress == null ? null : query.LocationDataOverride.IpAddress.Value);
            }

            var taxInformation = await this.getTaxInformation.ExecuteAsync(
                PositiveInt.Parse(amountToCharge),
                origin.CountryCode,
                origin.CreditCardPrefix,
                origin.IpAddress,
                origin.OriginalTaxamoTransactionKey,
                userType);

            return(new CreditRequestSummary(
                       subscriptionsAmount,
                       taxInformation));
        }
        public async Task WhenSubscriptionCstIsLessThanMinimumCharge_ItShouldReturnTaxInformationSummaryForMinimumCharge()
        {
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(UserId)).ReturnsAsync(Origin);
            this.requesterSecurity.Setup(v => v.IsInRoleAsync(Requester, FifthweekRole.TestUser)).ReturnsAsync(false);

            this.getUserWeeklySubscriptionCost.Setup(v => v.ExecuteAsync(UserId)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount - 1);

            this.getTaxInformation
            .Setup(v => v.ExecuteAsync(
                       PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount),
                       Origin.CountryCode,
                       Origin.CreditCardPrefix,
                       Origin.IpAddress,
                       Origin.OriginalTaxamoTransactionKey,
                       UserType.StandardUser))
            .ReturnsAsync(TaxamoTransaction);

            var result = await this.target.HandleAsync(Query);

            Assert.AreEqual(
                new CreditRequestSummary(TopUpUserAccountsWithCredit.MinimumPaymentAmount - 1, TaxamoTransaction),
                result);
        }
        private async Task ParameterizedTestAsync(
            Func <UserId,
                  UserId,
                  IReadOnlyList <ChannelId>,
                  IReadOnlyList <QueueId>,
                  DateTime,
                  bool,
                  NonNegativeInt,
                  PositiveInt,
                  IReadOnlyList <NewsfeedPost>,
                  int,
                  Task> parameterizedTest)
        {
            var totalLivePosts = SortedLiveNewsfeedPosts.Count;

            NonNegativeInt noPaginationStart = NonNegativeInt.Parse(0);
            PositiveInt    noPaginationCount = PositiveInt.Parse(int.MaxValue);

            var wrapper = new ParameterizedTestWrapper(parameterizedTest);

            parameterizedTest = wrapper.Execute;

            // No pagination.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts, 0);

            // Paginate from start.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(0), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Take(10).ToList(), 0);

            // Paginate from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(5), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Skip(5).Take(10).ToList(), 0);

            // Paginate from middle with same page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(10), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Skip(10).Take(10).ToList(), 0);

            // Paginate from near end, requesting up to last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 10), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Skip(totalLivePosts - 10).Take(10).ToList(), 0);

            // Paginate from near end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 5), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Skip(totalLivePosts - 5).Take(10).ToList(), 0);

            // Paginate from end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts), PositiveInt.Parse(1), new NewsfeedPost[0], 0);

            // Paginate from beyond end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts + 1), PositiveInt.Parse(1), new NewsfeedPost[0], 0);

            // Unsubscribed.
            await parameterizedTest(
                UnsubscribedUserId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, new NewsfeedPost[0], 0);

            // Subscribed at correct price, fetch from all subscriptions.
            await parameterizedTest(
                SubscribedUserId, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => !v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Subscribed at correct price.
            await parameterizedTest(
                SubscribedUserId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => !v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Subscribed at zero, but on free access list.
            await parameterizedTest(
                GuestListUserId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => !v.ChannelId.Equals(ChannelIds[2])).ToList(), 0);

            // Filter by channel for creator.
            await parameterizedTest(
                CreatorId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 0);

            // Filter by channel.
            await parameterizedTest(
                SubscribedUserId, null, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by channel 2.
            await parameterizedTest(
                SubscribedUserId, null, new[] { ChannelIds[1] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[1])).ToList(), 10);

            // Filter by unsubscribed channel 3.
            await parameterizedTest(
                SubscribedUserId, null, new[] { ChannelIds[2] }, null, Now, false, noPaginationStart, noPaginationCount, new NewsfeedPost[0], 10);

            // Filter by valid channel and creator combination.
            await parameterizedTest(
                SubscribedUserId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by invalid channel and creator combination.
            await parameterizedTest(
                SubscribedUserId, GuestListUserId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, new NewsfeedPost[0], 10);

            // Search forwards from now.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, true, noPaginationStart, noPaginationCount, new NewsfeedPost[0], 0);

            // Search forwards from beginning.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Reverse().ToList(), 0);

            // Paginate forwards from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, NonNegativeInt.Parse(5), PositiveInt.Parse(10), SortedLiveNewsfeedPosts.Reverse().Skip(5).Take(10).ToList(), 0);
        }
        private async Task ParameterizedTestAsync(
            Func <UserId,
                  UserId,
                  IReadOnlyList <ChannelId>,
                  IReadOnlyList <QueueId>,
                  DateTime,
                  bool,
                  NonNegativeInt,
                  PositiveInt,
                  IReadOnlyList <PreviewNewsfeedPost>,
                  int,
                  Task> parameterizedTest)
        {
            var totalLivePosts = SortedLiveNewsfeedPosts.Count;

            NonNegativeInt noPaginationStart = NonNegativeInt.Parse(0);
            PositiveInt    noPaginationCount = PositiveInt.Parse(int.MaxValue);

            var wrapper = new ParameterizedTestWrapper(parameterizedTest);

            parameterizedTest = wrapper.Execute;

            var visibleSortedLiveNewsfeedPosts =
                SortedLiveNewsfeedPosts.Where(v => !v.ChannelId.Equals(ChannelIds[3])).ToList();

            // No pagination.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts.ToList(), 0);

            // Paginate from start.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(0), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Take(10).ToList(), 0);

            // Paginate from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(5).Take(10).ToList(), 0);

            // Paginate from middle with same page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(10), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(10).Take(10).ToList(), 0);

            // Paginate from near end, requesting up to last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 10), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(totalLivePosts - 10).Take(10).ToList(), 0);

            // Paginate from near end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(totalLivePosts - 5).Take(10).ToList(), 0);

            // Paginate from end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts), PositiveInt.Parse(1), new PreviewNewsfeedPost[0], 0);

            // Paginate from beyond end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts + 1), PositiveInt.Parse(1), new PreviewNewsfeedPost[0], 0);

            // Unsubscribed.
            await parameterizedTest(
                UnsubscribedUserId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts, 0);

            // Unsubscribed, fetch from all subscriptions (will ignore non-discoverable channel).
            await parameterizedTest(
                UnsubscribedUserId, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Logged out.
            await parameterizedTest(
                null, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts, 0);

            // Logged out, fetch from all subscriptions (will ignore non-discoverable channel).
            await parameterizedTest(
                null, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Logged in as creator, filter by channel for creator (will ignore non-discoverable channel).
            await parameterizedTest(
                CreatorId, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 0);

            // Filter by channel for creator.
            await parameterizedTest(
                CreatorId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 0);

            // Filter by channel.
            await parameterizedTest(
                UnsubscribedUserId, null, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by channel 2.
            await parameterizedTest(
                UnsubscribedUserId, null, new[] { ChannelIds[1] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[1])).ToList(), 10);

            // Filter by valid channel and creator combination.
            await parameterizedTest(
                UnsubscribedUserId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by invalid channel and creator combination.
            await parameterizedTest(
                UnsubscribedUserId, UserId.Random(), new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, new PreviewNewsfeedPost[0], 10);

            // Search forwards from now.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, true, noPaginationStart, noPaginationCount, new PreviewNewsfeedPost[0], 0);

            // Search forwards from beginning.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts.AsEnumerable().Reverse().ToList(), 0);

            // Paginate forwards from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, NonNegativeInt.Parse(5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.AsEnumerable().Reverse().Skip(5).Take(10).ToList(), 0);
        }
        public async Task ItShouldChargeAllNecessaryUsers()
        {
            this.timestampCreator.SetupSequence(v => v.Now()).Returns(Now1).Returns(Now2);
            this.guidCreator.SetupSequence(v => v.CreateSqlSequential()).Returns(TransactionReference1.Value).Returns(TransactionReference2.Value);

            var userId1 = UserId.Random();
            var userId2 = UserId.Random();
            var userId3 = UserId.Random();
            var userId4 = UserId.Random();
            var userId5 = UserId.Random();
            var input   = new List <CalculatedAccountBalanceResult>
            {
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.Stripe, 0),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId1, LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge - 1),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId2, LedgerAccountType.FifthweekCredit, -1m),
            };

            var usersRequiringRetry = new List <UserId> {
                userId3, userId4, userId5
            };

            this.getUsersRequiringPaymentRetry.Setup(v => v.ExecuteAsync()).ReturnsAsync(usersRequiringRetry);

            var usersRequiringCharge = new List <UserId> {
                userId1, userId2, userId3, userId4, userId5
            };

            this.incrementPaymentStatus.Setup(v => v.ExecuteAsync(It.IsAny <IReadOnlyList <UserId> >()))
            .Callback <IReadOnlyList <UserId> >(v => CollectionAssert.AreEquivalent(usersRequiringCharge, v.ToList()))
            .Returns(Task.FromResult(0)).Verifiable();

            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId1)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount - 1);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId2)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId3)).ReturnsAsync(0);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId4)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId5)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);

            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId1))
            .ReturnsAsync(new UserPaymentOriginResult("customer1", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId2))
            .ReturnsAsync(new UserPaymentOriginResult("customer2", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));

            // Test PaymentOriginKeyType with no key.
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId4))
            .ReturnsAsync(new UserPaymentOriginResult(null, PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));

            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId5))
            .ReturnsAsync(new UserPaymentOriginResult("customer5", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.None));

            this.applyUserCredit.Setup(v => v.ExecuteAsync(userId1, Now1, TransactionReference1, PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount), null, UserType.StandardUser))
            .Returns(Task.FromResult(0))
            .Verifiable();

            this.applyUserCredit.Setup(v => v.ExecuteAsync(userId2, Now2, TransactionReference2, PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1), null, UserType.StandardUser))
            .Returns(Task.FromResult(0))
            .Verifiable();

            var result = await this.target.ExecuteAsync(input, new List <PaymentProcessingException>(), CancellationToken.None);

            this.incrementPaymentStatus.Verify();
            this.applyUserCredit.Verify();

            Assert.IsTrue(result);
        }
        public async Task <bool> ExecuteAsync(
            IReadOnlyList <CalculatedAccountBalanceResult> updatedAccountBalances,
            List <PaymentProcessingException> errors,
            CancellationToken cancellationToken)
        {
            using (PaymentsPerformanceLogger.Instance.Log(typeof(TopUpUserAccountsWithCredit)))
            {
                updatedAccountBalances.AssertNotNull("updatedAccountBalances");
                errors.AssertNotNull("errors");

                var userIdsToRetry = await this.getUsersRequiringPaymentRetry.ExecuteAsync();

                var newUserIds = updatedAccountBalances
                                 .Where(v => v.AccountType == LedgerAccountType.FifthweekCredit &&
                                        v.Amount < MinimumAccountBalanceBeforeCharge)
                                 .Select(v => v.UserId);
                var allUserIds = userIdsToRetry.Concat(newUserIds).Distinct().ToList();

                // Increment all billing status immediately so the user maintains access to his newsfeed.
                await this.incrementPaymentStatus.ExecuteAsync(allUserIds);

                bool recalculateBalances = false;
                foreach (var userId in allUserIds)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        // Work out what we should charge the user.
                        var amountToCharge = await this.getUserWeeklySubscriptionsCost.ExecuteAsync(userId);

                        if (amountToCharge == 0)
                        {
                            // No subscriptions, so no need to charge.
                            continue;
                        }

                        amountToCharge = Math.Max(MinimumPaymentAmount, amountToCharge);

                        var origin = await this.getUserPaymentOrigin.ExecuteAsync(userId);

                        if (origin.PaymentOriginKey == null ||
                            origin.PaymentOriginKeyType == PaymentOriginKeyType.None ||
                            origin.PaymentStatus == PaymentStatus.None)
                        {
                            // If the user doesn't have a stripe customer ID then they haven't given us
                            // credit card details and we can't bill them.
                            // If the user has manually topped up since we incremented the billing status,
                            // it will have been set back to None and we don't need to top up again.
                            continue;
                        }

                        var timestamp            = this.timestampCreator.Now();
                        var transactionReference = new TransactionReference(this.guidCreator.CreateSqlSequential());

                        // And apply the charge.
                        await this.applyUserCredit.ExecuteAsync(
                            userId,
                            timestamp,
                            transactionReference,
                            PositiveInt.Parse(amountToCharge),
                            null,
                            UserType.StandardUser);

                        recalculateBalances = true;
                    }
                    catch (Exception t)
                    {
                        errors.Add(new PaymentProcessingException(t, userId, null));
                    }
                }

                return(recalculateBalances);
            }
        }
Ejemplo n.º 12
0
            public async Task ItShouldCallCreateCreditRefund()
            {
                this.timestampCreator.Setup(v => v.Now()).Returns(Now);

                this.createCreditRefund.Setup(v => v.HandleAsync(
                                                  new CreateCreditRefundCommand(Requester, TransactionReference, Now, PositiveInt.Parse(Data.RefundCreditAmount), Data.Reason, Data.Comment)))
                .Returns(Task.FromResult(0))
                .Verifiable();

                await this.target.PostCreditRefundAsync(TransactionReference.Value.EncodeGuid(), Data);

                this.createCreditRefund.Verify();
            }
        public async Task ItShouldBeAbleToRefundCredit()
        {
            await this.IntegrationTestAsync(async testDatabase =>
            {
                this.InitializeServices(testDatabase);

                var random = new Random();

                TransactionReference transactionReference;
                using (var databaseContext = testDatabase.CreateContext())
                {
                    //var creator1 = CreateUser(databaseContext, random, CreatorId1);
                    var subscriber1 = CreateUser(databaseContext, random, SubscriberId1);

                    transactionReference = AddCredit(databaseContext, random, SubscriberId1, 1000);
                    //PayCreator(databaseContext, random, SubscriberId1, CreatorId1, 10m);
                    //PayCreatorUncommitted(databaseContext, random, SubscriberId2, CreatorId2, 5m);
                    await databaseContext.SaveChangesAsync();
                }

                Pause();
                await this.updateAccountBalances.ExecuteAsync(SubscriberId1, DateTime.UtcNow);
                Assert.AreEqual(1000, (await this.getCreditTransactionInformation.ExecuteAsync(transactionReference)).CreditAmountAvailableForRefund);
                Assert.AreEqual(1000, (await this.getAccountSettings.ExecuteAsync(SubscriberId1, DateTime.UtcNow, 0)).AccountBalance);
                Assert.AreEqual(200, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.SalesTax));
                Assert.AreEqual(-1200, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.Stripe));

                await this.persistCreditRefund.ExecuteAsync(
                    UserId.Random(),
                    SubscriberId1,
                    DateTime.UtcNow,
                    PositiveInt.Parse((int)(100 * Tax)),
                    PositiveInt.Parse(100),
                    transactionReference,
                    StripeChargeId,
                    TaxamoTransactionKey,
                    Comment);

                Pause();
                await this.updateAccountBalances.ExecuteAsync(SubscriberId1, DateTime.UtcNow);
                Assert.AreEqual(900, (await this.getCreditTransactionInformation.ExecuteAsync(transactionReference)).CreditAmountAvailableForRefund);
                Assert.AreEqual(900, (await this.getAccountSettings.ExecuteAsync(SubscriberId1, DateTime.UtcNow, 0)).AccountBalance);
                Assert.AreEqual(180, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.SalesTax));
                Assert.AreEqual(-1080, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.Stripe));

                await this.persistCreditRefund.ExecuteAsync(
                    UserId.Random(),
                    SubscriberId1,
                    DateTime.UtcNow,
                    PositiveInt.Parse((int)(500 * Tax)),
                    PositiveInt.Parse(500),
                    transactionReference,
                    StripeChargeId,
                    TaxamoTransactionKey,
                    Comment);

                Pause();
                await this.updateAccountBalances.ExecuteAsync(SubscriberId1, DateTime.UtcNow);
                Assert.AreEqual(400, (await this.getCreditTransactionInformation.ExecuteAsync(transactionReference)).CreditAmountAvailableForRefund);
                Assert.AreEqual(400, (await this.getAccountSettings.ExecuteAsync(SubscriberId1, DateTime.UtcNow, 0)).AccountBalance);
                Assert.AreEqual(80, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.SalesTax));
                Assert.AreEqual(-480, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.Stripe));

                await this.persistCreditRefund.ExecuteAsync(
                    UserId.Random(),
                    SubscriberId1,
                    DateTime.UtcNow,
                    PositiveInt.Parse((int)(400 * Tax)),
                    PositiveInt.Parse(400),
                    transactionReference,
                    StripeChargeId,
                    TaxamoTransactionKey,
                    Comment);

                Pause();
                await this.updateAccountBalances.ExecuteAsync(SubscriberId1, DateTime.UtcNow);
                Assert.AreEqual(0, (await this.getCreditTransactionInformation.ExecuteAsync(transactionReference)).CreditAmountAvailableForRefund);
                Assert.AreEqual(0, (await this.getAccountSettings.ExecuteAsync(SubscriberId1, DateTime.UtcNow, 0)).AccountBalance);
                Assert.AreEqual(0, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.SalesTax));
                Assert.AreEqual(0, await this.GetAccountBalance(SubscriberId1, LedgerAccountType.Stripe));

                await testDatabase.TakeSnapshotAsync();
                return(ExpectedSideEffects.None);
            });
        }
Ejemplo n.º 14
0
        public async Task WhenGettingPreviewNewsfeed_ItShouldReturnResultFromNewsfeedQuery()
        {
            var query       = new GetNewsfeedQuery(Requester, UserId, new[] { ChannelId }, Origin, SearchForwards, NonNegativeInt.Parse(10), PositiveInt.Parse(5));
            var requestData = new NewsfeedFilter
            {
                CreatorId      = UserId.Value.EncodeGuid(),
                ChannelId      = ChannelId.Value.EncodeGuid(),
                Origin         = Origin,
                SearchForwards = SearchForwards,
                Count          = 5,
                StartIndex     = 10
            };

            var queryResult = new GetPreviewNewsfeedQueryResult(new[] { new GetPreviewNewsfeedQueryResult.PreviewPost(UserId, new GetPreviewNewsfeedQueryResult.PreviewPostCreator(Username, null), PostId, BlogId, new GetPreviewNewsfeedQueryResult.PreviewPostBlog(BlogName, null, null), ChannelId, new GetPreviewNewsfeedQueryResult.PreviewPostChannel(ChannelName), new PreviewText(string.Empty), null, null, null, 0, 0, 0, 0, 0, DateTime.UtcNow, 0, 0, false, false) });

            this.requesterContext.Setup(_ => _.GetRequesterAsync()).ReturnsAsync(Requester);
            this.getPreviewNewsfeed.Setup(_ => _.HandleAsync(query)).ReturnsAsync(queryResult);

            var result = await this.target.GetPreviewNewsfeed(requestData);

            Assert.AreEqual(queryResult, result);
        }
Ejemplo n.º 15
0
 public PositiveInt ToPositiveInt()
 {
     return(PositiveInt.Parse(this.Value));
 }