/// <summary> /// Adds a redemption reward for the transaction in the context. /// </summary> /// <param name="redeemedDealId"> /// The ID of the redeemed deal for which redemption rewards are granted. /// </param> /// <returns> /// A Task to perform the operation. /// </returns> private async Task AddRedemptionRewards(Guid redeemedDealId) { RedeemedDealInfo redeemedDealInfo = (RedeemedDealInfo)Context[Key.RedeemedDealInfo]; if (EnableRedemptionRewards == true && (ReimbursementTender)redeemedDealInfo.ReimbursementTenderId == ReimbursementTender.MicrosoftEarn) { ConcurrentDictionary <string, string> payload = new ConcurrentDictionary <string, string>(); IScheduler scheduler = PartnerFactory.Scheduler(CommerceWorkerConfig.Instance.SchedulerQueueName, CommerceWorkerConfig.Instance.SchedulerTableName, CommerceWorkerConfig.Instance); if (WorkerActions.RewardRedemption(RewardOperations, Context) == ResultCode.Success) { // Add a job to potentially reward user for their first Earn. payload[Key.RewardPayoutId.ToString()] = ((Guid)Context[Key.RewardPayoutId]).ToString(); payload[Key.PartnerCardId.ToString()] = (string)Context[Key.PartnerCardId]; payload[Key.PartnerRedeemedDealId.ToString()] = redeemedDealInfo.PartnerRedeemedDealId; payload[Key.RewardId.ToString()] = Context.Config.FirstEarnRewardId.ToString(); ScheduledJobDetails scheduledJobDetails = new ScheduledJobDetails { JobId = Guid.NewGuid(), JobType = ScheduledJobType.ApplyRedemptionReward, JobDescription = redeemedDealInfo.GlobalUserId.ToString(), Orchestrated = true, Payload = payload }; await scheduler.ScheduleJobAsync(scheduledJobDetails).ConfigureAwait(false); } // Add a job to potentially reward the person who referred this user for this user's first Earn. Context[Key.RedeemedDealId] = ((RedeemedDeal)Context[Key.RedeemedDeal]).Id; Guid globalUserId = ((RedeemedDealInfo)Context[Key.RedeemedDealInfo]).GlobalUserId; Context[Key.GlobalUserId] = globalUserId; string userId = globalUserId.ToString(); if (WorkerActions.RewardReferredRedemption(RewardOperations, Context) == ResultCode.Success) { payload[Key.GlobalUserId.ToString()] = userId; payload[Key.ReferralEvent.ToString()] = ReferralEvent.Signup.ToString(); ScheduledJobDetails scheduledJobDetails = new ScheduledJobDetails { JobId = Guid.NewGuid(), JobType = ScheduledJobType.ApplyReferralReward, JobDescription = userId, Orchestrated = true, StartTime = DateTime.UtcNow, Payload = payload }; await scheduler.ScheduleJobAsync(scheduledJobDetails).ConfigureAwait(false); } } }
/// <summary> /// Process the rewards if applicable /// </summary> /// <param name="settlementDetail"> /// Settlement Details /// </param> /// <returns> /// Async Task Wrapper /// </returns> internal async Task ProcessRewardPayoutAsync(SettlementDetail settlementDetail) { if (settlementDetail.TransactionType == TransactionType.SettlementRedemption) { // First add a redemption reward to the redeeming user if they're enabled. if (EnableRedemptionRewards == true && WorkerActions.RewardRedemption(RewardOperations, Context) == ResultCode.Success) { // Add job to process the reward payout. Note that this job will be scheduled 30 minutes in the // future to guard against applying a reward for a transaction that was reversed in a later // record. ConcurrentDictionary <string, string> payload = new ConcurrentDictionary <string, string>(); payload[Key.RewardPayoutId.ToString()] = ((Guid)Context[Key.RewardPayoutId]).ToString(); payload[Key.PartnerCardId.ToString()] = (string)Context[Key.PartnerCardId]; payload[Key.PartnerRedeemedDealId.ToString()] = settlementDetail.TransactionId; IScheduler scheduler = PartnerFactory.Scheduler(CommerceWorkerConfig.Instance.SchedulerQueueName, CommerceWorkerConfig.Instance.SchedulerTableName, CommerceWorkerConfig.Instance); ScheduledJobDetails scheduledJobDetails = new ScheduledJobDetails { JobId = Guid.NewGuid(), JobType = ScheduledJobType.ApplyRedemptionReward, JobDescription = settlementDetail.ConsumerId, Orchestrated = true, StartTime = DateTime.UtcNow.AddMinutes(30), Payload = payload }; await scheduler.ScheduleJobAsync(scheduledJobDetails).ConfigureAwait(false); } // Then add a referred redemption reward to the user who referred the redeeming user. WorkerActions.RewardReferredRedemption(RewardOperations, Context); } else { Context.Log.Verbose("No Bing Reward can be given for a reversed transaction."); } }
/// <summary> /// Process the transaction log file /// </summary> /// <returns> /// Async Task Wrapper /// </returns> public async Task Process() { TransactionLogParser transactionLogParser = new TransactionLogParser(Context.Log); TransactionLogFile transactionLogFile = transactionLogParser.Parse(TransactionLogFileName, TransactionLogFileStream); if (transactionLogFile != null) { foreach (TransactionLogDetail detail in transactionLogFile.TransactionLogRecords) { // block the reversed transactions if (TransactionIdSet.Contains(detail.TransactionId) || detail.TransactionAmount <= 0) { continue; } TransactionIdSet.Add(detail.TransactionId); // 1. process the detail record here -> Insert as redeemed deal RedeemedDeal redeemedDeal = new RedeemedDeal() { AnalyticsEventId = Guid.NewGuid() }; Context[Key.RedeemedDeal] = redeemedDeal; MarshalRedeemDeal(detail); ResultCode result = RedeemedDealOperations.AddRedeemedDeal(); //2. If the record was processed successfully, attempt to add a redemption reward if applicable and analytics if (result == ResultCode.Created) { RedeemedDealInfo redemptionInfo = (RedeemedDealInfo)Context[Key.RedeemedDealInfo]; // First add a redemption reward to the redeeming user if they're enabled. if (EnableRedemptionRewards) { if (WorkerActions.RewardRedemption(RewardOperations, Context) == ResultCode.Success) { // Add job to process the reward payout. ConcurrentDictionary <string, string> payload = new ConcurrentDictionary <string, string>(); payload[Key.RewardPayoutId.ToString()] = ((Guid)Context[Key.RewardPayoutId]).ToString(); payload[Key.PartnerCardId.ToString()] = (string)Context[Key.PartnerCardId]; payload[Key.PartnerRedeemedDealId.ToString()] = redemptionInfo.PartnerRedeemedDealId; IScheduler scheduler = PartnerFactory.Scheduler(CommerceWorkerConfig.Instance.SchedulerQueueName, CommerceWorkerConfig.Instance.SchedulerTableName, CommerceWorkerConfig.Instance); ScheduledJobDetails scheduledJobDetails = new ScheduledJobDetails { JobId = Guid.NewGuid(), JobType = ScheduledJobType.ApplyRedemptionReward, JobDescription = redemptionInfo.GlobalUserId.ToString(), Orchestrated = true, Payload = payload }; await scheduler.ScheduleJobAsync(scheduledJobDetails).ConfigureAwait(false); } } // Then add a referred redemption reward to the user who referred the redeeming user. Context[Key.RedeemedDealId] = ((RedeemedDeal)Context[Key.RedeemedDeal]).Id; Context[Key.GlobalUserId] = ((RedeemedDealInfo)Context[Key.RedeemedDealInfo]).GlobalUserId; WorkerActions.RewardReferredRedemption(RewardOperations, Context); // Update analytics. // For FDC this happens at AUTH time // Butfor Amex flow, we put analytics at the time of Transaction File Processing SharedUserLogic sharedUserLogic = new SharedUserLogic(Context, CommerceOperationsFactory.UserOperations(Context)); Context[Key.GlobalUserId] = redemptionInfo.GlobalUserId; User user = sharedUserLogic.RetrieveUser(); Analytics.AddRedemptionEvent(redemptionInfo.GlobalUserId, redeemedDeal.AnalyticsEventId, user.AnalyticsEventId, redemptionInfo.ParentDealId, redemptionInfo.Currency, redeemedDeal.AuthorizationAmount, redemptionInfo.DiscountAmount, redemptionInfo.GlobalId, (string)Context[Key.PartnerMerchantId], CommerceWorkerConfig.Instance); } } } }