/// <summary>
            /// Populates the sales transaction.
            /// </summary>
            /// <param name="context">The context.</param>
            /// <param name="cartId">The cart id.</param>
            /// <param name="email">The email.</param>
            /// <param name="salesTransaction">The sales transaction.</param>
            private static void PopulateSalesTransaction(RequestContext context, string cartId, string email, out SalesTransaction salesTransaction)
            {
                salesTransaction = CartWorkflowHelper.LoadSalesTransaction(context, cartId);

                if (salesTransaction == null)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, cartId);
                }

                salesTransaction.ReceiptEmail    = email;
                salesTransaction.TransactionType = SalesTransactionType.PendingSalesOrder;

                if (string.IsNullOrEmpty(salesTransaction.ReceiptEmail))
                {
                    throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_RequiredValueNotFound, "Receipt email must be provided.");
                }

                OrderWorkflowHelper.FillTransactionWithContextData(context, salesTransaction);
            }
            /// <summary>
            /// Creates a sales transaction given the cart.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            protected override SubmitSalesTransactionResponse Process(SubmitSalesTransactionRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.Null(request.CartId, "request.CartId");

                // Get the Sales Transaction
                SalesTransaction salesTransaction = CartWorkflowHelper.LoadSalesTransaction(this.Context, request.CartId);

                if (salesTransaction == null)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, request.CartId);
                }

                if (salesTransaction.IsSuspended)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotActive, request.CartId);
                }

                if (!(salesTransaction.TerminalId ?? string.Empty).Equals(this.Context.GetTerminal().TerminalId ?? string.Empty, StringComparison.OrdinalIgnoreCase))
                {
                    // If the terminal id of the cart is not same as the context then it means that the cart is active on another terminal.
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_LoadingActiveCartFromAnotherTerminalNotAllowed, request.CartId);
                }

                salesTransaction.ReceiptEmail = request.ReceiptEmail;

                // Set the transaction type to represent Cash & Carry sales by default, if it's not an IncomeExpense nor AccountDeposit transaction.
                if (salesTransaction.TransactionType != SalesTransactionType.IncomeExpense && salesTransaction.TransactionType != SalesTransactionType.CustomerAccountDeposit)
                {
                    salesTransaction.TransactionType = SalesTransactionType.Sales;
                }

                // Fill in Store and Terminal information.
                OrderWorkflowHelper.FillTransactionWithContextData(this.Context, salesTransaction);

                // Calculate required reason code for end of transaction.
                ReasonCodesWorkflowHelper.CalculateRequiredReasonCodesOnTransaction(this.Context, salesTransaction, ReasonCodeSourceType.EndOfTransaction);

                // Validate required reason code lines has been filled.
                ReasonCodesWorkflowHelper.ValidateRequiredReasonCodeLinesFilled(this.Context, salesTransaction);

                // Validate return permission.
                CartWorkflowHelper.ValidateReturnPermission(this.Context, salesTransaction, salesTransaction.CartType);

                // Fill in variant information.
                OrderWorkflowHelper.FillVariantInformation(this.Context, salesTransaction);

                // Fill in Receipt Id.
                OrderWorkflowHelper.FillInReceiptId(this.Context, salesTransaction, request.ReceiptNumberSequence);

                // Validate sales order for creation.
                OrderWorkflowHelper.ValidateContextForCreateOrder(this.Context, salesTransaction);

                // Validate payments.
                OrderWorkflowHelper.CalculateAndValidateAmountPaidForCheckout(this.Context, salesTransaction);

                salesTransaction = OrderWorkflowHelper.ProcessCheckoutPayments(this.Context, salesTransaction);

                // release/unlock gift cards on sales lines
                GiftCardWorkflowHelper.UnlockGiftCardsOnActiveSalesLines(this.Context, salesTransaction);

                // Pay Sales Invoices...
                OrderWorkflowHelper.SettleInvoiceSalesLines(this.Context, salesTransaction);

                // Create order
                var salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction);

                // We also need to delete the shopping cart.
                CartWorkflowHelper.TryDeleteCart(
                    this.Context,
                    new SalesTransaction
                {
                    Id         = salesTransaction.Id,
                    TerminalId = salesTransaction.TerminalId,
                    CustomerId = salesTransaction.CustomerId,
                });

                return(new SubmitSalesTransactionResponse(salesOrder));
            }
            /// <summary>
            /// Creates a sales transaction given the cart.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            protected override SaveVoidTransactionResponse Process(SaveVoidTransactionRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.Null(request.CartId, "request.CartId");

                // Get the Sales Transaction
                SalesTransaction salesTransaction = CartWorkflowHelper.LoadSalesTransaction(this.Context, request.CartId, ignoreProductDiscontinuedNotification: true);

                if (salesTransaction == null)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, request.CartId);
                }

                if (salesTransaction.IsSuspended)
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotActive, request.CartId);
                }

                // If there are unvoided non-historical Tender lines throw exception that Transaction cannot be voided.
                if (salesTransaction.TenderLines != null && salesTransaction.TenderLines.Any(l => l.TransactionStatus != TransactionStatus.Voided && l.Status != TenderLineStatus.Historical))
                {
                    throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_VoidTransactionContainsTenderedLines, request.CartId);
                }

                // Add or update any incoming reason codes on the transaction.
                Cart cartToBeVoided = new Cart
                {
                    Id = request.CartId
                };

                if (request.ReasonCodeLines != null)
                {
                    cartToBeVoided.ReasonCodeLines = request.ReasonCodeLines.ToList();
                }

                ReasonCodesWorkflowHelper.AddOrUpdateReasonCodeLinesOnTransaction(salesTransaction, cartToBeVoided);

                // Calculate the required reason codes on the tender line for voiding transaction.
                ReasonCodesWorkflowHelper.CalculateRequiredReasonCodesOnTransaction(this.Context, salesTransaction, ReasonCodeSourceType.VoidTransaction);

                GiftCardWorkflowHelper.VoidGiftCardSalesLines(this.Context, salesTransaction);

                // Set the Sales Transaction Status to Voided.
                salesTransaction.EntryStatus = TransactionStatus.Voided;

                // Set the transaction type to represent Cash & Carry sales.
                if (salesTransaction.TransactionType != SalesTransactionType.IncomeExpense)
                {
                    salesTransaction.TransactionType = SalesTransactionType.Sales;
                }

                // Fill in Store and Terminal information.
                OrderWorkflowHelper.FillTransactionWithContextData(this.Context, salesTransaction);

                // Create order
                var salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction);

                // We also need to delete the shopping cart.
                CartWorkflowHelper.TryDeleteCart(
                    this.Context,
                    new SalesTransaction
                {
                    Id         = request.CartId,
                    TerminalId = salesTransaction.TerminalId,
                    CustomerId = salesTransaction.CustomerId,
                });

                CartWorkflowHelper.LogAuditEntry(
                    this.Context,
                    "SaveVoidTransactionRequestHandler.Process",
                    string.Format("Transaction '{0}' voided.", request.CartId));

                return(new SaveVoidTransactionResponse(salesOrder));
            }
            protected override CreateOrderFromCartResponse Process(CreateOrderFromCartRequest request)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.Null(request.CartId, "request.CartId");

                List <TenderLine> tenderLines = new List <TenderLine>();

                // Get the Sales Transaction.
                SalesTransaction salesTransaction = null;

                ExecutionHandler(
                    delegate
                {
                    PopulateSalesTransaction(this.Context, request.CartId, request.ReceiptEmailAddress, out salesTransaction);
                },
                    SubmitOrderOperationType.GetSalesTransaction.ToString());

                // Validate sales order for creation.
                ExecutionHandler(
                    delegate
                {
                    OrderWorkflowHelper.ValidateContextForCreateOrder(this.Context, salesTransaction);
                },
                    SubmitOrderOperationType.ValidateContextForCreateOrder.ToString());

                // Validate addresses.
                ExecutionHandler(
                    delegate
                {
                    ShippingHelper.ValidateAndResolveAddresses(this.Context, salesTransaction);
                },
                    SubmitOrderOperationType.ValidateAndResolveAddresses.ToString());

                // Add missing dependencies to the sales transaction.
                ExecutionHandler(
                    delegate
                {
                    OrderWorkflowHelper.FillMissingRequirementsForOrder(this.Context, salesTransaction);
                },
                    SubmitOrderOperationType.FillMissingRequirementsForOrder.ToString());

                // Validate addresses for shipping.
                ExecutionHandler(
                    delegate
                {
                    ShippingHelper.ValidateShippingInformation(this.Context, salesTransaction);
                },
                    SubmitOrderOperationType.ValidateShippingAddresses.ToString());

                // Validate required reason code lines has been filled.
                ExecutionHandler(
                    () => ReasonCodesWorkflowHelper.ValidateRequiredReasonCodeLinesFilled(this.Context, salesTransaction),
                    SubmitOrderOperationType.ValidateReasonCodes.ToString());

                // Authorize payments.
                ExecutionHandler(
                    delegate
                {
                    tenderLines = OrderWorkflowHelper.ProcessPendingOrderPayments(this.Context, salesTransaction, request.CartTenderLines);
                },
                    SubmitOrderOperationType.AuthorizePayments.ToString());

                SalesOrder salesOrder = null;

                try
                {
                    // Create order and add all authorization payment blobs.
                    ExecutionHandler(
                        delegate
                    {
                        salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction);
                    },
                        SubmitOrderOperationType.CreateSaleOrderInCrt.ToString());
                }
                catch (Exception ex)
                {
                    try
                    {
                        // Cancel the payment authorizations
                        OrderWorkflowHelper.CancelPayments(this.Context, salesTransaction, tenderLines, request.CartTenderLines);
                    }
                    catch (PaymentException cancelPaymentsEx)
                    {
                        // Inside of CancelPayments() we always wrap Exception as PaymentException.
                        RetailLogger.Log.CrtWorkflowCancelingPaymentFailure(ex, cancelPaymentsEx);
                    }

                    throw;
                }

                // We also need to delete the shopping cart.
                CartWorkflowHelper.TryDeleteCart(
                    this.Context,
                    new SalesTransaction
                {
                    Id         = request.CartId,
                    TerminalId = salesTransaction.TerminalId,
                    CustomerId = salesTransaction.CustomerId,
                });

                return(new CreateOrderFromCartResponse(salesOrder));
            }