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); }
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); }
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(); } }
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); }
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); } }