Пример #1
0
        public async Task WhenUncommittedRecordHasZeroAmount_ItShouldPersistTheData()
        {
            byte guidIndex           = 0;
            byte sequentialGuidIndex = 0;

            this.guidCreator.Setup(v => v.Create()).Returns(() => this.CreateGuid(0, guidIndex++));
            this.guidCreator.Setup(v => v.CreateSqlSequential()).Returns(() => this.CreateGuid(1, sequentialGuidIndex++));

            var dataId         = this.CreateGuid(0, 0);
            var transactionId1 = this.CreateGuid(0, 1);
            var transactionId2 = this.CreateGuid(0, 2);
            var transactionId3 = this.CreateGuid(0, 3);

            var resultItems = new List <PaymentProcessingResult>(Results.Items);
            var uncommitted = resultItems.Last();

            resultItems[resultItems.Count - 1] = new PaymentProcessingResult(
                uncommitted.StartTimeInclusive,
                uncommitted.EndTimeExclusive,
                new AggregateCostSummary(0),
                uncommitted.CreatorPercentageOverride,
                false);
            var results = new PaymentProcessingResults(Results.CommittedAccountBalance, resultItems);

            this.persistPaymentProcessingData.Setup(
                v => v.ExecuteAsync(new PersistedPaymentProcessingData(dataId, Data, results)))
            .Returns(Task.FromResult(0));

            IReadOnlyList <AppendOnlyLedgerRecord> actualCommittedRecords  = null;
            UncommittedSubscriptionPayment         actualUncommittedRecord = null;

            this.persistCommittedAndUncommittedRecords.Setup(v => v.ExecuteAsync(SubscriberId, CreatorId, It.IsAny <IReadOnlyList <AppendOnlyLedgerRecord> >(), It.IsAny <UncommittedSubscriptionPayment>()))
            .Callback <UserId, UserId, IReadOnlyList <AppendOnlyLedgerRecord>, UncommittedSubscriptionPayment>(
                (s, c, a, b) =>
            {
                actualCommittedRecords  = a;
                actualUncommittedRecord = b;
            })
            .Returns(Task.FromResult(0));

            await this.target.ExecuteAsync(Data, results);

            CollectionAssert.AreEqual(
                new List <AppendOnlyLedgerRecord>
            {
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 0), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(1), -1m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 1), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(1), 1m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 2), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(1), -0.9m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 3), CreatorId.Value, CreatorId.Value, StartTimeInclusive.AddDays(1), 0.9m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 4), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(2), -2m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 5), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(2), 2m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 6), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(2), -1.6m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 7), CreatorId.Value, CreatorId.Value, StartTimeInclusive.AddDays(2), 1.6m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 8), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(3), 0m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId3, dataId, null, null, null),
            },
                actualCommittedRecords.ToList());

            Assert.IsNull(actualUncommittedRecord);
        }
Пример #2
0
        public async Task ItShouldPersistTheData()
        {
            byte guidIndex           = 0;
            byte sequentialGuidIndex = 0;

            this.guidCreator.Setup(v => v.Create()).Returns(() => this.CreateGuid(0, guidIndex++));
            this.guidCreator.Setup(v => v.CreateSqlSequential()).Returns(() => this.CreateGuid(1, sequentialGuidIndex++));

            var dataId         = this.CreateGuid(0, 0);
            var transactionId1 = this.CreateGuid(0, 1);
            var transactionId2 = this.CreateGuid(0, 2);
            var transactionId3 = this.CreateGuid(0, 3);

            this.persistPaymentProcessingData.Setup(
                v => v.ExecuteAsync(new PersistedPaymentProcessingData(dataId, Data, Results)))
            .Returns(Task.FromResult(0));

            IReadOnlyList <AppendOnlyLedgerRecord> actualCommittedRecords  = null;
            UncommittedSubscriptionPayment         actualUncommittedRecord = null;

            this.persistCommittedAndUncommittedRecords.Setup(v => v.ExecuteAsync(SubscriberId, CreatorId, It.IsAny <IReadOnlyList <AppendOnlyLedgerRecord> >(), It.IsAny <UncommittedSubscriptionPayment>()))
            .Callback <UserId, UserId, IReadOnlyList <AppendOnlyLedgerRecord>, UncommittedSubscriptionPayment>(
                (s, c, a, b) =>
            {
                actualCommittedRecords  = a;
                actualUncommittedRecord = b;
            })
            .Returns(Task.FromResult(0));

            await this.target.ExecuteAsync(Data, Results);

            CollectionAssert.AreEqual(
                new List <AppendOnlyLedgerRecord>
            {
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 0), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(1), -1m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 1), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(1), 1m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 2), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(1), -0.9m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 3), CreatorId.Value, CreatorId.Value, StartTimeInclusive.AddDays(1), 0.9m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId1, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 4), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(2), -2m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 5), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(2), 2m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 6), Guid.Empty, CreatorId.Value, StartTimeInclusive.AddDays(2), -1.6m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 7), CreatorId.Value, CreatorId.Value, StartTimeInclusive.AddDays(2), 1.6m, LedgerAccountType.FifthweekRevenue, LedgerTransactionType.SubscriptionPayment, transactionId2, dataId, null, null, null),
                new AppendOnlyLedgerRecord(this.CreateGuid(1, 8), SubscriberId.Value, CreatorId.Value, StartTimeInclusive.AddDays(3), 0m, LedgerAccountType.FifthweekCredit, LedgerTransactionType.SubscriptionPayment, transactionId3, dataId, null, null, null),
            },
                actualCommittedRecords.ToList());

            Assert.AreEqual(
                new UncommittedSubscriptionPayment(
                    SubscriberId.Value,
                    CreatorId.Value,
                    StartTimeInclusive.AddDays(3),
                    StartTimeInclusive.AddDays(4),
                    3,
                    dataId),
                actualUncommittedRecord);
        }
Пример #3
0
        public async Task ExecuteAsync(
            UserId subscriberId,
            UserId creatorId,
            IReadOnlyList <AppendOnlyLedgerRecord> ledgerRecords,
            UncommittedSubscriptionPayment uncommittedRecord)
        {
            subscriberId.AssertNotNull("subscriberId");
            creatorId.AssertNotNull("creatorId");
            ledgerRecords.AssertNotNull("ledgerRecords");

            using (PaymentsPerformanceLogger.Instance.Log(typeof(PersistCommittedAndUncommittedRecordsDbStatement)))
                using (var transaction = TransactionScopeBuilder.CreateAsync())
                {
                    using (var connection = this.connectionFactory.CreateConnection())
                    {
                        if (ledgerRecords.Any())
                        {
                            await connection.InsertAsync(ledgerRecords, false);
                        }

                        if (uncommittedRecord != null)
                        {
                            var uncommittedFields = UncommittedSubscriptionPayment.Fields.StartTimestampInclusive
                                                    | UncommittedSubscriptionPayment.Fields.EndTimestampExclusive
                                                    | UncommittedSubscriptionPayment.Fields.Amount
                                                    | UncommittedSubscriptionPayment.Fields.InputDataReference;

                            await connection.UpsertAsync(uncommittedRecord, uncommittedFields);
                        }
                        else
                        {
                            // Remove the existing uncommitted record.
                            await connection.ExecuteAsync(
                                string.Format(
                                    @"DELETE FROM {0} WHERE {1}=@SubscriberId AND {2}=@CreatorId",
                                    UncommittedSubscriptionPayment.Table,
                                    UncommittedSubscriptionPayment.Fields.SubscriberId,
                                    UncommittedSubscriptionPayment.Fields.CreatorId),
                                new
                            {
                                SubscriberId = subscriberId.Value,
                                CreatorId    = creatorId.Value
                            });
                        }
                    }

                    transaction.Complete();
                }
        }
Пример #4
0
        public async Task WhenNoCommittedRecords_ItShouldPersistTheDataButNotSaveBlob()
        {
            byte guidIndex           = 0;
            byte sequentialGuidIndex = 0;

            this.guidCreator.Setup(v => v.Create()).Returns(() => this.CreateGuid(0, guidIndex++));
            this.guidCreator.Setup(v => v.CreateSqlSequential()).Returns(() => this.CreateGuid(1, sequentialGuidIndex++));

            var dataId = this.CreateGuid(0, 0);

            var resultItems = new List <PaymentProcessingResult>(Results.Items);

            resultItems.Remove(resultItems.First());
            resultItems.Remove(resultItems.First());
            resultItems.Remove(resultItems.First());
            var results = new PaymentProcessingResults(Results.CommittedAccountBalance, resultItems);

            IReadOnlyList <AppendOnlyLedgerRecord> actualCommittedRecords  = null;
            UncommittedSubscriptionPayment         actualUncommittedRecord = null;

            this.persistCommittedAndUncommittedRecords.Setup(v => v.ExecuteAsync(SubscriberId, CreatorId, It.IsAny <IReadOnlyList <AppendOnlyLedgerRecord> >(), It.IsAny <UncommittedSubscriptionPayment>()))
            .Callback <UserId, UserId, IReadOnlyList <AppendOnlyLedgerRecord>, UncommittedSubscriptionPayment>(
                (s, c, a, b) =>
            {
                actualCommittedRecords  = a;
                actualUncommittedRecord = b;
            })
            .Returns(Task.FromResult(0));

            await this.target.ExecuteAsync(Data, results);

            CollectionAssert.AreEqual(
                new List <AppendOnlyLedgerRecord>(),
                actualCommittedRecords.ToList());

            Assert.AreEqual(
                new UncommittedSubscriptionPayment(
                    SubscriberId.Value,
                    CreatorId.Value,
                    StartTimeInclusive.AddDays(3),
                    StartTimeInclusive.AddDays(4),
                    3,
                    dataId),
                actualUncommittedRecord);
        }
Пример #5
0
        public async Task ExecuteAsync(PaymentProcessingData data, PaymentProcessingResults results)
        {
            data.AssertNotNull("data");
            results.AssertNotNull("results");

            var committedResults  = results.Items.Where(v => v.IsCommitted).ToList();
            var uncommittedResult = results.Items.SingleOrDefault(v => !v.IsCommitted);

            var dataId = this.guidCreator.Create();

            var committedRecords = new List <AppendOnlyLedgerRecord>();

            foreach (var result in committedResults)
            {
                var transactionId = this.guidCreator.Create();

                if (result.SubscriptionCost.Cost == 0)
                {
                    // A single zero record, so we know when to start processing from
                    // next time.
                    committedRecords.Add(new AppendOnlyLedgerRecord(
                                             this.guidCreator.CreateSqlSequential(),
                                             data.SubscriberId.Value,
                                             data.CreatorId.Value,
                                             result.EndTimeExclusive,
                                             0,
                                             LedgerAccountType.FifthweekCredit,
                                             LedgerTransactionType.SubscriptionPayment,
                                             transactionId,
                                             dataId,
                                             null,
                                             null,
                                             null));

                    continue;
                }

                committedRecords.Add(new AppendOnlyLedgerRecord(
                                         this.guidCreator.CreateSqlSequential(),
                                         data.SubscriberId.Value,
                                         data.CreatorId.Value,
                                         result.EndTimeExclusive,
                                         -result.SubscriptionCost.Cost,
                                         LedgerAccountType.FifthweekCredit,
                                         LedgerTransactionType.SubscriptionPayment,
                                         transactionId,
                                         dataId,
                                         null,
                                         null,
                                         null));

                committedRecords.Add(new AppendOnlyLedgerRecord(
                                         this.guidCreator.CreateSqlSequential(),
                                         Guid.Empty,
                                         data.CreatorId.Value,
                                         result.EndTimeExclusive,
                                         result.SubscriptionCost.Cost,
                                         LedgerAccountType.FifthweekRevenue,
                                         LedgerTransactionType.SubscriptionPayment,
                                         transactionId,
                                         dataId,
                                         null,
                                         null,
                                         null));

                var creatorPercentage = result.CreatorPercentageOverride == null
                                            ? Payments.Constants.DefaultCreatorPercentage
                                            : result.CreatorPercentageOverride.Percentage;

                var creatorPayment = result.SubscriptionCost.Cost * creatorPercentage;

                committedRecords.Add(new AppendOnlyLedgerRecord(
                                         this.guidCreator.CreateSqlSequential(),
                                         Guid.Empty,
                                         data.CreatorId.Value,
                                         result.EndTimeExclusive,
                                         -creatorPayment,
                                         LedgerAccountType.FifthweekRevenue,
                                         LedgerTransactionType.SubscriptionPayment,
                                         transactionId,
                                         dataId,
                                         null,
                                         null,
                                         null));

                committedRecords.Add(new AppendOnlyLedgerRecord(
                                         this.guidCreator.CreateSqlSequential(),
                                         data.CreatorId.Value,
                                         data.CreatorId.Value,
                                         result.EndTimeExclusive,
                                         creatorPayment,
                                         LedgerAccountType.FifthweekRevenue,
                                         LedgerTransactionType.SubscriptionPayment,
                                         transactionId,
                                         dataId,
                                         null,
                                         null,
                                         null));
            }

            UncommittedSubscriptionPayment uncommittedRecord = null;

            if (uncommittedResult != null && uncommittedResult.SubscriptionCost.Cost != 0)
            {
                uncommittedRecord = new UncommittedSubscriptionPayment(
                    data.SubscriberId.Value,
                    data.CreatorId.Value,
                    uncommittedResult.StartTimeInclusive,
                    uncommittedResult.EndTimeExclusive,
                    uncommittedResult.SubscriptionCost.Cost,
                    dataId);
            }

            if (committedRecords.Count > 0)
            {
                await this.persistPaymentProcessingData.ExecuteAsync(new PersistedPaymentProcessingData(dataId, data, results));
            }

            if (committedRecords.Count > 0 || uncommittedResult != null)
            {
                await this.persistCommittedAndUncommittedRecords.ExecuteAsync(data.SubscriberId, data.CreatorId, committedRecords, uncommittedRecord);
            }
        }