using Nop.Core.Domain.Shipping; using Nop.Services.Common; using Nop.Services.Directory; using Nop.Services.Localization; using Nop.Services.Shipping; using Nop.Services.Shipping.Date; using Nop.Services.Shipping.Pickup; using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions; using Nop.Web.Areas.Admin.Models.Directory; using Nop.Web.Areas.Admin.Models.Shipping; using Nop.Web.Framework.Factories; using Nop.Web.Framework.Models.Extensions; namespace Nop.Web.Areas.Admin.Factories; /// /// Represents the shipping model factory implementation /// public partial class ShippingModelFactory : IShippingModelFactory { #region Fields protected readonly IAddressModelFactory _addressModelFactory; protected readonly IAddressService _addressService; protected readonly ICountryService _countryService; protected readonly IDateRangeService _dateRangeService; protected readonly ILocalizationService _localizationService; protected readonly ILocalizedModelFactory _localizedModelFactory; protected readonly IPickupPluginManager _pickupPluginManager; protected readonly IShippingPluginManager _shippingPluginManager; protected readonly IShippingService _shippingService; protected readonly IStateProvinceService _stateProvinceService; #endregion #region Ctor public ShippingModelFactory(IAddressModelFactory addressModelFactory, IAddressService addressService, ICountryService countryService, IDateRangeService dateRangeService, ILocalizationService localizationService, ILocalizedModelFactory localizedModelFactory, IPickupPluginManager pickupPluginManager, IShippingPluginManager shippingPluginManager, IShippingService shippingService, IStateProvinceService stateProvinceService) { _addressModelFactory = addressModelFactory; _addressService = addressService; _countryService = countryService; _dateRangeService = dateRangeService; _localizationService = localizationService; _localizedModelFactory = localizedModelFactory; _pickupPluginManager = pickupPluginManager; _shippingPluginManager = shippingPluginManager; _shippingService = shippingService; _stateProvinceService = stateProvinceService; } #endregion #region Utilities /// /// Prepare delivery date search model /// /// Delivery date search model /// Delivery date search model protected virtual DeliveryDateSearchModel PrepareDeliveryDateSearchModel(DeliveryDateSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } /// /// Prepare product availability range search model /// /// Product availability range search model /// Product availability range search model protected virtual ProductAvailabilityRangeSearchModel PrepareProductAvailabilityRangeSearchModel(ProductAvailabilityRangeSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return searchModel; } #endregion #region Methods /// /// Prepare shipping provider search model /// /// Shipping provider search model /// /// A task that represents the asynchronous operation /// The task result contains the shipping provider search model /// public virtual Task PrepareShippingProviderSearchModelAsync(ShippingProviderSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return Task.FromResult(searchModel); } /// /// Prepare paged shipping provider list model /// /// Shipping provider search model /// /// A task that represents the asynchronous operation /// The task result contains the shipping provider list model /// public virtual async Task PrepareShippingProviderListModelAsync(ShippingProviderSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get shipping providers var shippingProviders = (await _shippingPluginManager.LoadAllPluginsAsync()).ToPagedList(searchModel); //prepare grid model var model = await new ShippingProviderListModel().PrepareToGridAsync(searchModel, shippingProviders, () => { return shippingProviders.SelectAwait(async provider => { //fill in model values from the entity var shippingProviderModel = provider.ToPluginModel(); //fill in additional values (not existing in the entity) shippingProviderModel.IsActive = _shippingPluginManager.IsPluginActive(provider); shippingProviderModel.ConfigurationUrl = provider.GetConfigurationPageUrl(); shippingProviderModel.LogoUrl = await _shippingPluginManager.GetPluginLogoUrlAsync(provider); return shippingProviderModel; }); }); return model; } /// /// Prepare pickup point provider search model /// /// Pickup point provider search model /// /// A task that represents the asynchronous operation /// The task result contains the pickup point provider search model /// public virtual Task PreparePickupPointProviderSearchModelAsync(PickupPointProviderSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return Task.FromResult(searchModel); } /// /// Prepare paged pickup point provider list model /// /// Pickup point provider search model /// /// A task that represents the asynchronous operation /// The task result contains the pickup point provider list model /// public virtual async Task PreparePickupPointProviderListModelAsync(PickupPointProviderSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get pickup point providers var pickupPointProviders = (await _pickupPluginManager.LoadAllPluginsAsync()).ToPagedList(searchModel); //prepare grid model var model = await new PickupPointProviderListModel().PrepareToGridAsync(searchModel, pickupPointProviders, () => { return pickupPointProviders.SelectAwait(async provider => { //fill in model values from the entity var pickupPointProviderModel = provider.ToPluginModel(); //fill in additional values (not existing in the entity) pickupPointProviderModel.IsActive = _pickupPluginManager.IsPluginActive(provider); pickupPointProviderModel.ConfigurationUrl = provider.GetConfigurationPageUrl(); pickupPointProviderModel.LogoUrl = await _pickupPluginManager.GetPluginLogoUrlAsync(provider); return pickupPointProviderModel; }); }); return model; } /// /// Prepare shipping method search model /// /// Shipping method search model /// /// A task that represents the asynchronous operation /// The task result contains the shipping method search model /// public virtual Task PrepareShippingMethodSearchModelAsync(ShippingMethodSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return Task.FromResult(searchModel); } /// /// Prepare paged shipping method list model /// /// Shipping method search model /// /// A task that represents the asynchronous operation /// The task result contains the shipping method list model /// public virtual async Task PrepareShippingMethodListModelAsync(ShippingMethodSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get shipping methods var shippingMethods = (await _shippingService.GetAllShippingMethodsAsync()).ToPagedList(searchModel); //prepare grid model var model = new ShippingMethodListModel().PrepareToGrid(searchModel, shippingMethods, () => { return shippingMethods.Select(method => method.ToModel()); }); return model; } /// /// Prepare shipping method model /// /// Shipping method model /// Shipping method /// Whether to exclude populating of some properties of model /// /// A task that represents the asynchronous operation /// The task result contains the shipping method model /// public virtual async Task PrepareShippingMethodModelAsync(ShippingMethodModel model, ShippingMethod shippingMethod, bool excludeProperties = false) { Func localizedModelConfiguration = null; if (shippingMethod != null) { //fill in model values from the entity model ??= shippingMethod.ToModel(); //define localized model configuration action localizedModelConfiguration = async (locale, languageId) => { locale.Name = await _localizationService.GetLocalizedAsync(shippingMethod, entity => entity.Name, languageId, false, false); locale.Description = await _localizationService.GetLocalizedAsync(shippingMethod, entity => entity.Description, languageId, false, false); }; } //prepare localized models if (!excludeProperties) model.Locales = await _localizedModelFactory.PrepareLocalizedModelsAsync(localizedModelConfiguration); return model; } /// /// Prepare dates and ranges search model /// /// Dates and ranges search model /// /// A task that represents the asynchronous operation /// The task result contains the dates and ranges search model /// public virtual Task PrepareDatesRangesSearchModelAsync(DatesRangesSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare nested search models PrepareDeliveryDateSearchModel(searchModel.DeliveryDateSearchModel); PrepareProductAvailabilityRangeSearchModel(searchModel.ProductAvailabilityRangeSearchModel); return Task.FromResult(searchModel); } /// /// Prepare paged delivery date list model /// /// Delivery date search model /// /// A task that represents the asynchronous operation /// The task result contains the delivery date list model /// public virtual async Task PrepareDeliveryDateListModelAsync(DeliveryDateSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get delivery dates var deliveryDates = (await _dateRangeService.GetAllDeliveryDatesAsync()).ToPagedList(searchModel); //prepare grid model var model = new DeliveryDateListModel().PrepareToGrid(searchModel, deliveryDates, () => { //fill in model values from the entity return deliveryDates.Select(date => date.ToModel()); }); return model; } /// /// Prepare delivery date model /// /// Delivery date model /// Delivery date /// Whether to exclude populating of some properties of model /// /// A task that represents the asynchronous operation /// The task result contains the delivery date model /// public virtual async Task PrepareDeliveryDateModelAsync(DeliveryDateModel model, DeliveryDate deliveryDate, bool excludeProperties = false) { Func localizedModelConfiguration = null; if (deliveryDate != null) { //fill in model values from the entity model ??= deliveryDate.ToModel(); //define localized model configuration action localizedModelConfiguration = async (locale, languageId) => { locale.Name = await _localizationService.GetLocalizedAsync(deliveryDate, entity => entity.Name, languageId, false, false); }; } //prepare localized models if (!excludeProperties) model.Locales = await _localizedModelFactory.PrepareLocalizedModelsAsync(localizedModelConfiguration); return model; } /// /// Prepare paged product availability range list model /// /// Product availability range search model /// /// A task that represents the asynchronous operation /// The task result contains the product availability range list model /// public virtual async Task PrepareProductAvailabilityRangeListModelAsync(ProductAvailabilityRangeSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get product availability ranges var productAvailabilityRanges = (await _dateRangeService.GetAllProductAvailabilityRangesAsync()).ToPagedList(searchModel); //prepare grid model var model = new ProductAvailabilityRangeListModel().PrepareToGrid(searchModel, productAvailabilityRanges, () => { //fill in model values from the entity return productAvailabilityRanges.Select(range => range.ToModel()); }); return model; } /// /// Prepare product availability range model /// /// Product availability range model /// Product availability range /// Whether to exclude populating of some properties of model /// /// A task that represents the asynchronous operation /// The task result contains the product availability range model /// public virtual async Task PrepareProductAvailabilityRangeModelAsync(ProductAvailabilityRangeModel model, ProductAvailabilityRange productAvailabilityRange, bool excludeProperties = false) { Func localizedModelConfiguration = null; if (productAvailabilityRange != null) { //fill in model values from the entity model ??= productAvailabilityRange.ToModel(); //define localized model configuration action localizedModelConfiguration = async (locale, languageId) => { locale.Name = await _localizationService.GetLocalizedAsync(productAvailabilityRange, entity => entity.Name, languageId, false, false); }; } //prepare localized models if (!excludeProperties) model.Locales = await _localizedModelFactory.PrepareLocalizedModelsAsync(localizedModelConfiguration); return model; } /// /// Prepare warehouse search model /// /// Warehouse search model /// /// A task that represents the asynchronous operation /// The task result contains the warehouse search model /// public virtual Task PrepareWarehouseSearchModelAsync(WarehouseSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //prepare page parameters searchModel.SetGridPageSize(); return Task.FromResult(searchModel); } /// /// Prepare paged warehouse list model /// /// Warehouse search model /// /// A task that represents the asynchronous operation /// The task result contains the warehouse list model /// public virtual async Task PrepareWarehouseListModelAsync(WarehouseSearchModel searchModel) { ArgumentNullException.ThrowIfNull(searchModel); //get warehouses var warehouses = (await _shippingService.GetAllWarehousesAsync( name: searchModel.SearchName)) .ToPagedList(searchModel); //prepare list model var model = new WarehouseListModel().PrepareToGrid(searchModel, warehouses, () => { //fill in model values from the entity return warehouses.Select(warehouse => warehouse.ToModel()); }); return model; } /// /// Prepare warehouse model /// /// Warehouse model /// Warehouse /// Whether to exclude populating of some properties of model /// /// A task that represents the asynchronous operation /// The task result contains the warehouse model /// public virtual async Task PrepareWarehouseModelAsync(WarehouseModel model, Warehouse warehouse, bool excludeProperties = false) { if (warehouse != null) { //fill in model values from the entity if (model == null) { model = warehouse.ToModel(); } } //prepare address model var address = await _addressService.GetAddressByIdAsync(warehouse?.AddressId ?? 0); if (!excludeProperties && address != null) model.Address = address.ToModel(model.Address); await _addressModelFactory.PrepareAddressModelAsync(model.Address, address); model.Address.CountryRequired = true; model.Address.ZipPostalCodeRequired = true; return model; } /// /// Prepare shipping method restriction model /// /// Shipping method restriction model /// /// A task that represents the asynchronous operation /// The task result contains the shipping method restriction model /// public virtual async Task PrepareShippingMethodRestrictionModelAsync(ShippingMethodRestrictionModel model) { ArgumentNullException.ThrowIfNull(model); var countries = await _countryService.GetAllCountriesAsync(showHidden: true); model.AvailableCountries = await countries.SelectAwait(async country => { var countryModel = country.ToModel(); countryModel.NumberOfStates = (await _stateProvinceService.GetStateProvincesByCountryIdAsync(country.Id))?.Count ?? 0; return countryModel; }).ToListAsync(); foreach (var shippingMethod in await _shippingService.GetAllShippingMethodsAsync()) { model.AvailableShippingMethods.Add(shippingMethod.ToModel()); foreach (var country in countries) { if (!model.Restricted.ContainsKey(country.Id)) model.Restricted[country.Id] = new Dictionary(); model.Restricted[country.Id][shippingMethod.Id] = await _shippingService.CountryRestrictionExistsAsync(shippingMethod, country.Id); } } return model; } #endregion }