public async Task CanLoadActiveShippingRateComputationMethods() { var shippingRateComputationMethods = await _shippingPluginManager.LoadActivePluginsAsync(new List <string> { "FixedRateTestShippingRateComputationMethod" }); shippingRateComputationMethods.Should().NotBeNull(); shippingRateComputationMethods.Any().Should().BeTrue(); }
/// <summary> /// Gets available shipping options /// </summary> /// <param name="cart">Shopping cart</param> /// <param name="shippingAddress">Shipping address</param> /// <param name="customer">Load records allowed only to a specified customer; pass null to ignore ACL permissions</param> /// <param name="allowedShippingRateComputationMethodSystemName">Filter by shipping rate computation method identifier; null to load shipping options of all shipping rate computation methods</param> /// <param name="storeId">Load records allowed only in a specified store; pass 0 to load all records</param> /// <returns>Shipping options</returns> public virtual async Task <GetShippingOptionResponse> GetShippingOptionsAsync(IList <ShoppingCartItem> cart, Address shippingAddress, Customer customer = null, string allowedShippingRateComputationMethodSystemName = "", int storeId = 0) { if (cart == null) { throw new ArgumentNullException(nameof(cart)); } var result = new GetShippingOptionResponse(); //create a package var(shippingOptionRequests, shippingFromMultipleLocations) = await CreateShippingOptionRequestsAsync(cart, shippingAddress, storeId); result.ShippingFromMultipleLocations = shippingFromMultipleLocations; var shippingRateComputationMethods = await _shippingPluginManager .LoadActivePluginsAsync(customer, storeId, allowedShippingRateComputationMethodSystemName); if (!shippingRateComputationMethods.Any()) { return(result); } //request shipping options from each shipping rate computation methods foreach (var srcm in shippingRateComputationMethods) { //request shipping options (separately for each package-request) IList <ShippingOption> srcmShippingOptions = null; foreach (var shippingOptionRequest in shippingOptionRequests) { var getShippingOptionResponse = await srcm.GetShippingOptionsAsync(shippingOptionRequest); if (getShippingOptionResponse.Success) { //success if (srcmShippingOptions == null) { //first shipping option request srcmShippingOptions = getShippingOptionResponse.ShippingOptions; } else { //get shipping options which already exist for prior requested packages for this scrm (i.e. common options) srcmShippingOptions = srcmShippingOptions .Where(existingso => getShippingOptionResponse.ShippingOptions.Any(newso => newso.Name == existingso.Name)) .ToList(); //and sum the rates foreach (var existingso in srcmShippingOptions) { existingso.Rate += getShippingOptionResponse .ShippingOptions .First(newso => newso.Name == existingso.Name) .Rate; } } } else { //errors foreach (var error in getShippingOptionResponse.Errors) { result.AddError(error); await _logger.WarningAsync($"Shipping ({srcm.PluginDescriptor.FriendlyName}). {error}"); } //clear the shipping options in this case srcmShippingOptions = new List <ShippingOption>(); break; } } //add this scrm's options to the result if (srcmShippingOptions == null) { continue; } foreach (var so in srcmShippingOptions) { //set system name if not set yet if (string.IsNullOrEmpty(so.ShippingRateComputationMethodSystemName)) { so.ShippingRateComputationMethodSystemName = srcm.PluginDescriptor.SystemName; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { so.Rate = await _priceCalculationService.RoundPriceAsync(so.Rate); } result.ShippingOptions.Add(so); } } if (_shippingSettings.ReturnValidOptionsIfThereAreAny) { //return valid options if there are any (no matter of the errors returned by other shipping rate computation methods). if (result.ShippingOptions.Any() && result.Errors.Any()) { result.Errors.Clear(); } } //no shipping options loaded if (!result.ShippingOptions.Any() && !result.Errors.Any()) { result.Errors.Add(await _localizationService.GetResourceAsync("Checkout.ShippingOptionCouldNotBeLoaded")); } return(result); }
/// <summary> /// Prepares the checkout pickup points model /// </summary> /// <param name="cart">Cart</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the checkout pickup points model /// </returns> protected virtual async Task <CheckoutPickupPointsModel> PrepareCheckoutPickupPointsModelAsync(IList <ShoppingCartItem> cart) { var model = new CheckoutPickupPointsModel { AllowPickupInStore = _shippingSettings.AllowPickupInStore }; if (!model.AllowPickupInStore) { return(model); } model.DisplayPickupPointsOnMap = _shippingSettings.DisplayPickupPointsOnMap; model.GoogleMapsApiKey = _shippingSettings.GoogleMapsApiKey; var pickupPointProviders = await _pickupPluginManager.LoadActivePluginsAsync(await _workContext.GetCurrentCustomerAsync(), (await _storeContext.GetCurrentStoreAsync()).Id); if (pickupPointProviders.Any()) { var languageId = (await _workContext.GetWorkingLanguageAsync()).Id; var pickupPointsResponse = await _shippingService.GetPickupPointsAsync((await _workContext.GetCurrentCustomerAsync()).BillingAddressId ?? 0, await _workContext.GetCurrentCustomerAsync(), storeId : (await _storeContext.GetCurrentStoreAsync()).Id); if (pickupPointsResponse.Success) { model.PickupPoints = await pickupPointsResponse.PickupPoints.SelectAwait(async point => { var country = await _countryService.GetCountryByTwoLetterIsoCodeAsync(point.CountryCode); var state = await _stateProvinceService.GetStateProvinceByAbbreviationAsync(point.StateAbbreviation, country?.Id); var pickupPointModel = new CheckoutPickupPointModel { Id = point.Id, Name = point.Name, Description = point.Description, ProviderSystemName = point.ProviderSystemName, Address = point.Address, City = point.City, County = point.County, StateName = state != null ? await _localizationService.GetLocalizedAsync(state, x => x.Name, languageId) : string.Empty, CountryName = country != null ? await _localizationService.GetLocalizedAsync(country, x => x.Name, languageId) : string.Empty, ZipPostalCode = point.ZipPostalCode, Latitude = point.Latitude, Longitude = point.Longitude, OpeningHours = point.OpeningHours }; var cart = await _shoppingCartService.GetShoppingCartAsync(await _workContext.GetCurrentCustomerAsync(), ShoppingCartType.ShoppingCart, (await _storeContext.GetCurrentStoreAsync()).Id); var amount = await _orderTotalCalculationService.IsFreeShippingAsync(cart) ? 0 : point.PickupFee; if (amount > 0) { (amount, _) = await _taxService.GetShippingPriceAsync(amount, await _workContext.GetCurrentCustomerAsync()); amount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(amount, await _workContext.GetWorkingCurrencyAsync()); pickupPointModel.PickupFee = await _priceFormatter.FormatShippingPriceAsync(amount, true); } //adjust rate var(shippingTotal, _) = await _orderTotalCalculationService.AdjustShippingRateAsync(point.PickupFee, cart, true); var(rateBase, _) = await _taxService.GetShippingPriceAsync(shippingTotal, await _workContext.GetCurrentCustomerAsync()); var rate = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(rateBase, await _workContext.GetWorkingCurrencyAsync()); pickupPointModel.PickupFee = await _priceFormatter.FormatShippingPriceAsync(rate, true); return(pickupPointModel); }).ToListAsync(); } else { foreach (var error in pickupPointsResponse.Errors) { model.Warnings.Add(error); } } } //only available pickup points var shippingProviders = await _shippingPluginManager.LoadActivePluginsAsync(await _workContext.GetCurrentCustomerAsync(), (await _storeContext.GetCurrentStoreAsync()).Id); if (!shippingProviders.Any()) { if (!pickupPointProviders.Any()) { model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.ShippingIsNotAllowed")); model.Warnings.Add(await _localizationService.GetResourceAsync("Checkout.PickupPoints.NotAvailable")); } model.PickupInStoreOnly = true; model.PickupInStore = true; return(model); } return(model); }