Webiant Logo Webiant Logo
  1. No results found.

    Try your search with a different keyword or use * as a wildcard.

BaseAdminModelFactory.cs

using Microsoft.AspNetCore.Mvc.Rendering;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Discounts;
using Nop.Core.Domain.Gdpr;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Services;
using Nop.Services.Catalog;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Helpers;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Messages;
using Nop.Services.Plugins;
using Nop.Services.Shipping;
using Nop.Services.Shipping.Date;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Topics;
using Nop.Services.Vendors;
using Nop.Web.Areas.Admin.Infrastructure.Cache;
using LogLevel = Nop.Core.Domain.Logging.LogLevel;

namespace Nop.Web.Areas.Admin.Factories;

/// 
/// Represents the implementation of the base model factory that implements a most common admin model factories methods
/// 
public partial class BaseAdminModelFactory : IBaseAdminModelFactory
{
    #region Fields

    protected readonly ICategoryService _categoryService;
    protected readonly ICategoryTemplateService _categoryTemplateService;
    protected readonly ICountryService _countryService;
    protected readonly ICurrencyService _currencyService;
    protected readonly ICustomerActivityService _customerActivityService;
    protected readonly ICustomerService _customerService;
    protected readonly IDateRangeService _dateRangeService;
    protected readonly IDateTimeHelper _dateTimeHelper;
    protected readonly IEmailAccountService _emailAccountService;
    protected readonly ILanguageService _languageService;
    protected readonly ILocalizationService _localizationService;
    protected readonly IManufacturerService _manufacturerService;
    protected readonly IManufacturerTemplateService _manufacturerTemplateService;
    protected readonly IPluginService _pluginService;
    protected readonly IProductTemplateService _productTemplateService;
    protected readonly ISpecificationAttributeService _specificationAttributeService;
    protected readonly IShippingService _shippingService;
    protected readonly IStateProvinceService _stateProvinceService;
    protected readonly IStaticCacheManager _staticCacheManager;
    protected readonly IStoreService _storeService;
    protected readonly ITaxCategoryService _taxCategoryService;
    protected readonly ITopicTemplateService _topicTemplateService;
    protected readonly IVendorService _vendorService;

    #endregion

    #region Ctor

    public BaseAdminModelFactory(ICategoryService categoryService,
        ICategoryTemplateService categoryTemplateService,
        ICountryService countryService,
        ICurrencyService currencyService,
        ICustomerActivityService customerActivityService,
        ICustomerService customerService,
        IDateRangeService dateRangeService,
        IDateTimeHelper dateTimeHelper,
        IEmailAccountService emailAccountService,
        ILanguageService languageService,
        ILocalizationService localizationService,
        IManufacturerService manufacturerService,
        IManufacturerTemplateService manufacturerTemplateService,
        IPluginService pluginService,
        IProductTemplateService productTemplateService,
        ISpecificationAttributeService specificationAttributeService,
        IShippingService shippingService,
        IStateProvinceService stateProvinceService,
        IStaticCacheManager staticCacheManager,
        IStoreService storeService,
        ITaxCategoryService taxCategoryService,
        ITopicTemplateService topicTemplateService,
        IVendorService vendorService)
    {
        _categoryService = categoryService;
        _categoryTemplateService = categoryTemplateService;
        _countryService = countryService;
        _currencyService = currencyService;
        _customerActivityService = customerActivityService;
        _customerService = customerService;
        _dateRangeService = dateRangeService;
        _dateTimeHelper = dateTimeHelper;
        _emailAccountService = emailAccountService;
        _languageService = languageService;
        _localizationService = localizationService;
        _manufacturerService = manufacturerService;
        _manufacturerTemplateService = manufacturerTemplateService;
        _pluginService = pluginService;
        _productTemplateService = productTemplateService;
        _specificationAttributeService = specificationAttributeService;
        _shippingService = shippingService;
        _stateProvinceService = stateProvinceService;
        _staticCacheManager = staticCacheManager;
        _storeService = storeService;
        _taxCategoryService = taxCategoryService;
        _topicTemplateService = topicTemplateService;
        _vendorService = vendorService;
    }

    #endregion

    #region Utilities

    /// 
    /// Prepare default item
    /// 
    /// Available items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use "All" text
    /// Default item value; defaults 0
    /// A task that represents the asynchronous operation
    protected virtual async Task PrepareDefaultItemAsync(IList items, bool withSpecialDefaultItem, string defaultItemText = null, string defaultItemValue = "0")
    {
        ArgumentNullException.ThrowIfNull(items);

        //whether to insert the first special item for the default value
        if (!withSpecialDefaultItem)
            return;

        //prepare item text
        defaultItemText ??= await _localizationService.GetResourceAsync("Admin.Common.All");

        //insert this default item at first
        items.Insert(0, new SelectListItem { Text = defaultItemText, Value = defaultItemValue });
    }

    /// 
    /// Get category list
    /// 
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the category list
    /// 
    protected virtual async Task> GetCategoryListAsync()
    {
        var listItems = await _staticCacheManager.GetAsync(NopModelCacheDefaults.CategoriesListKey, async () =>
        {
            var categories = await _categoryService.GetAllCategoriesAsync(showHidden: true);
            return await categories.SelectAwait(async c => new SelectListItem
            {
                Text = await _categoryService.GetFormattedBreadCrumbAsync(c, categories),
                Value = c.Id.ToString()
            }).ToListAsync();
        });

        var result = new List();
        //clone the list to ensure that "selected" property is not set
        foreach (var item in listItems)
        {
            result.Add(new SelectListItem
            {
                Text = item.Text,
                Value = item.Value
            });
        }

        return result;
    }

    /// 
    /// Get manufacturer list
    /// 
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the manufacturer list
    /// 
    protected virtual async Task> GetManufacturerListAsync()
    {
        var listItems = await _staticCacheManager.GetAsync(NopModelCacheDefaults.ManufacturersListKey, async () =>
        {
            var manufacturers = await _manufacturerService.GetAllManufacturersAsync(showHidden: true);
            return manufacturers.Select(m => new SelectListItem
            {
                Text = m.Name,
                Value = m.Id.ToString()
            });
        });

        var result = new List();
        //clone the list to ensure that "selected" property is not set
        foreach (var item in listItems)
        {
            result.Add(new SelectListItem
            {
                Text = item.Text,
                Value = item.Value
            });
        }

        return result;
    }

    /// 
    /// Get vendor list
    /// 
    /// 
    /// A task that represents the asynchronous operation
    /// The task result contains the vendor list
    /// 
    protected virtual async Task> GetVendorListAsync()
    {
        var listItems = await _staticCacheManager.GetAsync(NopModelCacheDefaults.VendorsListKey, async () =>
        {
            var vendors = await _vendorService.GetAllVendorsAsync(showHidden: true);
            return vendors.Select(v => new SelectListItem
            {
                Text = v.Name,
                Value = v.Id.ToString()
            });
        });

        var result = new List();
        //clone the list to ensure that "selected" property is not set
        foreach (var item in listItems)
        {
            result.Add(new SelectListItem
            {
                Text = item.Text,
                Value = item.Value
            });
        }

        return result;
    }

    #endregion

    #region Methods

    /// 
    /// Prepare available activity log types
    /// 
    /// Activity log type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareActivityLogTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available activity log types
        var availableActivityTypes = await _customerActivityService.GetAllActivityTypesAsync();
        foreach (var activityType in availableActivityTypes)
        {
            items.Add(new SelectListItem { Value = activityType.Id.ToString(), Text = activityType.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available order statuses
    /// 
    /// Order status items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareOrderStatusesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available order statuses
        var availableStatusItems = await OrderStatus.Pending.ToSelectListAsync(false);
        foreach (var statusItem in availableStatusItems)
        {
            items.Add(statusItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available payment statuses
    /// 
    /// Payment status items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PreparePaymentStatusesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available payment statuses
        var availableStatusItems = await PaymentStatus.Pending.ToSelectListAsync(false);
        foreach (var statusItem in availableStatusItems)
        {
            items.Add(statusItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available shipping statuses
    /// 
    /// Shipping status items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareShippingStatusesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available shipping statuses
        var availableStatusItems = await ShippingStatus.NotYetShipped.ToSelectListAsync(false);
        foreach (var statusItem in availableStatusItems)
        {
            items.Add(statusItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available countries
    /// 
    /// Country items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareCountriesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available countries
        var availableCountries = await _countryService.GetAllCountriesAsync(showHidden: true);
        foreach (var country in availableCountries)
        {
            items.Add(new SelectListItem { Value = country.Id.ToString(), Text = country.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText ?? await _localizationService.GetResourceAsync("Admin.Address.SelectCountry"));
    }

    /// 
    /// Prepare available states and provinces
    /// 
    /// State and province items
    /// Country identifier; pass null to don't load states and provinces
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareStatesAndProvincesAsync(IList items, int? countryId,
        bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        if (countryId.HasValue)
        {
            //prepare available states and provinces of the country
            var availableStates = await _stateProvinceService.GetStateProvincesByCountryIdAsync(countryId.Value, showHidden: true);
            foreach (var state in availableStates)
            {
                items.Add(new SelectListItem { Value = state.Id.ToString(), Text = state.Name });
            }

            //insert special item for the default value
            if (items.Count > 1)
                await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText ?? await _localizationService.GetResourceAsync("Admin.Address.SelectState"));
        }

        //insert special item for the default value
        if (!items.Any())
            await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText ?? await _localizationService.GetResourceAsync("Admin.Address.Other"));
    }

    /// 
    /// Prepare available languages
    /// 
    /// Language items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareLanguagesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available languages
        var availableLanguages = await _languageService.GetAllLanguagesAsync(showHidden: true);
        foreach (var language in availableLanguages)
        {
            items.Add(new SelectListItem { Value = language.Id.ToString(), Text = language.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available stores
    /// 
    /// Store items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareStoresAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available stores
        var availableStores = await _storeService.GetAllStoresAsync();
        foreach (var store in availableStores)
        {
            items.Add(new SelectListItem { Value = store.Id.ToString(), Text = store.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available customer roles
    /// 
    /// Customer role items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareCustomerRolesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available customer roles
        var availableCustomerRoles = await _customerService.GetAllCustomerRolesAsync();
        foreach (var customerRole in availableCustomerRoles)
        {
            items.Add(new SelectListItem { Value = customerRole.Id.ToString(), Text = customerRole.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available email accounts
    /// 
    /// Email account items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareEmailAccountsAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available email accounts
        var availableEmailAccounts = await _emailAccountService.GetAllEmailAccountsAsync();
        foreach (var emailAccount in availableEmailAccounts)
        {
            items.Add(new SelectListItem { Value = emailAccount.Id.ToString(), Text = $"{emailAccount.DisplayName} ({emailAccount.Email})" });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available tax categories
    /// 
    /// Tax category items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareTaxCategoriesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available tax categories
        var availableTaxCategories = await _taxCategoryService.GetAllTaxCategoriesAsync();
        foreach (var taxCategory in availableTaxCategories)
        {
            items.Add(new SelectListItem { Value = taxCategory.Id.ToString(), Text = taxCategory.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem,
            defaultItemText ?? await _localizationService.GetResourceAsync("Admin.Configuration.Settings.Tax.TaxCategories.None"));
    }

    /// 
    /// Prepare available categories
    /// 
    /// Category items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareCategoriesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available categories
        var availableCategoryItems = await GetCategoryListAsync();
        foreach (var categoryItem in availableCategoryItems)
        {
            items.Add(categoryItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available manufacturers
    /// 
    /// Manufacturer items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareManufacturersAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available manufacturers
        var availableManufacturerItems = await GetManufacturerListAsync();
        foreach (var manufacturerItem in availableManufacturerItems)
        {
            items.Add(manufacturerItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available vendors
    /// 
    /// Vendor items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareVendorsAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available vendors
        var availableVendorItems = await GetVendorListAsync();
        foreach (var vendorItem in availableVendorItems)
        {
            items.Add(vendorItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available product types
    /// 
    /// Product type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareProductTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available product types
        var availableProductTypeItems = await ProductType.SimpleProduct.ToSelectListAsync(false);
        foreach (var productTypeItem in availableProductTypeItems)
        {
            items.Add(productTypeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available category templates
    /// 
    /// Category template items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareCategoryTemplatesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available category templates
        var availableTemplates = await _categoryTemplateService.GetAllCategoryTemplatesAsync();
        foreach (var template in availableTemplates)
        {
            items.Add(new SelectListItem { Value = template.Id.ToString(), Text = template.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available time zones
    /// 
    /// Time zone items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareTimeZonesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available time zones
        var availableTimeZones = _dateTimeHelper.GetSystemTimeZones();
        foreach (var timeZone in availableTimeZones)
        {
            items.Add(new SelectListItem { Value = timeZone.Id, Text = timeZone.DisplayName });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available shopping cart types
    /// 
    /// Shopping cart type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareShoppingCartTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available shopping cart types
        var availableShoppingCartTypeItems = await ShoppingCartType.ShoppingCart.ToSelectListAsync(false);
        foreach (var shoppingCartTypeItem in availableShoppingCartTypeItems)
        {
            items.Add(shoppingCartTypeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available tax display types
    /// 
    /// Tax display type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareTaxDisplayTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available tax display types
        var availableTaxDisplayTypeItems = await TaxDisplayType.ExcludingTax.ToSelectListAsync(false);
        foreach (var taxDisplayTypeItem in availableTaxDisplayTypeItems)
        {
            items.Add(taxDisplayTypeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available currencies
    /// 
    /// Currency items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareCurrenciesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available currencies
        var availableCurrencies = await _currencyService.GetAllCurrenciesAsync(true);
        foreach (var currency in availableCurrencies)
        {
            items.Add(new SelectListItem { Value = currency.Id.ToString(), Text = currency.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available discount types
    /// 
    /// Discount type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareDiscountTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available discount types
        var availableDiscountTypeItems = await DiscountType.AssignedToOrderTotal.ToSelectListAsync(false);
        foreach (var discountTypeItem in availableDiscountTypeItems)
        {
            items.Add(discountTypeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available log levels
    /// 
    /// Log level items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareLogLevelsAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available log levels
        var availableLogLevelItems = await LogLevel.Debug.ToSelectListAsync(false);
        foreach (var logLevelItem in availableLogLevelItems)
        {
            items.Add(logLevelItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available manufacturer templates
    /// 
    /// Manufacturer template items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareManufacturerTemplatesAsync(IList items,
        bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available manufacturer templates
        var availableTemplates = await _manufacturerTemplateService.GetAllManufacturerTemplatesAsync();
        foreach (var template in availableTemplates)
        {
            items.Add(new SelectListItem { Value = template.Id.ToString(), Text = template.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available load plugin modes
    /// 
    /// Load plugin mode items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareLoadPluginModesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available load plugin modes
        var availableLoadPluginModeItems = await LoadPluginsMode.All.ToSelectListAsync(false);
        foreach (var loadPluginModeItem in availableLoadPluginModeItems)
        {
            items.Add(loadPluginModeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available plugin groups
    /// 
    /// Plugin group items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PreparePluginGroupsAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available plugin groups
        var availablePluginGroups = (await _pluginService.GetPluginDescriptorsAsync(LoadPluginsMode.All))
            .Select(plugin => plugin.Group).Distinct().OrderBy(groupName => groupName).ToList();
        foreach (var group in availablePluginGroups)
            items.Add(new SelectListItem { Value = @group, Text = @group });

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available return request statuses
    /// 
    /// Return request status items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareReturnRequestStatusesAsync(IList items,
        bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available return request statuses
        var availableStatusItems = await ReturnRequestStatus.Pending.ToSelectListAsync(false);
        foreach (var statusItem in availableStatusItems)
        {
            items.Add(statusItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available product templates
    /// 
    /// Product template items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareProductTemplatesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available product templates
        var availableTemplates = await _productTemplateService.GetAllProductTemplatesAsync();
        foreach (var template in availableTemplates)
        {
            items.Add(new SelectListItem { Value = template.Id.ToString(), Text = template.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available topic templates
    /// 
    /// Topic template items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareTopicTemplatesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available topic templates
        var availableTemplates = await _topicTemplateService.GetAllTopicTemplatesAsync();
        foreach (var template in availableTemplates)
        {
            items.Add(new SelectListItem { Value = template.Id.ToString(), Text = template.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available warehouses
    /// 
    /// Warehouse items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareWarehousesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available warehouses
        var availableWarehouses = await _shippingService.GetAllWarehousesAsync();
        foreach (var warehouse in availableWarehouses)
        {
            items.Add(new SelectListItem { Value = warehouse.Id.ToString(), Text = warehouse.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available delivery dates
    /// 
    /// Delivery date items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareDeliveryDatesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available delivery dates
        var availableDeliveryDates = await _dateRangeService.GetAllDeliveryDatesAsync();
        foreach (var date in availableDeliveryDates)
        {
            items.Add(new SelectListItem { Value = date.Id.ToString(), Text = date.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available product availability ranges
    /// 
    /// Product availability range items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareProductAvailabilityRangesAsync(IList items,
        bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available product availability ranges
        var availableProductAvailabilityRanges = await _dateRangeService.GetAllProductAvailabilityRangesAsync();
        foreach (var range in availableProductAvailabilityRanges)
        {
            items.Add(new SelectListItem { Value = range.Id.ToString(), Text = range.Name });
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available GDPR request types
    /// 
    /// Request type items
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareGdprRequestTypesAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available request types
        var gdprRequestTypeItems = await GdprRequestType.ConsentAgree.ToSelectListAsync(false);
        foreach (var gdprRequestTypeItem in gdprRequestTypeItems)
        {
            items.Add(gdprRequestTypeItem);
        }

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText);
    }

    /// 
    /// Prepare available specification attribute groups
    /// 
    /// Specification attributes
    /// Whether to insert the first special item for the default value
    /// Default item text; pass null to use default value of the default item text
    /// A task that represents the asynchronous operation
    public virtual async Task PrepareSpecificationAttributeGroupsAsync(IList items, bool withSpecialDefaultItem = true, string defaultItemText = null)
    {
        ArgumentNullException.ThrowIfNull(items);

        //prepare available specification attribute groups
        var availableSpecificationAttributeGroups = await _specificationAttributeService.GetSpecificationAttributeGroupsAsync();
        foreach (var group in availableSpecificationAttributeGroups)
        {
            items.Add(new SelectListItem { Value = group.Id.ToString(), Text = group.Name });
        }

        // use empty string for nullable field
        var defaultItemValue = string.Empty;

        //insert special item for the default value
        await PrepareDefaultItemAsync(items, withSpecialDefaultItem, defaultItemText, defaultItemValue);
    }

    #endregion
}