Пример #1
0
        public JsonResult GetCities(ConfigurationRequestViewModel viewModel)
        {
            var country = _addressConfigurationService.GetCountry(viewModel.CountryId);

            if (country == null)
            {
                // this is an error
            }
            else
            {
                var cities = _addressConfigurationService.GetAllCities(
                    viewModel.IsBillingAddress
                        ? AddressRecordType.BillingAddress
                        : AddressRecordType.ShippingAddress,
                    country);
                return(Json(new {
                    Success = true,
                    Cities = cities
                             .Select(tp =>
                                     new {
                        Value = tp.Record.TerritoryInternalRecord.Id,
                        Text = _contentManager.GetItemMetadata(tp).DisplayText
                    })
                             .OrderBy(obj => obj.Text)
                }));
            }
            // TODO
            return(Json(new List <string>()));
        }
Пример #2
0
        private AddressEditViewModel CreateVM(AddressRecord address)
        {
            // defaults to "no country selected" for a new or "legacy" AddressRecord
            var countryId = address.CountryId;

            if (countryId == 0 && !string.IsNullOrWhiteSpace(address.Country))
            {
                // from address.Country, find the value that should be used
                // address.Country is of type string. It could represent the
                // name of the country (legacy) or the Id of the country territory.
                // Try to parse it.
                if (!int.TryParse(address.Country, out countryId))
                {
                    // parsing failed, so the string may be a territory's name
                    var tp = _addressConfigurationService.GetCountry(address.Country);
                    if (tp != null)
                    {
                        countryId = tp.Record.TerritoryInternalRecord.Id;
                    }
                }
            }

            return(new AddressEditViewModel(address)
            {
                Countries = _addressConfigurationService
                            .CountryOptions(address.AddressType, countryId),
                CountryId = countryId
            });
        }
Пример #3
0
        private void ValidateVM(AddressEditViewModel vm)
        {
            int id = -1;

            if (vm.CityId > 0)
            {
                if (int.TryParse(vm.City, out id))
                {
                    // the form sent the city's id instead of its name
                    vm.City = _addressConfigurationService
                              .GetCity(vm.CityId)
                              ?.As <TitlePart>()
                              ?.Title
                              ?? string.Empty;
                }
            }
            if (vm.ProvinceId > 0)
            {
                if (int.TryParse(vm.Province, out id))
                {
                    // the form sent the city's id instead of its name
                    vm.Province = _addressConfigurationService
                                  .GetProvince(vm.ProvinceId)
                                  ?.As <TitlePart>()
                                  ?.Title
                                  ?? string.Empty;
                }
            }
            if (vm.CountryId > 0)
            {
                if (int.TryParse(vm.Country, out id))
                {
                    // the form sent the city's id instead of its name
                    vm.Country = _addressConfigurationService
                                 .GetCountry(vm.CountryId)
                                 ?.As <TitlePart>()
                                 ?.Title
                                 ?? string.Empty;
                }
            }
        }
        /// <summary>
        /// validation of the vm coming from a create/edit action
        /// </summary>
        /// <param name="vm"></param>
        /// <returns></returns>
        /// <remarks>
        /// It would be cleaner to do this in its own validation classes,
        /// but we need a bunch of IDependencies, so putting this code
        /// here is less of an hassle.
        /// </remarks>
        public bool Validate(AddressEditViewModel vm)
        {
            var validCountries = _addressConfigurationService
                                 .GetAllCountries(vm.AddressType);
            var countryTP = _addressConfigurationService
                            .GetCountry(vm.CountryId);

            if (!SubValidation(validCountries, countryTP))
            {
                return(false);
            }
            var validProvinces = _addressConfigurationService
                                 .GetAllProvinces(vm.AddressType, countryTP);

            if (validProvinces == null)
            {
                // error condition
                return(false);
            }
            var provinceTP = GetTerritory(vm.Province);

            if (validProvinces.Any())
            {
                // there may not be any configured province, and that is ok,
                // but if any is configured, we check that the one selected is valid
                if (!SubValidation(validProvinces, provinceTP))
                {
                    return(false);
                }
            }
            var validCities = _addressConfigurationService
                              .GetAllCities(vm.AddressType,
                                            // use province if it exists, otherwise country
                                            provinceTP == null ? countryTP : provinceTP);

            if (validCities == null)
            {
                // error condition
                return(false);
            }
            if (validCities.Any())
            {
                // there may not be any configured city, and that is ok,
                // but if any is configured, we check that the one selected is valid
                var cityTP = GetTerritory(vm.City);
                if (!SubValidation(validCities, cityTP))
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #5
0
        public JsonResult GetAdministrativeInfo(int territoryId)
        {
            var country = _addressConfigurationService.GetCountry(territoryId);
            var part    = country?.As <TerritoryAdministrativeTypePart>();

            if (part != null)
            {
                return(Json(new { part.HasCities, part.HasProvinces, part.AdministrativeType }, JsonRequestBehavior.AllowGet));
            }
            else
            {
                return(null);
            }
        }
Пример #6
0
        public ActionResult Index(AddressesVM model)
        {
            ActionResult result         = null;
            var          thecurrentUser = _orchardServices.WorkContext.CurrentUser;

            switch (model.Submit)
            {
            case "cart":
                result = RedirectToAction("Index", "ShoppingCart", new { area = "Nwazet.Commerce" });
                break;

            case "save":
                // validate addresses
                if (!TryUpdateModel(model.ShippingAddressVM) || !TryUpdateModel(model.BillingAddressVM) ||
                    !ValidateVM(model.ShippingAddressVM) || !ValidateVM(model.BillingAddressVM) ||
                    !ValidateVM(model))
                {
                    // in case of error, repopulate the default lists
                    model.ShippingAddressVM = CreateVM(AddressRecordType.ShippingAddress);
                    model.BillingAddressVM  = CreateVM(AddressRecordType.BillingAddress);
                    if (thecurrentUser != null)
                    {
                        model.ListAvailableBillingAddress  = _nwazetCommunicationService.GetBillingByUser(thecurrentUser);
                        model.ListAvailableShippingAddress = _nwazetCommunicationService.GetShippingByUser(thecurrentUser);
                    }
                    result = View("Index", model);
                    break;
                }
                // Hack: based on the address coming in model.ShippingAddressVM, we can compute the actual
                // destinations to be used for tax computations at this stage
                var countryName = _addressConfigurationService
                                  ?.GetCountry(model.ShippingAddressVM.CountryId)
                                  ?.Record?.TerritoryInternalRecord.Name;
                // costruisce la lista di CheckoutItems in base al contenuto del carrello
                List <CheckoutItem> items = new List <CheckoutItem>();
                foreach (var prod in _shoppingCart.GetProducts())
                {
                    items.Add(new CheckoutItem {
                        Attributes          = prod.AttributeIdsToValues,
                        LinePriceAdjustment = prod.LinePriceAdjustment,
                        OriginalPrice       = prod.OriginalPrice,
                        Price = prod.Product.DiscountPrice >= 0 && prod.Product.DiscountPrice < prod.Product.Price
                            ? _productPriceService.GetDiscountPrice(prod.Product, countryName, null)
                            : _productPriceService.GetPrice(prod.Product, countryName, null),
                        ProductId   = prod.Product.Id,
                        PromotionId = prod.Promotion == null ? null : (int?)(prod.Promotion.Id),
                        Quantity    = prod.Quantity,
                        Title       = prod.Product.ContentItem.As <TitlePart>().Title
                    });
                }
                // check if there are products in the cart
                if (items.Count > 0)
                {
                    var paymentGuid = Guid.NewGuid().ToString();
                    var charge      = new PaymentGatewayCharge("Payment Gateway", paymentGuid);
                    // get Orchard user id
                    var userId      = -1;
                    var currentUser = _orchardServices.WorkContext.CurrentUser;
                    if (currentUser != null)
                    {
                        userId = currentUser.Id;
                    }

                    // update addresses based on those populated in the form
                    model.ShippingAddress = AddressFromVM(model.ShippingAddressVM);
                    model.BillingAddress  = AddressFromVM(model.BillingAddressVM);

                    var currency = _currencyProvider.CurrencyCode;
                    var order    = _orderService.CreateOrder(
                        charge,
                        items,
                        _shoppingCart.Subtotal(),
                        _shoppingCart.Total(),
                        _shoppingCart.Taxes(),
                        _shoppingCart.ShippingOption,
                        model.ShippingAddress,
                        model.BillingAddress,
                        model.Email,
                        model.PhonePrefix + " " + model.Phone,
                        model.SpecialInstructions,
                        OrderPart.Pending, //.Cancelled,
                        null,
                        false,
                        userId,
                        0,
                        "",
                        currency);
                    // update advanced address information
                    var addressPart = order.As <AddressOrderPart>();
                    if (addressPart != null)
                    {
                        // shipping info
                        addressPart.ShippingCountryName  = model.ShippingAddressVM.Country;
                        addressPart.ShippingCountryId    = model.ShippingAddressVM.CountryId;
                        addressPart.ShippingCityName     = model.ShippingAddressVM.City;
                        addressPart.ShippingCityId       = model.ShippingAddressVM.CityId;
                        addressPart.ShippingProvinceName = model.ShippingAddressVM.Province;
                        addressPart.ShippingProvinceId   = model.ShippingAddressVM.ProvinceId;
                        // billing
                        addressPart.BillingCountryName  = model.BillingAddressVM.Country;
                        addressPart.BillingCountryId    = model.BillingAddressVM.CountryId;
                        addressPart.BillingCityName     = model.BillingAddressVM.City;
                        addressPart.BillingCityId       = model.BillingAddressVM.CityId;
                        addressPart.BillingProvinceName = model.BillingAddressVM.Province;
                        addressPart.BillingProvinceId   = model.BillingAddressVM.ProvinceId;
                    }
                    // To properly handle the order's advanced address configuration we need
                    // to call again the providers to store the additional data, because when they
                    // are invoked in Nwazet's IOrderService implementation we can't have access
                    // to the new information yet. If we ever overhaul that module, we should
                    // account for this extensibility requirement.
                    foreach (var oaip in _orderAdditionalInformationProviders)
                    {
                        oaip.StoreAdditionalInformation(order);
                    }
                    order.LogActivity(OrderPart.Event, "Order created");
                    // we unpublish the order here. The service from Nwazet creates it
                    // and publishes it. This would cause issues whenever a user leaves
                    // mid checkout rather than completing the entire process, because we
                    // would end up having unprocessed orders that are created and published.
                    // By unpublishing, we practically turn the order in a draft. Later,
                    // after processing payments, we publish the order again so it shows
                    // in the "normal" queries and lists.
                    // Note that this is a workaround for order management that only really
                    // works as long as payments are processed and the order published there.
                    // In cases where we may not wish to have payments happen when a new order
                    // is created, this system should be reworked properly.
                    _contentManager.Unpublish(order.ContentItem);
                    // save the addresses for the contact doing the order.
                    _nwazetCommunicationService.OrderToContact(order);
                    var reason  = string.Format("Purchase Order {0}", order.OrderKey);
                    var payment = new PaymentRecord {
                        Reason        = reason,
                        Amount        = order.Total,
                        Currency      = order.CurrencyCode,
                        ContentItemId = order.Id
                    };
                    var nonce = _paymentService.CreatePaymentNonce(payment);
                    result = RedirectToAction("Pay", "Payment",
                                              new {
                        area           = "Laser.Orchard.PaymentGateway",
                        nonce          = nonce,
                        newPaymentGuid = paymentGuid
                    });
                }
                else
                {
                    _notifier.Information(T("There are no products in the cart. Go back to the catalog and add products."));
                    result = View("Index", model);
                }
                break;

            default:
                model.ShippingAddressVM = CreateVM(AddressRecordType.ShippingAddress);
                model.BillingAddressVM  = CreateVM(AddressRecordType.BillingAddress);
                if (thecurrentUser != null)
                {
                    model.ListAvailableBillingAddress  = _nwazetCommunicationService.GetBillingByUser(thecurrentUser);
                    model.ListAvailableShippingAddress = _nwazetCommunicationService.GetShippingByUser(thecurrentUser);
                    model.Email = thecurrentUser.Email;
                    var cel = _nwazetCommunicationService.GetPhone(thecurrentUser);
                    if (cel.Length == 2)
                    {
                        model.PhonePrefix = cel[0];
                        model.Phone       = cel[1];
                    }
                }
                result = View("Index", model);
                break;
            }
            return(result);
        }
Пример #7
0
        public ActionResult IndexPOST(CheckoutViewModel model)
        {
            // Depending on whether shipping is required or not, the validation of what has been
            // input changes, because if there is no shipping there's no need for the shipping
            // address.
            var user = _workContextAccessor.GetContext().CurrentUser;

            if (!_checkoutHelperService.UserMayCheckout(user, out ActionResult redirect))
            {
                if (redirect != null)
                {
                    return(redirect);
                }
                return(Redirect(RedirectUrl));
            }
            // check if the user is trying to reset the selected addresses to select different
            // ones.
            if (model.ResetAddresses)
            {
                // reset shipment to redo the calculation correctly,
                // removing from the total the shipment that will have to be reselected
                _shoppingCart.ShippingOption = null;

                ReinflateViewModelAddresses(model);
                // Put the model we validated in TempData so it can be reused in the next action.
                TempData["CheckoutViewModel"] = model;
                return(RedirectToAction("Index"));
            }
            model.ShippingRequired = IsShippingRequired(); //we'll reuse this
            // Ensure address types are initialized correctly
            model.BillingAddressVM.AddressType = AddressRecordType.BillingAddress;
            model.BillingAddressVM.AddressRecord.AddressType = AddressRecordType.BillingAddress;
            if (model.ShippingAddressVM != null)
            {
                model.ShippingAddressVM.AddressType = AddressRecordType.ShippingAddress;
                model.ShippingAddressVM.AddressRecord.AddressType = AddressRecordType.ShippingAddress;
            }
            // validate
            var validationSuccess = ValidateVM(model);

            if (!validationSuccess)
            {
                // don't move on, but rather leave the user on this form
                model.BillingAddressVM = CreateVM(AddressRecordType.BillingAddress, model.BillingAddressVM);
                if (model.ShippingRequired)
                {
                    model.ShippingAddressVM = CreateVM(AddressRecordType.ShippingAddress, model.ShippingAddressVM);
                }
                InjectServices(model);
                if (user != null)
                {
                    // also load the list of existing addresses for them
                    model.ListAvailableBillingAddress =
                        _nwazetCommunicationService.GetBillingByUser(user);
                    // we are only going to load the shipping addresses if shipping is required
                    if (model.ShippingRequired)
                    {
                        model.ListAvailableShippingAddress =
                            _nwazetCommunicationService.GetShippingByUser(user);
                    }
                }
                return(View(model));
            }
            // in case validation is successful, if a user exists, try to store the
            // addresses they just configured.
            if (user != null)
            {
                if (model.BillingAddressVM != null && model.BillingAddressVM.AddressRecord != null)
                {
                    var countryTP = _addressConfigurationService.GetCountry(model.BillingAddressVM.CountryId);
                    model.BillingAddressVM.Country = _contentManager.GetItemMetadata(countryTP).DisplayText;

                    if (model.BillingAddressVMListAddress > 0)
                    {
                        model.BillingAddressVM.AddressRecord.Id = model.BillingAddressVMListAddress;
                    }
                    _nwazetCommunicationService.AddAddress(model.BillingAddressVM.AddressRecord, user);
                }
                if (model.ShippingAddressVM != null && model.ShippingAddressVM.AddressRecord != null)
                {
                    var countryTP = _addressConfigurationService.GetCountry(model.ShippingAddressVM.CountryId);
                    model.ShippingAddressVM.Country = _contentManager.GetItemMetadata(countryTP).DisplayText;
                    if (model.ShippingAddressVMListAddress > 0)
                    {
                        model.ShippingAddressVM.AddressRecord.Id = model.ShippingAddressVMListAddress;
                    }
                    _nwazetCommunicationService.AddAddress(model.ShippingAddressVM.AddressRecord, user);
                }
                if (!string.IsNullOrWhiteSpace(model.PhonePrefix) || !string.IsNullOrWhiteSpace(model.Phone))
                {
                    _nwazetCommunicationService.SetPhone(model.PhonePrefix, model.Phone, user);
                }
            }
            // In case validation is successful, depending on whether shipping is required, we
            // should redirect to a different action/step.
            // If shipping is required, we should redirect to an action that lets the user select
            // their preferred shipping method. If only one method is configured, the user should
            // still be made to go through that step. The selection of the list of available methods
            // can make use of the address the user has selected for shipping.
            // If no shipping is required we can move on to reviewing the order.
            // At this stage, since we also have the correct address, we can correctly compute TAX
            // TODO: compute VAT
            // Put the model we validated in TempData so it can be reused in the next action.
            TempData["CheckoutViewModel"] = model;
            if (IsShippingRequired())
            {
                // Set values into the ShoppingCart storage
                var country = _addressConfigurationService
                              ?.GetCountry(model.ShippingAddressVM.CountryId);
                _shoppingCart.Country = _contentManager.GetItemMetadata(country).DisplayText;
                _shoppingCart.ZipCode = model.ShippingAddressVM.PostalCode;
                return(RedirectToAction("Shipping"));
            }
            return(RedirectToAction("Review"));
        }
Пример #8
0
        public ActionResult Index(CheckoutViewModel model)
        {
            // This will be the entry point for the checkout process.
            // This method should probably have parameters to handle displaying its form
            // with some information already in it in case of validation errors when posting
            // it.
            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"];
            }
            model.ShippingRequired = IsShippingRequired();
            if (user != null)
            {
                // If the user is authenticated, set the model's email and any other information
                // we can get from the user's contact, but avoid overwriting previous input
                if (string.IsNullOrWhiteSpace(model.Email))
                {
                    model.Email = user.Email;
                }
                if (string.IsNullOrWhiteSpace(model.Phone))
                {
                    var cel = _nwazetCommunicationService.GetPhone(user);
                    if (cel.Length == 2)
                    {
                        model.PhonePrefix = cel[0];
                        model.Phone       = cel[1];
                    }
                }
                // also load the list of existing addresses for them
                model.ListAvailableBillingAddress =
                    _nwazetCommunicationService.GetBillingByUser(user);
                // we are only going to load the shipping addresses if shipping is required
                if (model.ShippingRequired)
                {
                    model.ListAvailableShippingAddress =
                        _nwazetCommunicationService.GetShippingByUser(user);
                }
            }
            // attempt to shortcircuit the actions
            if (model.UseDefaultAddress)
            {
                // if the user has saved addresses, preselect the ones used most recently
                if (model.ListAvailableBillingAddress.Any() &&
                    (!model.ShippingRequired || (model.ShippingRequired && model.ListAvailableShippingAddress.Any())))
                {
                    model.BillingAddressVM = new AddressEditViewModel(model
                                                                      .ListAvailableBillingAddress
                                                                      // pick the one used/updated most recently
                                                                      .OrderByDescending(a => a.TimeStampUTC)
                                                                      .First());
                    if (model.ShippingRequired)
                    {
                        model.ShippingAddressVM = new AddressEditViewModel(model
                                                                           .ListAvailableShippingAddress
                                                                           // pick the one used/updated most recently
                                                                           .OrderByDescending(a => a.TimeStampUTC)
                                                                           .First());
                    }
                    // redirect to next step
                    // Put the model we validated in TempData so it can be reused in the next action.
                    TempData["CheckoutViewModel"] = model;
                    if (model.ShippingRequired)
                    {
                        // Set values into the ShoppingCart storage
                        var country = _addressConfigurationService
                                      ?.GetCountry(model.ShippingAddressVM.CountryId);
                        _shoppingCart.Country = _contentManager.GetItemMetadata(country).DisplayText;
                        _shoppingCart.ZipCode = model.ShippingAddressVM.PostalCode;
                    }
                    // we redirect to this post action, where we do validation
                    return(IndexPOST(model));
                }
            }

            model.BillingAddressVM = CreateVM(AddressRecordType.BillingAddress, model.BillingAddressVM);
            // test whether shipping will be required for the order, because that will change
            // what must be displayed for the addresses as well as what happens when we go ahead
            // with the checkout: if no shipping is required, we can go straight to order review
            // and then payment.
            if (model.ShippingRequired)
            {
                model.ShippingAddressVM = CreateVM(AddressRecordType.ShippingAddress, model.ShippingAddressVM);
            }
            InjectServices(model);
            FinalizeVM(model);
            return(View(model));
        }
Пример #9
0
        /// <summary>
        /// validation of the vm coming from a create/edit action
        /// </summary>
        /// <param name="vm"></param>
        /// <returns></returns>
        /// <remarks>
        /// It would be cleaner to do this in its own validation classes,
        /// but we need a bunch of IDependencies, so putting this code
        /// here is less of an hassle.
        /// </remarks>
        public bool Validate(AddressEditViewModel vm)
        {
            var validCountries = _addressConfigurationService
                                 .GetAllCountries(vm.AddressType);
            var countryTP = _addressConfigurationService
                            .GetCountry(vm.CountryId);

            if (!SubValidation(validCountries, countryTP))
            {
                return(false);
            }

            var provinceTP = GetTerritory(vm.Province)
                             ?? _addressConfigurationService.SingleTerritory(vm.ProvinceId);

            if (provinceTP == null)
            {
                // maybe we did not find a territory because it's not configured,
                // but we had a free text input for the province
                var provinceName = vm.Province.Trim();
                if (provinceName.Length < 2)
                {
                    // at least two characters
                    return(false);
                }
            }
            else
            {
                // check in the configuration parts if they are a valid province or not
                var adminTypePart = provinceTP.As <TerritoryAdministrativeTypePart>();
                if (adminTypePart != null)
                {
                    if (adminTypePart.AdministrativeType == TerritoryAdministrativeType.Province)
                    {
                        var territoryAddressTypePart = provinceTP.As <TerritoryAddressTypePart>();
                        if (territoryAddressTypePart != null)
                        {
                            if (vm.AddressType == AddressRecordType.ShippingAddress)
                            {
                                if (!territoryAddressTypePart.Shipping)
                                {
                                    return(false);
                                }
                            }
                            else
                            {
                                if (!territoryAddressTypePart.Billing)
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                }
            }

            var cityTP = GetTerritory(vm.City)
                         ?? _addressConfigurationService.SingleTerritory(vm.CityId);

            // check in the configuration parts if they are a valid city or not
            if (cityTP != null)
            {
                var adminTypePart = cityTP.As <TerritoryAdministrativeTypePart>();
                if (adminTypePart != null)
                {
                    if (adminTypePart.AdministrativeType == TerritoryAdministrativeType.City)
                    {
                        var territoryAddressTypePart = cityTP.As <TerritoryAddressTypePart>();
                        if (territoryAddressTypePart != null)
                        {
                            if (vm.AddressType == AddressRecordType.ShippingAddress)
                            {
                                if (!territoryAddressTypePart.Shipping)
                                {
                                    return(false);
                                }
                            }
                            else
                            {
                                if (!territoryAddressTypePart.Billing)
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                }
            }

            // https://en.wikipedia.org/wiki/List_of_postal_codes
            // we had to make the change because we first checked
            // it was just a number
            // during use we noticed that the Netherlands have PS in the cap
            // therefore changed the control over the character
            if (string.IsNullOrWhiteSpace(vm.PostalCode))
            {
                return(false);
            }
            else
            {
                foreach (char c in vm.PostalCode)
                {
                    if (!char.IsLetterOrDigit(c) && !char.IsWhiteSpace(c))
                    {
                        vm.Errors.Add(T("Postal or ZIP code may contain only characters or digits.").Text);
                        return(false);
                    }
                }
            }
            return(true);
        }