Пример #1
0
        public ActionResult Review(CheckoutViewModel model)
        {
            // In this step the user will be able to review their order, and finally go ahead
            // and finalize. We may want to have a null payment provider for free stuff?
            var user = _workContextAccessor.GetContext().CurrentUser;

            if (!_checkoutHelperService.UserMayCheckout(user, out ActionResult redirect))
            {
                if (redirect != null)
                {
                    return(redirect);
                }
                return(Redirect(RedirectUrl));
            }
            // Try to fetch the model from TempData to handle the case where we have been
            // redirected here.
            if (TempData.ContainsKey("CheckoutViewModel"))
            {
                model = (CheckoutViewModel)TempData["CheckoutViewModel"];
            }
            // decode stuff that may be encoded
            ReinflateViewModelAddresses(model);
            model.ShippingRequired = IsShippingRequired();
            if (model.ShippingRequired && model.SelectedShippingOption == null)
            {
                if (string.IsNullOrWhiteSpace(model.ShippingOption))
                {
                    // Here we need a selected shipping method, but we don't have it somehow
                    // so we redirect back to shipping selection
                    // Put the model in TempData so it can be reused in the next action.
                    // This is an attempt to skip shipping, so try to shortcircuit.
                    model.UseDefaultShipping      = true;
                    TempData["CheckoutViewModel"] = model;
                    return(RedirectToAction("Shipping"));
                }
                var selectedOption = ShippingService.RebuildShippingOption(model.ShippingOption);
                _shoppingCart.ShippingOption = selectedOption;
                model.SelectedShippingOption = selectedOption;
            }
            // We will need to display:
            // 1. The summary of all the user's choices up until this point.
            //    (that's already in the model)
            // 2. The list of buttons for the available payment options.
            model.PosServices = _posServices;

            // encode addresses so we can hide them in the form
            model.EncodeAddresses();
            // make sure services are injected so they may be used
            InjectServices(model);
            return(View(model));
        }
Пример #2
0
        public ActionResult Shipping(CheckoutViewModel model)
        {
            // In this step the user will select the shipping method from a list
            var user = _workContextAccessor.GetContext().CurrentUser;

            if (!_checkoutHelperService.UserMayCheckout(user, out ActionResult redirect))
            {
                if (redirect != null)
                {
                    return(redirect);
                }
                return(Redirect(RedirectUrl));
            }
            // Try to fetch the model from TempData to handle the case where we have been
            // redirected here.
            if (TempData.ContainsKey("CheckoutViewModel"))
            {
                model = (CheckoutViewModel)TempData["CheckoutViewModel"];
            }

            // Check if the mail returned an error: "A shipment has not been selected"
            if (TempData.ContainsKey("ShippingError"))
            {
                ModelState.AddModelError("_FORM", TempData["ShippingError"].ToString());
            }

            // deserialize addresses
            ReinflateViewModelAddresses(model);

            model.ShippingRequired = IsShippingRequired();
            if (model.ShippingAddressVM != null)
            {
                var productQuantities = _shoppingCart
                                        .GetProducts()
                                        .Where(p => p.Quantity > 0)
                                        .ToList();
                // Hack: based on the address coming in model.ShippingAddressVM, we can
                // compute the actual destinations to be used at this stage
                var country = _addressConfigurationService
                              ?.GetCountry(model.ShippingAddressVM.CountryId);
                var countryName = country
                                  ?.Record?.TerritoryInternalRecord.Name;
                // we should make sure that the country name is filled in for the shipping
                // address view model, so we can display it.
                if (string.IsNullOrWhiteSpace(model.ShippingAddressVM.Country))
                {
                    model.ShippingAddressVM.Country = _contentManager.GetItemMetadata(country).DisplayText;
                }
                // get all possible providers for shipping methods
                var shippingMethods = _shippingMethodProviders
                                      .SelectMany(p => p.GetShippingMethods())
                                      .ToList();
                // Test those providers with nwazet's default interface.
                var allShippingOptions = ShippingService
                                         .GetShippingOptions(
                    shippingMethods,
                    productQuantities,
                    countryName,
                    model.ShippingAddressVM.PostalCode,
                    _workContextAccessor).ToList();
                // Those tests done like that cannot be very reliable with respect to
                // territories' configuration, unless we configure a hierarchy of postal
                // codes. Rather than do that, we are going to do an hack on the PostalCode
                // that will let a shipping criterion parse out the territory Ids.
                allShippingOptions
                .AddRange(ShippingService
                          .GetShippingOptions(
                              shippingMethods,
                              productQuantities,
                              countryName,
                              $"{model.ShippingAddressVM.PostalCode};" +
                              $"{model.ShippingAddressVM.CountryId};" +
                              $"{model.ShippingAddressVM.ProvinceId};" +
                              $"{model.ShippingAddressVM.CityId}",
                              _workContextAccessor));
                // remove duplicate shipping options
                model.AvailableShippingOptions = allShippingOptions.Distinct(new ShippingOption.ShippingOptionComparer()).ToList();
                // See whether we are trying to short circuit the checkout steps
                if (model.UseDefaultShipping)
                {
                    // if there is no option selected, and there is only one possible option, we can skip
                    // the selection. If the user is trying to reset their selection, there is a selected
                    // option so it should not trigger this condition
                    if (string.IsNullOrWhiteSpace(model.ShippingOption) && model.AvailableShippingOptions.Count == 1)
                    {
                        model.ShippingOption = model.AvailableShippingOptions.First().FormValue;
                        return(ShippingPOST(model));
                    }
                }
                // to correctly display prices, the view will need the currency provider
                model.CurrencyProvider = _currencyProvider;
                // encode addresses so we can hide them in the form
                model.EncodeAddresses();
                // make sure services are injected so they may be used
                InjectServices(model);
                return(View(model));
            }
            // to get here something must have gone very wrong. Perhaps the user
            // is trying to select a shipping method where no shipping is required.
            // More likely, a refresh of the shipping page messed things up for us.
            // Either way, go through the index in an attempt to properly repopulate
            // the addresses
            model.UseDefaultAddress = true;
            // Put the model in TempData so it can be reused in the next action.
            TempData["CheckoutViewModel"] = model;
            return(RedirectToAction("Index"));
        }