using Nop.Core; using Nop.Core.Caching; using Nop.Core.Domain.Common; using Nop.Services.Common; using Nop.Services.Configuration; using Nop.Services.Localization; using Nop.Services.Orders; using Nop.Web.Areas.Admin.Infrastructure.Cache; using Nop.Web.Areas.Admin.Models.Common; using Nop.Web.Areas.Admin.Models.Home; using Nop.Web.Areas.Admin.Models.Orders; using Nop.Web.Areas.Admin.Models.Reports; using Nop.Web.Framework.Models.DataTables; using ILogger = Nop.Services.Logging.ILogger; namespace Nop.Web.Areas.Admin.Factories; /// /// Represents the home models factory implementation /// public partial class HomeModelFactory : IHomeModelFactory { #region Fields protected readonly AdminAreaSettings _adminAreaSettings; protected readonly ICommonModelFactory _commonModelFactory; protected readonly ILocalizationService _localizationService; protected readonly ILogger _logger; protected readonly IOrderModelFactory _orderModelFactory; protected readonly ISettingService _settingService; protected readonly IStaticCacheManager _staticCacheManager; protected readonly IWorkContext _workContext; protected readonly NopHttpClient _nopHttpClient; #endregion #region Ctor public HomeModelFactory(AdminAreaSettings adminAreaSettings, ICommonModelFactory commonModelFactory, ILocalizationService localizationService, ILogger logger, IOrderModelFactory orderModelFactory, ISettingService settingService, IStaticCacheManager staticCacheManager, IWorkContext workContext, NopHttpClient nopHttpClient) { _adminAreaSettings = adminAreaSettings; _commonModelFactory = commonModelFactory; _localizationService = localizationService; _logger = logger; _orderModelFactory = orderModelFactory; _settingService = settingService; _staticCacheManager = staticCacheManager; _workContext = workContext; _nopHttpClient = nopHttpClient; } #endregion #region Methods /// /// Prepare dashboard model /// /// Dashboard model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareDashboardModelAsync(DashboardModel model) { ArgumentNullException.ThrowIfNull(model); model.IsLoggedInAsVendor = await _workContext.GetCurrentVendorAsync() != null; return model; } /// /// Prepare popular search term report model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PreparePopularSearchTermReportModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); var searchModel = new PopularSearchTermSearchModel(); searchModel = await _commonModelFactory.PreparePopularSearchTermSearchModelAsync(searchModel); model.Name = "search-term-report-grid"; model.UrlRead = new DataUrl("PopularSearchTermsReport", "Common", null); model.Length = searchModel.Length; model.LengthMenu = searchModel.AvailablePageSizes; model.RefreshButton = false; model.ColumnCollection = new List { new(nameof(PopularSearchTermModel.Keyword)) { Title = await _localizationService.GetResourceAsync("Admin.SearchTermReport.Keyword") }, new(nameof(PopularSearchTermModel.Count)) { Title = await _localizationService.GetResourceAsync("Admin.SearchTermReport.Count") } }; return model; } /// /// Prepare bestsellers brief by amount report model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareBestsellersBriefReportByAmountModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); var searchModel = new BestsellerBriefSearchModel(); searchModel = await _orderModelFactory.PrepareBestsellerBriefSearchModelAsync(searchModel); model.Name = "bestsellers-byamount-grid"; model.UrlRead = new DataUrl("BestsellersBriefReportByAmountList", "Order", new RouteValueDictionary { [nameof(searchModel.OrderBy)] = OrderByEnum.OrderByTotalAmount }); model.Length = searchModel.PageSize; model.RefreshButton = false; model.ColumnCollection = new List { new(nameof(BestsellerModel.ProductName)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.Name") }, new(nameof(BestsellerModel.TotalQuantity)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.TotalQuantity") }, new(nameof(BestsellerModel.TotalAmount)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.TotalAmount") }, new(nameof(BestsellerModel.ProductId)) { Title = await _localizationService.GetResourceAsync("Admin.Common.View"), Width = "80", ClassName = NopColumnClassDefaults.Button, Render = new RenderButtonView(new DataUrl("~/Admin/Product/Edit/")) } }; return model; } /// /// Prepare bestsellers brief by quantity report model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareBestsellersBriefReportByQuantityModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); var searchModel = new BestsellerBriefSearchModel(); searchModel = await _orderModelFactory.PrepareBestsellerBriefSearchModelAsync(searchModel); model.Name = "bestsellers-byquantity-grid"; model.UrlRead = new DataUrl("BestsellersBriefReportByQuantityList", "Order", new RouteValueDictionary { [nameof(searchModel.OrderBy)] = OrderByEnum.OrderByQuantity }); model.Length = searchModel.PageSize; model.RefreshButton = false; model.ColumnCollection = new List { new(nameof(BestsellerModel.ProductName)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.Name") }, new(nameof(BestsellerModel.TotalQuantity)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.TotalQuantity") }, new(nameof(BestsellerModel.TotalAmount)) { Title = await _localizationService.GetResourceAsync("Admin.Reports.Sales.Bestsellers.Fields.TotalAmount") }, new(nameof(BestsellerModel.ProductId)) { Title = await _localizationService.GetResourceAsync("Admin.Common.View"), Width = "80", ClassName = NopColumnClassDefaults.Button, Render = new RenderButtonView(new DataUrl("~/Admin/Product/Edit/")) } }; return model; } /// /// Prepare latest orders model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareLatestOrdersModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); model.Name = "orders-grid"; model.UrlRead = new DataUrl("OrderList", "Order", null); model.Length = 5; model.RefreshButton = false; model.ColumnCollection = new List { new(nameof(OrderModel.CustomOrderNumber)) { Title = await _localizationService.GetResourceAsync("Admin.Orders.Fields.CustomOrderNumber"), Width = "80" }, new(nameof(OrderModel.OrderStatus)) { Title = await _localizationService.GetResourceAsync("Admin.Orders.Fields.OrderStatus"), Width = "100", Render = new RenderCustom("renderColumnOrderStatus") }, new(nameof(OrderModel.CustomerEmail)) { Title = await _localizationService.GetResourceAsync("Admin.Orders.Fields.Customer"), Width = "250", Render = new RenderCustom("renderColumnCustomerEmail") }, new(nameof(OrderModel.CreatedOn)) { Title = await _localizationService.GetResourceAsync("Admin.Orders.Fields.CreatedOn"), Width = "100", Render = new RenderDate() }, new(nameof(OrderModel.Id)) { Title = await _localizationService.GetResourceAsync("Admin.Common.View"), Width = "50", ClassName = NopColumnClassDefaults.Button, Render = new RenderButtonView(new DataUrl("~/Admin/Order/Edit/")) } }; return model; } /// /// Prepare incomplete orders report model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareOrderIncompleteModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); model.Name = "incomplete-order-report-grid"; model.UrlRead = new DataUrl("OrderIncompleteReportList", "Order", null); model.Length = int.MaxValue; model.Paging = false; model.Info = false; model.ColumnCollection = new List { new(nameof(OrderIncompleteReportModel.Item)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Incomplete.Item") }, new(nameof(OrderIncompleteReportModel.Total)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Incomplete.Total"), Width = "50" }, new(nameof(OrderIncompleteReportModel.Count)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Incomplete.Count"), Width = "120", ClassName = NopColumnClassDefaults.Button, Render = new RenderCustom("renderColumnOrderIncompleteReportCount") } }; return model; } /// /// Prepare order average report model /// /// DataTables model /// /// A task that represents the asynchronous operation /// The task result contains the dashboard model /// public virtual async Task PrepareOrderAverageModelAsync(DataTablesModel model) { ArgumentNullException.ThrowIfNull(model); model.Name = "average-order-report-grid"; model.UrlRead = new DataUrl("OrderAverageReportList", "Order", null); model.Length = int.MaxValue; model.Paging = false; model.Info = false; model.ColumnCollection = new List { new(nameof(OrderAverageReportModel.OrderStatus)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.OrderStatus") }, new(nameof(OrderAverageReportModel.SumTodayOrders)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.SumTodayOrders") }, new(nameof(OrderAverageReportModel.SumThisWeekOrders)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.SumThisWeekOrders") }, new(nameof(OrderAverageReportModel.SumThisMonthOrders)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.SumThisMonthOrders") }, new(nameof(OrderAverageReportModel.SumThisYearOrders)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.SumThisYearOrders") }, new(nameof(OrderAverageReportModel.SumAllTimeOrders)) { Title = await _localizationService.GetResourceAsync("Admin.SalesReport.Average.SumAllTimeOrders") } }; return model; } /// /// Prepare nopCommerce news model /// /// /// A task that represents the asynchronous operation /// The task result contains the nopCommerce news model /// public virtual async Task PrepareNopCommerceNewsModelAsync() { var model = new NopCommerceNewsModel { HideAdvertisements = _adminAreaSettings.HideAdvertisementsOnAdminArea }; try { //try to get news RSS feed var rssData = await _staticCacheManager.GetAsync(_staticCacheManager.PrepareKeyForDefaultCache(NopModelCacheDefaults.OfficialNewsModelKey), async () => { try { return await _nopHttpClient.GetNewsRssAsync(); } catch (AggregateException exception) { //rethrow actual excepion throw exception.InnerException; } }); for (var i = 0; i < rssData.Items.Count; i++) { var item = rssData.Items.ElementAt(i); var newsItem = new NopCommerceNewsDetailsModel { Title = item.TitleText, Summary = XmlHelper.XmlDecode(item.Content?.Value ?? string.Empty), Url = item.Url.OriginalString, PublishDate = item.PublishDate }; model.Items.Add(newsItem); //has new items? if (i != 0) continue; var firstRequest = string.IsNullOrEmpty(_adminAreaSettings.LastNewsTitleAdminArea); if (_adminAreaSettings.LastNewsTitleAdminArea == newsItem.Title) continue; _adminAreaSettings.LastNewsTitleAdminArea = newsItem.Title; await _settingService.SaveSettingAsync(_adminAreaSettings); //new item if (!firstRequest) model.HasNewItems = true; } } catch (Exception ex) { await _logger.ErrorAsync("No access to the news. Website www.nopcommerce.com is not available.", ex); } return model; } #endregion }