Beispiel #1
0
        public Task<PaymentProcessingResults> ExecuteAsync(PaymentProcessingData data)
        {
            using (PaymentsPerformanceLogger.Instance.Log(typeof(ProcessPaymentProcessingData)))
            {
                data.AssertNotNull("data");

                var subscriberId = data.SubscriberId;
                var creatorId = data.CreatorId;
                DateTime startTimeInclusive = data.StartTimeInclusive;
                DateTime endTimeExclusive = data.EndTimeExclusive;
                IReadOnlyList<ISnapshot> orderedSnapshots = data.GetOrderedSnapshots();
                IReadOnlyList<CreatorPost> posts = data.CreatorPosts;

                var committedAccountBalance = data.CommittedAccountBalance;

                var currentStartTimeInclusive = startTimeInclusive;
                var currentEndTimeExclusive = startTimeInclusive.AddDays(7);

                // This is the final time at which we can be totally sure if the creator
                // has posted in the billing week, as the subscriber billing week most likely
                // doesn't line up with the payment billing week.
                var committedRecordsEndTimeExclusive = endTimeExclusive.AddDays(-7);

                var result = new List<PaymentProcessingResult>();
                while (currentEndTimeExclusive <= committedRecordsEndTimeExclusive)
                {
                    // Calculate complete week.
                    var cost = this.subscriberPaymentPipeline.CalculatePayment(
                        orderedSnapshots,
                        posts,
                        subscriberId,
                        creatorId,
                        currentStartTimeInclusive,
                        currentEndTimeExclusive);

                    if (cost.Cost > committedAccountBalance.Amount)
                    {
                        cost = new AggregateCostSummary(committedAccountBalance.Amount);
                    }

                    committedAccountBalance = committedAccountBalance.Subtract(cost.Cost);

                    var creatorPercentageOverride = PaymentProcessingUtilities.GetCreatorPercentageOverride(
                        data.CreatorPercentageOverride,
                        currentEndTimeExclusive);

                    result.Add(new PaymentProcessingResult(currentStartTimeInclusive, currentEndTimeExclusive, cost, creatorPercentageOverride, true));

                    currentStartTimeInclusive = currentEndTimeExclusive;
                    currentEndTimeExclusive = currentStartTimeInclusive.AddDays(7);
                }

                if (currentStartTimeInclusive < endTimeExclusive)
                {
                    // Calculate uncommitted period.
                    // We calculate without taking into account CreatorPosts,
                    // as we assume they will post until we can be totally sure
                    // know otherwise.
                    var cost = this.subscriberPaymentPipeline.CalculatePayment(
                        orderedSnapshots,
                        null,
                        subscriberId,
                        creatorId,
                        currentStartTimeInclusive,
                        endTimeExclusive);

                    var creatorPercentageOverride = PaymentProcessingUtilities.GetCreatorPercentageOverride(
                        data.CreatorPercentageOverride,
                        endTimeExclusive);

                    result.Add(new PaymentProcessingResult(currentStartTimeInclusive, endTimeExclusive, cost, creatorPercentageOverride, false));
                }

                return Task.FromResult(new PaymentProcessingResults(committedAccountBalance, result));
            }
        }
Beispiel #2
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);
            }
        }