public async Task <ActionResult> Purchase(CheckoutViewModel viewModel, IPaymentMethod paymentOption)
        {
            if (CartIsNullOrEmpty())
            {
                return(Redirect(Url.ContentUrl(ContentReference.StartPage)));
            }

            // Since the payment property is marked with an exclude binding attribute in the CheckoutViewModel
            // it needs to be manually re-added again.
            //viewModel.Payments = paymentOption;

            if (User.Identity.IsAuthenticated)
            {
                _checkoutService.CheckoutAddressHandling.UpdateAuthenticatedUserAddresses(viewModel);

                var validation = _checkoutService.AuthenticatedPurchaseValidation;

                if (!validation.ValidateModel(ModelState, viewModel) ||
                    !validation.ValidateOrderOperation(ModelState, _cartService.ValidateCart(CartWithValidationIssues.Cart)) ||
                    !validation.ValidateOrderOperation(ModelState, _cartService.RequestInventory(CartWithValidationIssues.Cart)))
                {
                    return(View(viewModel));
                }
            }
            else
            {
                _checkoutService.CheckoutAddressHandling.UpdateAnonymousUserAddresses(viewModel);

                var validation = _checkoutService.AnonymousPurchaseValidation;

                if (!validation.ValidateModel(ModelState, viewModel) ||
                    !validation.ValidateOrderOperation(ModelState, _cartService.ValidateCart(CartWithValidationIssues.Cart)) ||
                    !validation.ValidateOrderOperation(ModelState, _cartService.RequestInventory(CartWithValidationIssues.Cart)))
                {
                    return(View(viewModel));
                }
            }

            if (!paymentOption.ValidateData())
            {
                return(View(viewModel));
            }

            _checkoutService.UpdateShippingAddresses(CartWithValidationIssues.Cart, viewModel);

            _checkoutService.CreateAndAddPaymentToCart(CartWithValidationIssues.Cart, viewModel);

            var purchaseOrder = _checkoutService.PlaceOrder(CartWithValidationIssues.Cart, ModelState, viewModel);

            if (purchaseOrder == null)
            {
                return(View(viewModel));
            }

            if (Request.IsAuthenticated)
            {
                var contact      = _customerContext.GetCurrentContact().Contact;
                var organization = contact.ContactOrganization;
                if (organization != null)
                {
                    purchaseOrder.Properties[Constant.Customer.CustomerFullName]            = contact.FullName;
                    purchaseOrder.Properties[Constant.Customer.CustomerEmailAddress]        = contact.Email;
                    purchaseOrder.Properties[Constant.Customer.CurrentCustomerOrganization] = organization.Name;
                    _orderRepository.Save(purchaseOrder);
                }
            }

            var confirmationSentSuccessfully = await _checkoutService.SendConfirmation(viewModel, purchaseOrder);

            //await _checkoutService.CreateOrUpdateBoughtProductsProfileStore(CartWithValidationIssues.Cart);
            //await _checkoutService.CreateBoughtProductsSegments(CartWithValidationIssues.Cart);
            await _recommendationService.TrackOrder(HttpContext, purchaseOrder);

            return(Redirect(_checkoutService.BuildRedirectionUrl(viewModel, purchaseOrder, confirmationSentSuccessfully)));
        }
        public async Task <ActionResult> BuyNow(RequestParamsToCart param)
        {
            var warningMessage = string.Empty;

            ModelState.Clear();

            if (CartWithValidationIssues.Cart == null)
            {
                _cart = new CartWithValidationIssues
                {
                    Cart             = _cartService.LoadOrCreateCart(_cartService.DefaultCartName),
                    ValidationIssues = new Dictionary <ILineItem, List <ValidationIssue> >()
                };
            }

            var result = _cartService.AddToCart(CartWithValidationIssues.Cart, param.Code, param.Quantity, param.Store, param.SelectedStore);

            if (!result.EntriesAddedToCart)
            {
                return(new HttpStatusCodeResult(500, result.GetComposedValidationMessage()));
            }
            var contact = PrincipalInfo.CurrentPrincipal.GetCustomerContact();

            if (contact == null)
            {
                return(RedirectToCart("The contact is invalid"));
            }

            var creditCard = contact.ContactCreditCards.FirstOrDefault();

            if (creditCard == null)
            {
                return(RedirectToCart("There is not any credit card"));
            }

            var shipment = CartWithValidationIssues.Cart.GetFirstShipment();

            if (shipment == null)
            {
                return(RedirectToCart("The shopping cart is not exist"));
            }

            var shippingAddress = (contact.PreferredShippingAddress ?? contact.ContactAddresses.FirstOrDefault())?.ConvertToOrderAddress(CartWithValidationIssues.Cart);

            if (shippingAddress == null)
            {
                return(RedirectToCart("The shipping address is not exist"));
            }

            shipment.ShippingAddress = shippingAddress;

            var shippingMethodViewModels = _shipmentViewModelFactory.CreateShipmentsViewModel(CartWithValidationIssues.Cart).SelectMany(x => x.ShippingMethods);
            var shippingMethodViewModel  = shippingMethodViewModels.Where(x => x.Price != 0)
                                           .OrderBy(x => x.Price)
                                           .FirstOrDefault();

            //If product is virtual set shipping method is Free
            if (shipment.LineItems.FirstOrDefault().IsVirtualVariant())
            {
                shippingMethodViewModel = shippingMethodViewModels.Where(x => x.Price == 0).FirstOrDefault();
            }

            if (shippingMethodViewModel == null)
            {
                return(RedirectToCart("The shipping method is invalid"));
            }

            shipment.ShippingMethodId = shippingMethodViewModel.Id;

            var paymentAddress = (contact.PreferredBillingAddress ?? contact.ContactAddresses.FirstOrDefault())?.ConvertToOrderAddress(CartWithValidationIssues.Cart);

            if (paymentAddress == null)
            {
                return(RedirectToCart("The billing address is not exist"));
            }

            var totals = _orderGroupCalculator.GetOrderGroupTotals(CartWithValidationIssues.Cart);

            var payment = CartWithValidationIssues.Cart.CreateCardPayment();

            payment.BillingAddress         = paymentAddress;
            payment.CardType               = "Credit card";
            payment.PaymentMethodId        = new Guid("B1DA37A6-CF19-40D5-915B-B863D74D8799");
            payment.PaymentMethodName      = "GenericCreditCard";
            payment.Amount                 = CartWithValidationIssues.Cart.GetTotal().Amount;
            payment.CreditCardNumber       = creditCard.CreditCardNumber;
            payment.CreditCardSecurityCode = creditCard.SecurityCode;
            payment.ExpirationMonth        = creditCard.ExpirationMonth ?? 1;
            payment.ExpirationYear         = creditCard.ExpirationYear ?? DateTime.Now.Year;
            payment.Status                 = PaymentStatus.Pending.ToString();
            payment.CustomerName           = contact.FullName;
            payment.TransactionType        = TransactionType.Authorization.ToString();
            CartWithValidationIssues.Cart.GetFirstForm().Payments.Add(payment);

            var issues = _cartService.ValidateCart(CartWithValidationIssues.Cart);

            if (issues.Keys.Any(x => issues.HasItemBeenRemoved(x)))
            {
                return(RedirectToCart("The product is invalid"));
            }
            var order = _checkoutService.PlaceOrder(CartWithValidationIssues.Cart, new ModelStateDictionary(), new CheckoutViewModel());

            //await _checkoutService.CreateOrUpdateBoughtProductsProfileStore(CartWithValidationIssues.Cart);
            //await _checkoutService.CreateBoughtProductsSegments(CartWithValidationIssues.Cart);
            await _recommendationService.TrackOrder(HttpContext, order);

            var homePage = _contentLoader.Get <PageData>(ContentReference.StartPage) as CommerceHomePage;

            if (homePage?.OrderConfirmationPage != null)
            {
                var orderConfirmationPage = _contentLoader.Get <OrderConfirmationPage>(homePage.OrderConfirmationPage);
                var queryCollection       = new NameValueCollection
                {
                    { "contactId", contact.PrimaryKeyId?.ToString() },
                    { "orderNumber", order.OrderLink.OrderGroupId.ToString() }
                };
                var urlRedirect = new UrlBuilder(orderConfirmationPage.StaticLinkURL)
                {
                    QueryCollection = queryCollection
                };
                return(Json(new { Redirect = urlRedirect.ToString() }));
            }

            return(RedirectToCart("Something went wrong"));
        }
        public async Task <ActionResult> GetRecommendations(string widgetType, string name, string value = "", int numberOfRecs = 4)
        {
            if (string.IsNullOrEmpty(widgetType) || PageEditing.PageIsInEditMode)
            {
                return(new EmptyResult());
            }

            List <Recommendation> recommendations = null;
            TrackingResponseData  response;

            switch (widgetType)
            {
            case "Home":
                response = await _trackingService.TrackHome(ControllerContext.HttpContext);

                recommendations = response.GetRecommendations(_referenceConverter, RecommendationsExtensions.Home)
                                  .ToList();
                break;

            case "Basket":
                response = await _trackingService.TrackCart(ControllerContext.HttpContext, _cartService.LoadCart(_cartService.DefaultCartName, false).Cart);

                recommendations = response.GetRecommendations(_referenceConverter, RecommendationsExtensions.Basket)
                                  .ToList();
                break;

            case "Checkout":
                response = await _trackingService.TrackCheckout(ControllerContext.HttpContext);

                recommendations = response.GetRecommendations(_referenceConverter, "Checkout")
                                  .ToList();
                break;

            case "Wishlist":
                response = await _trackingService.TrackWishlist(ControllerContext.HttpContext);

                recommendations = response.GetRecommendations(_referenceConverter, "Wishlist")
                                  .ToList();
                break;

            case "Order":
                IPurchaseOrder order = null;
                if (PageEditing.PageIsInEditMode)
                {
                    break;
                }
                if (int.TryParse(ControllerContext.HttpContext.Request.QueryString["orderNumber"], out var orderNumber))
                {
                    order = _confirmationService.GetOrder(orderNumber);
                }
                if (order == null)
                {
                    break;
                }
                response = await _trackingService.TrackOrder(ControllerContext.HttpContext, order);

                recommendations = response.GetRecommendations(_referenceConverter, "orderWidget")
                                  .ToList();
                break;

            default:
                response = await _trackingService.TrackAttribute(ControllerContext.HttpContext, name, value);

                recommendations = response.GetRecommendations(_referenceConverter, "attributeWidget")
                                  .ToList();
                break;
            }

            if (recommendations == null)
            {
                return(new EmptyResult());
            }
            recommendations = recommendations.Take(numberOfRecs).ToList();

            return(PartialView("/Features/Recommendations/Index.cshtml", _productService.GetRecommendedProductTileViewModels(recommendations)));
        }