Beispiel #1
0
        /// <summary>
        /// Marshals information from the MasterCard clearing data record into the RedeemedDeal object in the context.
        /// </summary>
        /// <param name="clearingData">
        /// The clearing data record to marshal.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Parameter clearingData cannot be null.
        /// </exception>
        public void MarshalRedeemDeal(ClearingData clearingData)
        {
            if (clearingData == null)
            {
                throw new ArgumentNullException("clearingData", "Parameter clearingData cannot be null.");
            }

            RedeemedDeal redeemedDeal = (RedeemedDeal)Context[Key.RedeemedDeal];

            redeemedDeal.CallbackEvent              = RedemptionEvent.Settlement;
            redeemedDeal.PurchaseDateTime           = clearingData.TransactionDate;
            redeemedDeal.AuthorizationAmount        = (int)(clearingData.TransactionAmount * 100);
            redeemedDeal.Currency                   = "USD";
            redeemedDeal.PartnerRedeemedDealScopeId = clearingData.BankNetRefNumber;

            KeyClearingData keyClearingData = new KeyClearingData
            {
                BankCustomerNumber = clearingData.BankCustomerNumber,
                BankNetRefNumber   = clearingData.BankNetRefNumber,
                MerchantId         = clearingData.MerchantId,
                IssuerIca          = clearingData.IssuerIca
            };

            Context[Key.PartnerData] = keyClearingData.XmlSerialize();

            Context[Key.PartnerCardId]          = clearingData.BankCustomerNumber;
            Context[Key.PartnerMerchantId]      = clearingData.LocationId;
            Context[Key.PartnerMerchantIdType]  = PartnerMerchantIdType.SettlementOnly;
            Context[Key.CreditStatus]           = CreditStatus.ClearingReceived;
            Context[Key.PartnerReferenceNumber] = clearingData.TransactionSequenceNumber;
        }
        /// <summary>
        /// Processes the clearing file.
        /// </summary>
        public async virtual Task Process()
        {
            // Deserialize clearing file into a Clearing object.
            ClearingParser clearingParser = new ClearingParser(Context.Log);
            Clearing       clearing       = clearingParser.Parse(FileName, Stream);

            if (clearing != null)
            {
                foreach (ClearingData clearingData in clearing.DataRecords)
                {
                    if (clearingData != null)
                    {
                        // Add a redeemed deal record to the data store for the transaction.
                        RedeemedDeal redeemedDeal = new RedeemedDeal();
                        ResultCode   result       = AddRedeemedDealRecord(clearingData, redeemedDeal);

                        // If the redeemed deal record was added successfully, update rewards.
                        if (result == ResultCode.Created)
                        {
                            await AddRedemptionRewards(redeemedDeal.Id).ConfigureAwait(false);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds a RedeemedDeal record to the data store for the specified ClearingData record.
        /// </summary>
        /// <param name="clearingData">
        /// The ClearingData record for which to add a redeemed deal record.
        /// </param>
        /// <param name="redeemedDeal">
        /// The RedeemedDeal object to use when committing the redeemed deal record.
        /// </param>
        /// <returns>
        /// The ResultCode corresponding to the result of the operation.
        /// </returns>
        private ResultCode AddRedeemedDealRecord(ClearingData clearingData,
                                                 RedeemedDeal redeemedDeal)
        {
            ResultCode result = ResultCode.NoApplicableDealFound;

            redeemedDeal.AnalyticsEventId = Guid.NewGuid();
            Context[Key.RedeemedDeal]     = redeemedDeal;
            new MasterCard(Context).MarshalRedeemDeal(clearingData);
            Context[Key.Partner] = Partner.MasterCard;
            result = RedeemedDealOperations.AddRedeemedDeal();

            return(result);
        }
        /// <summary>
        /// Updates analytics with information about the transaction in the context.
        /// </summary>
        private void UpdateAnalytics()
        {
            RedeemedDealInfo redeemedDealInfo = (RedeemedDealInfo)Context[Key.RedeemedDealInfo];
            SharedUserLogic  sharedUserLogic  = new SharedUserLogic(Context, CommerceOperationsFactory.UserOperations(Context));

            Context[Key.GlobalUserId] = redeemedDealInfo.GlobalUserId;
            User         user         = sharedUserLogic.RetrieveUser();
            RedeemedDeal redeemedDeal = (RedeemedDeal)Context[Key.RedeemedDeal];

            Analytics.AddRedemptionEvent(redeemedDealInfo.GlobalUserId, redeemedDeal.AnalyticsEventId, user.AnalyticsEventId,
                                         redeemedDealInfo.ParentDealId, redeemedDealInfo.Currency,
                                         redeemedDeal.AuthorizationAmount, redeemedDealInfo.DiscountAmount,
                                         redeemedDealInfo.GlobalId, (string)Context[Key.PartnerMerchantId],
                                         CommerceWorkerConfig.Instance);
        }
        /// <summary>
        /// Marshal Transaction Log File Record into a RedeemedDeal Record
        /// </summary>
        /// <param name="detail">
        /// Transaction Log File Detail Record
        /// </param>
        private void MarshalRedeemDeal(TransactionLogDetail detail)
        {
            RedeemedDeal redeemedDeal = (RedeemedDeal)Context[Key.RedeemedDeal];

            redeemedDeal.CallbackEvent              = RedemptionEvent.Settlement;
            redeemedDeal.PurchaseDateTime           = detail.TransactionDate;
            redeemedDeal.AuthorizationAmount        = (int)(detail.TransactionAmount * 100);
            redeemedDeal.Currency                   = "USD";
            redeemedDeal.PartnerRedeemedDealScopeId = detail.TransactionId;
            //redeemedDeal.PartnerRedeemedDealId = detail.TransactionId;

            Context[Key.PartnerDealId]     = detail.OfferId;
            Context[Key.PartnerCardId]     = detail.CardToken;
            Context[Key.PartnerMerchantId] = detail.MerchantNumber;
            Context[Key.CreditStatus]      = CreditStatus.ClearingReceived;
        }
        /// <summary>
        /// Taken down the parameters used to call the addReedemedDeal stored procedure
        /// </summary>
        /// <param name="redeemedDeal">RedeemedDeal just populated</param>
        private void LogRedeedmedDealRequestParameters(RedeemedDeal redeemedDeal)
        {
            String request = String.Format("ReededmedDealRequest: {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}",
                                           redeemedDeal.Id,
                                           (int)Context[Key.Partner],
                                           Context[Key.PartnerDealId],
                                           Context[Key.PartnerCardId],
                                           Context[Key.PartnerClaimedDealId],
                                           Context[Key.PartnerMerchantId],
                                           Context[Key.OutletPartnerMerchantId],
                                           (int)(redeemedDeal.CallbackEvent),
                                           redeemedDeal.PurchaseDateTime.ToString(),
                                           redeemedDeal.AuthorizationAmount,
                                           redeemedDeal.Currency,
                                           redeemedDeal.PartnerRedeemedDealId,
                                           redeemedDeal.AnalyticsEventId,
                                           Context[Key.CreditStatus]);

            Context.Log.Verbose(request);
        }
        /// <summary>
        ///     Executes processing of the request.
        /// </summary>
        public ResultCode Execute()
        {
            ResultCode                  result  = ResultCode.None;
            EndPointMessageRequest      request = (EndPointMessageRequest)Context[Key.Request];
            Dictionary <String, String> messageElementCollectionDictionary = new Dictionary <string, string>();

            foreach (MessageElementsCollection c in request.MessageElementsCollection)
            {
                messageElementCollectionDictionary.Add(c.Key, c.Value);
            }

            String requestType = messageElementCollectionDictionary[VisaEPMConstants.EventEventType];

            if (string.Equals(requestType, VisaEPMConstants.OnClearEventTypeValue, StringComparison.OrdinalIgnoreCase))
            {
                Dictionary <String, String> userDefinedFieldsCollectionDictionary = new Dictionary <string, string>();
                foreach (UserDefinedFieldsCollection c in request.UserDefinedFieldsCollection)
                {
                    userDefinedFieldsCollectionDictionary.Add(c.Key, c.Value);
                }

                String cardId     = request.CardId;
                String merchantId = messageElementCollectionDictionary[VisaEPMConstants.TransactionVisaMerchantId];
                String storeId    = messageElementCollectionDictionary[VisaEPMConstants.TransactionVisaStoreId];

                // Marshal the redeem deal request into a RedeemedDeal object.
                RedeemedDeal redeemedDeal = new RedeemedDeal()
                {
                    AnalyticsEventId = Guid.NewGuid()
                };
                Context[Key.RedeemedDeal] = redeemedDeal;

                redeemedDeal.CallbackEvent = RedemptionEvent.Settlement;
                redeemedDeal.PartnerRedeemedDealScopeId = messageElementCollectionDictionary[VisaEPMConstants.TransactionVipTransactionId];
                redeemedDeal.PartnerRedeemedDealId      =
                    messageElementCollectionDictionary[VisaEPMConstants.TransactionTransactionID];
                String time = messageElementCollectionDictionary[VisaEPMConstants.TransactionTimeStampYYMMDD];
                // UTC Time: 2013-12-05T07:25:06
                redeemedDeal.PurchaseDateTime = DateTime.Parse(time);
                redeemedDeal.PurchaseDateTime = DateTime.SpecifyKind(redeemedDeal.PurchaseDateTime, DateTimeKind.Utc);
                String amount = messageElementCollectionDictionary[VisaEPMConstants.TransactionClearingAmount];
                redeemedDeal.AuthorizationAmount = AmexUtilities.ParseAuthAmount(amount);
                redeemedDeal.Currency            = VisaConstants.CurrencyUSD;

                Context[Key.PartnerCardId]           = cardId;
                Context[Key.PartnerClaimedDealId]    = null; // could be the BingOfferDealId
                Context[Key.PartnerMerchantId]       = string.Format("{0};{1}", merchantId, storeId);
                Context[Key.OutletPartnerMerchantId] = null; // storedId;
                Context[Key.CreditStatus]            = CreditStatus.ClearingReceived;

                string merchantCity       = messageElementCollectionDictionary.NullIfNotExist(VisaEPMConstants.MerchantCityString);
                string merchantState      = messageElementCollectionDictionary.NullIfNotExist(VisaEPMConstants.MerchantStateString);
                var    merchantPostalCode = messageElementCollectionDictionary.NullIfNotExist(VisaEPMConstants.MerchantPostalCodeString);

                KeyTransactionData keyTransactionData = new KeyTransactionData
                {
                    MerchantCity       = merchantCity,
                    MerchantState      = merchantState,
                    MerchantPostalCode = merchantPostalCode
                };

                Context[Key.PartnerData] = keyTransactionData.XmlSerialize();

                LogRedeedmedDealRequestParameters(redeemedDeal);

                result = AddRedeemedDeal();
                Context[Key.ResultCode] = result;

                // If the deal was successfully redeemed, apply any applicable rewards.
                if (result == ResultCode.Created)
                {
                    RedeemedDealInfo redeemedDealInfo = (RedeemedDealInfo)Context[Key.RedeemedDealInfo];
                    if (redeemedDealInfo != null)
                    {
                        // Update analytics.
                        SharedUserLogic sharedUserLogic = new SharedUserLogic(Context,
                                                                              CommerceOperationsFactory.UserOperations(
                                                                                  Context));
                        Context[Key.GlobalUserId] = redeemedDealInfo.GlobalUserId;
                        User user = sharedUserLogic.RetrieveUser();
                        if (user != null)
                        {
                            Analytics.AddRedemptionEvent(redeemedDealInfo.GlobalUserId, redeemedDeal.AnalyticsEventId,
                                                         user.AnalyticsEventId,
                                                         redeemedDealInfo.ParentDealId, redeemedDealInfo.Currency,
                                                         redeemedDeal.AuthorizationAmount,
                                                         redeemedDealInfo.DiscountAmount,
                                                         redeemedDealInfo.GlobalId, (string)Context[Key.PartnerMerchantId]);
                        }

                        // Add rewards for any active rewards program.
                        AddRedemptionRewards();
                    }
                }
            }
            return(result);
        }
        /// <summary>
        /// Executes processing of the deal redemption request.
        /// </summary>
        public ResultCode Execute()
        {
            ResultCode result;

            // Marshal the First Data redeem deal request into a RedeemedDeal object.
            RedeemedDeal redeemedDeal = new RedeemedDeal()
            {
                AnalyticsEventId = Guid.NewGuid()
            };

            Context[Key.RedeemedDeal] = redeemedDeal;
            FirstData firstData = new FirstData(Context);

            firstData.MarshalRedeemDeal();

            // If the purchase date and time was valid, Add the RedeemedDeal to the data store.
            if (redeemedDeal.PurchaseDateTime != DateTime.MinValue)
            {
                string disallowedReason = Context[Key.DisallowedReason] as string;
                if (String.IsNullOrWhiteSpace(disallowedReason) == true)
                {
                    result = AddRedeemedDeal();
                }
                else
                {
                    Context.Log.Warning("Transaction is disallowed because tender type was: {0}.", disallowedReason);
                    Context[Key.RedeemedDealInfo] = new RedeemedDealInfo
                    {
                        PartnerDealId        = (string)Context[Key.PartnerDealId],
                        PartnerClaimedDealId = (string)Context[Key.PartnerClaimedDealId]
                    };
                    result = ResultCode.TransactionDisallowed;
                }
            }
            else
            {
                result = ResultCode.InvalidPurchaseDateTime;
            }

            // Build the response to send back to First Data based on the result of adding the RedeemedDeal.
            Context[Key.ResultCode] = result;
            firstData.BuildRedeemedDealResponse();

            // If the deal was successfully redeemed, send user notification and update analytics.
            if (result == ResultCode.Created)
            {
                RedeemedDealInfo redeemedDealInfo = (RedeemedDealInfo)Context[Key.RedeemedDealInfo];

                // Send notification.
                NotifyAuthorization notifyAuthorization = new NotifyAuthorization(Context);
                Task.Run(new Action(notifyAuthorization.SendNotification));

                // Update analytics.
                SharedUserLogic sharedUserLogic = new SharedUserLogic(Context,
                                                                      CommerceOperationsFactory.UserOperations(Context));
                Context[Key.GlobalUserId] = redeemedDealInfo.GlobalUserId;
                User user = sharedUserLogic.RetrieveUser();
                Analytics.AddRedemptionEvent(redeemedDealInfo.GlobalUserId, redeemedDeal.AnalyticsEventId, user.AnalyticsEventId,
                                             redeemedDealInfo.ParentDealId, redeemedDealInfo.Currency,
                                             redeemedDeal.AuthorizationAmount, redeemedDealInfo.DiscountAmount,
                                             redeemedDealInfo.GlobalId, (string)Context[Key.PartnerMerchantId]);
            }

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