Esempio n. 1
0
            /// <summary>
            /// Calculates the loyalty reward points for a given transaction.
            /// </summary>
            /// <param name="request">The request containing the transaction.</param>
            /// <returns>The response containing the transaction with calculated reward points.</returns>
            private static CalculateLoyaltyRewardPointsServiceResponse CalculateLoyaltyRewardPoints(CalculateLoyaltyRewardPointsServiceRequest request)
            {
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }

                if (request.SalesTransaction == null)
                {
                    throw new ArgumentNullException("request", "request.SalesTransaction");
                }

                // Calculate loyalty only when the loyalty card number exists.
                // Calculate loyalty only when the transaction type is Sales (i.e. Cash and carry).
                // Other transactions such as PendingOrder and CustomerOrder will calculate in HQ after invoicing.
                var loyaltyCardNumber = request.SalesTransaction.LoyaltyCardId;

                if (!string.IsNullOrWhiteSpace(loyaltyCardNumber) &&
                    request.SalesTransaction.TransactionType == Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesTransactionType.Sales)
                {
                    // Clear existing reward point lines.
                    if (request.SalesTransaction.LoyaltyRewardPointLines != null && request.SalesTransaction.LoyaltyRewardPointLines.Count > 0)
                    {
                        IEnumerable <LoyaltyRewardPointLine> otherLines = request.SalesTransaction.LoyaltyRewardPointLines.Where <LoyaltyRewardPointLine>(
                            l => (l.EntryType != LoyaltyRewardPointEntryType.Earn && l.EntryType != LoyaltyRewardPointEntryType.ReturnEarned));
                        request.SalesTransaction.LoyaltyRewardPointLines = new Collection <LoyaltyRewardPointLine>(otherLines.ToList());
                    }

                    // Find the applied earn scheme lines of the current channel
                    var getLoyaltySchemeLineEarnDataRequest = new GetLoyaltySchemeLineEarnDataRequest(request.RequestContext.GetPrincipal().ChannelId, loyaltyCardNumber);
                    getLoyaltySchemeLineEarnDataRequest.QueryResultSettings = QueryResultSettings.AllRecords;
                    var earnSchemeLines = request.RequestContext.Execute <EntityDataServiceResponse <LoyaltySchemeLineEarn> >(getLoyaltySchemeLineEarnDataRequest).PagedEntityCollection.Results;

                    // Calculate returned reward points, deduct points first before earn new points
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForReturn(request.RequestContext, request.SalesTransaction, earnSchemeLines, loyaltyCardNumber);

                    // Calculate earned reward points
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForSales(request.RequestContext, request.SalesTransaction, earnSchemeLines, loyaltyCardNumber);
                }

                var response = new CalculateLoyaltyRewardPointsServiceResponse(request.SalesTransaction);

                return(response);
            }
            /// <summary>
            /// Authorizes the payment.
            /// This step checks whether the loyalty card has enough reward points to redeem. If yes, it decides the points
            /// to redeem based on redeem ranking.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>A response containing the authorized tender line.</returns>
            private static AuthorizePaymentServiceResponse AuthorizePayment(AuthorizePaymentServiceRequest request)
            {
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }

                if (request.TenderLine == null)
                {
                    throw new ArgumentException("request.TenderLine cannot be null.");
                }

                if (request.RequestContext == null)
                {
                    throw new ArgumentException("request.RequestContext cannot be null.");
                }

                if (request.Transaction == null)
                {
                    throw new ArgumentException("request.Transaction cannot be null.");
                }

                // Check tender amount.
                if (request.TenderLine.Amount == 0m)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "The tender amount must be greater than zero.");
                }

                // Check tender currency.
                if (string.IsNullOrWhiteSpace(request.TenderLine.Currency))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "The tender currency is missing.");
                }

                // Check if the transaction already has loyalty payments
                var activeTenderLines = request.Transaction.ActiveTenderLines;

                if (activeTenderLines != null && activeTenderLines.Any(line => !string.IsNullOrWhiteSpace(line.LoyaltyCardId)))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoMoreThanOneLoyaltyTender, "The transaction cannot contain more than one loyalty payment line.");
                }

                SalesOrder salesOrder = request.Transaction as SalesOrder;

                if (salesOrder != null && salesOrder.HasLoyaltyPayment &&
                    (salesOrder.CustomerOrderMode != CustomerOrderMode.Cancellation || salesOrder.AmountDue > decimal.Zero))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoMoreThanOneLoyaltyTender, "The transaction cannot contain more than one loyalty payment line.");
                }

                // Check whether the loyalty card is valid.
                var         getLoyaltyCardDataRequest = new GetLoyaltyCardDataRequest(request.TenderLine.LoyaltyCardId);
                LoyaltyCard loyaltyCard = request.RequestContext.Execute <SingleEntityDataServiceResponse <LoyaltyCard> >(getLoyaltyCardDataRequest).Entity;

                if (loyaltyCard == null || string.IsNullOrWhiteSpace(loyaltyCard.CardNumber))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidLoyaltyCardNumber, "The loyalty card number does not exists.");
                }

                // Check whether the loyalty card is blocked.
                if (loyaltyCard.CardTenderType == LoyaltyCardTenderType.Blocked)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_BlockedLoyaltyCard, "The loyalty card is blocked.");
                }

                if (loyaltyCard.CardTenderType == LoyaltyCardTenderType.NoTender)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoTenderLoyaltyCard, "The loyalty card is not allowed for payment.");
                }

                // Calculate redeem trans and fill in the sales transaction.
                if (request.TenderLine.Amount >= 0)
                {
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForPayment(
                        request.RequestContext,
                        request.Transaction,
                        loyaltyCard,
                        request.TenderLine.Amount,
                        request.TenderLine.Currency);
                }
                else
                {
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForRefund(
                        request.RequestContext,
                        request.Transaction,
                        loyaltyCard,
                        request.TenderLine.Amount,
                        request.TenderLine.Currency);
                }

                // Set Card Type Id for Loyalty Card if not set by the client.
                if (request.TenderLine.CardTypeId == null)
                {
                    string tenderTypeId                  = request.TenderLine.TenderTypeId;
                    var    cardTypeDataRequest           = new GetCardTypeDataRequest(QueryResultSettings.AllRecords);
                    var    cardTypeInfoResponse          = request.RequestContext.Execute <EntityDataServiceResponse <CardTypeInfo> >(cardTypeDataRequest);
                    IEnumerable <CardTypeInfo> cardTypes = cardTypeInfoResponse.PagedEntityCollection.Results;
                    CardTypeInfo loyaltyCardTypeInfo     = cardTypes.FirstOrDefault(cardType => cardType.PaymentMethodId == tenderTypeId);
                    if (loyaltyCardTypeInfo == null)
                    {
                        throw new ConfigurationException(ConfigurationErrors.Microsoft_Dynamics_Commerce_Runtime_ConfigurationSettingNotFound, "The loyalty card payment as a tender type card is not configured for the channel.");
                    }

                    request.TenderLine.CardTypeId = loyaltyCardTypeInfo.TypeId;
                }

                // Authorize.
                request.TenderLine.Status     = TenderLineStatus.PendingCommit;
                request.TenderLine.IsVoidable = true;

                return(new AuthorizePaymentServiceResponse(request.TenderLine));
            }