protected virtual void ConvertAvailability(CatalogSearchQuery query, RouteData routeData, string origin) { bool availability; GetValueFor(query, "a", FacetGroupKind.Availability, out availability); // Setting specifies the logical direction of the filter. That's smarter than just to specify a default value. if (_searchSettings.IncludeNotAvailable) { // False = show, True = hide unavailable products. if (availability) { query.AvailableOnly(true); } } else { // False = hide, True = show unavailable products. if (!availability) { query.AvailableOnly(true); } } AddFacet(query, FacetGroupKind.Availability, true, FacetSorting.LabelAsc, descriptor => { descriptor.MinHitCount = 0; var newValue = availability ? new FacetValue(true, IndexTypeCode.Boolean) : new FacetValue(null, IndexTypeCode.Empty); newValue.IsSelected = availability; newValue.Label = _services.Localization.GetResource(_searchSettings.IncludeNotAvailable ? "Search.Facet.ExcludeOutOfStock" : "Search.Facet.IncludeOutOfStock"); descriptor.AddValue(newValue); }); }
protected virtual void ConvertDeliveryTime(CatalogSearchQuery query, RouteData routeData, string origin) { List <int> ids; if (GetValueFor(query, "d", FacetGroupKind.DeliveryTime, out ids) && ids != null && ids.Any()) { query.WithDeliveryTimeIds(ids.ToArray()); } AddFacet(query, FacetGroupKind.DeliveryTime, true, FacetSorting.DisplayOrder, descriptor => { if (ids != null) { foreach (var id in ids) { descriptor.AddValue(new FacetValue(id, IndexTypeCode.Int32) { IsSelected = true }); } } }); }
protected virtual void ConvertRating(CatalogSearchQuery query, string origin) { var alias = _catalogSearchQueryAliasMapper.GetCommonFacetAliasByGroupKind(FacetGroupKind.Rating, query.LanguageId ?? 0); if (TryGetValueFor(alias ?? "r", out double?fromRate) && fromRate.HasValue) { query.WithRating(fromRate, null); } AddFacet(query, FacetGroupKind.Rating, false, FacetSorting.DisplayOrder, descriptor => { descriptor.MinHitCount = 0; descriptor.MaxChoicesCount = 5; if (fromRate.HasValue) { descriptor.AddValue(new FacetValue(fromRate.Value, IndexTypeCode.Double) { IsSelected = true }); } }); }
protected virtual void ConvertRating(CatalogSearchQuery query, RouteData routeData, string origin) { double?fromRate; if (GetValueFor(query, "r", FacetGroupKind.Rating, out fromRate) && fromRate.HasValue) { query.WithRating(fromRate, null); } AddFacet(query, FacetGroupKind.Rating, false, FacetSorting.DisplayOrder, descriptor => { descriptor.MinHitCount = 0; descriptor.MaxChoicesCount = 5; if (fromRate.HasValue) { descriptor.AddValue(new FacetValue(fromRate.Value, IndexTypeCode.Double) { IsSelected = true }); } }); }
protected virtual void ConvertDeliveryTime(CatalogSearchQuery query, string origin) { var alias = _catalogSearchQueryAliasMapper.GetCommonFacetAliasByGroupKind(FacetGroupKind.DeliveryTime, query.LanguageId ?? 0); if (TryGetValueFor(alias ?? "d", out List <int> ids) && ids != null && ids.Any()) { query.WithDeliveryTimeIds(ids.ToArray()); } AddFacet(query, FacetGroupKind.DeliveryTime, true, FacetSorting.DisplayOrder, descriptor => { if (ids != null) { foreach (var id in ids) { descriptor.AddValue(new FacetValue(id, IndexTypeCode.Int32) { IsSelected = true }); } } }); }
private decimal?CalculatePrice(int key, bool lowestPrice) { string requiredProperties = "TierPrices, AppliedDiscounts, ProductBundleItems"; var entity = GetExpandedEntity(key, requiredProperties); var customer = Services.WorkContext.CurrentCustomer; decimal?result = null; this.ProcessEntity(() => { if (lowestPrice) { if (entity.ProductType == ProductType.GroupedProduct) { Product lowestPriceProduct; var searchQuery = new CatalogSearchQuery() .VisibleOnly() .HasParentGroupedProduct(entity.Id); var query = _catalogSearchService.Value.PrepareQuery(searchQuery, GetExpandedEntitySet(requiredProperties)); var associatedProducts = query.OrderBy(x => x.DisplayOrder).ToList(); result = _priceCalculationService.Value.GetLowestPrice(entity, customer, null, associatedProducts, out lowestPriceProduct); } else { bool displayFromMessage; result = _priceCalculationService.Value.GetLowestPrice(entity, customer, null, out displayFromMessage); } } else { result = _priceCalculationService.Value.GetPreselectedPrice(entity, customer, Services.WorkContext.WorkingCurrency, null); } }); return(result); }
/// <param name="contextProduct">The product or the first associated product of a group.</param> /// <returns>The final price</returns> private decimal MapSummaryItemPrice(Product product, ref Product contextProduct, ProductSummaryModel.SummaryItem item, MapProductSummaryItemContext ctx) { var displayFromMessage = false; var taxRate = decimal.Zero; var oldPriceBase = decimal.Zero; var oldPrice = decimal.Zero; var finalPriceBase = decimal.Zero; var finalPrice = decimal.Zero; var displayPrice = decimal.Zero; ICollection <Product> associatedProducts = null; var priceModel = new ProductSummaryModel.PriceModel(); item.Price = priceModel; if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing && !ctx.BatchContext.ProductBundleItems.FullyLoaded) { ctx.BatchContext.ProductBundleItems.LoadAll(); } if (product.ProductType == ProductType.GroupedProduct) { priceModel.DisableBuyButton = true; priceModel.DisableWishlistButton = true; priceModel.AvailableForPreOrder = false; if (ctx.GroupedProducts == null) { // One-time batched retrieval of all associated products. var searchQuery = new CatalogSearchQuery() .PublishedOnly(true) .HasStoreId(ctx.Store.Id) .HasParentGroupedProduct(ctx.BatchContext.ProductIds.ToArray()); // Get all associated products for this batch grouped by ParentGroupedProductId. var allAssociatedProducts = _catalogSearchService.Search(searchQuery).Hits .OrderBy(x => x.ParentGroupedProductId) .ThenBy(x => x.DisplayOrder); ctx.GroupedProducts = allAssociatedProducts.ToMultimap(x => x.ParentGroupedProductId, x => x); ctx.AssociatedProductBatchContext = _dataExporter.Value.CreateProductExportContext(allAssociatedProducts, ctx.Customer, null, null, false); } associatedProducts = ctx.GroupedProducts[product.Id]; if (associatedProducts.Any()) { contextProduct = associatedProducts.OrderBy(x => x.DisplayOrder).First(); _services.DisplayControl.Announce(contextProduct); } } else { priceModel.DisableBuyButton = product.DisableBuyButton || !ctx.AllowShoppingCart || !ctx.AllowPrices; priceModel.DisableWishlistButton = product.DisableWishlistButton || !ctx.AllowWishlist || !ctx.AllowPrices; priceModel.AvailableForPreOrder = product.AvailableForPreOrder; } // Return if there's no pricing at all. if (contextProduct == null || contextProduct.CustomerEntersPrice || !ctx.AllowPrices || _catalogSettings.PriceDisplayType == PriceDisplayType.Hide) { return(finalPrice); } // Return if group has no associated products. if (product.ProductType == ProductType.GroupedProduct && !associatedProducts.Any()) { return(finalPrice); } // Call for price. priceModel.CallForPrice = contextProduct.CallForPrice; if (contextProduct.CallForPrice) { priceModel.Price = ctx.Resources["Products.CallForPrice"]; return(finalPrice); } // Calculate prices. var batchContext = product.ProductType == ProductType.GroupedProduct ? ctx.AssociatedProductBatchContext : ctx.BatchContext; if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { displayPrice = _priceCalculationService.GetPreselectedPrice(contextProduct, ctx.Customer, ctx.Currency, batchContext); } else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) { displayPrice = _priceCalculationService.GetFinalPrice(contextProduct, null, ctx.Customer, decimal.Zero, false, 1, null, batchContext); } else { // Display lowest price. if (product.ProductType == ProductType.GroupedProduct) { displayFromMessage = true; displayPrice = _priceCalculationService.GetLowestPrice(product, ctx.Customer, batchContext, associatedProducts, out contextProduct) ?? decimal.Zero; } else { displayPrice = _priceCalculationService.GetLowestPrice(product, ctx.Customer, batchContext, out displayFromMessage); } } oldPriceBase = _taxService.GetProductPrice(contextProduct, contextProduct.OldPrice, out taxRate); finalPriceBase = _taxService.GetProductPrice(contextProduct, displayPrice, out taxRate); oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, ctx.Currency); finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, ctx.Currency); priceModel.PriceValue = finalPrice; priceModel.Price = displayFromMessage ? string.Format(ctx.Resources["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)) : _priceFormatter.FormatPrice(finalPrice); priceModel.HasDiscount = oldPriceBase > decimal.Zero && oldPriceBase > finalPriceBase; if (priceModel.HasDiscount) { priceModel.RegularPriceValue = oldPrice; priceModel.RegularPrice = _priceFormatter.FormatPrice(oldPrice); } // Calculate saving. var finalPriceWithDiscount = _priceCalculationService.GetFinalPrice(contextProduct, null, ctx.Customer, decimal.Zero, true, 1, null, batchContext); finalPriceWithDiscount = _taxService.GetProductPrice(contextProduct, finalPriceWithDiscount, out taxRate); finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscount, ctx.Currency); var finalPriceWithoutDiscount = finalPrice; if (_catalogSettings.PriceDisplayType != PriceDisplayType.PriceWithoutDiscountsAndAttributes) { finalPriceWithoutDiscount = _priceCalculationService.GetFinalPrice(contextProduct, null, ctx.Customer, decimal.Zero, false, 1, null, batchContext); finalPriceWithoutDiscount = _taxService.GetProductPrice(contextProduct, finalPriceWithoutDiscount, out taxRate); finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscount, ctx.Currency); } // Discounted price has priority over the old price (avoids differing percentage discount in product lists and detail page). var regularPrice = finalPriceWithDiscount < finalPriceWithoutDiscount ? finalPriceWithoutDiscount : oldPrice; if (regularPrice > 0 && regularPrice > finalPriceWithDiscount) { priceModel.HasDiscount = true; priceModel.SavingPercent = (float)((regularPrice - finalPriceWithDiscount) / regularPrice) * 100; priceModel.SavingAmount = _priceFormatter.FormatPrice(regularPrice - finalPriceWithDiscount, true, false); if (!priceModel.RegularPriceValue.HasValue) { priceModel.RegularPriceValue = regularPrice; priceModel.RegularPrice = _priceFormatter.FormatPrice(regularPrice); } if (ctx.Model.ShowDiscountBadge) { item.Badges.Add(new ProductSummaryModel.Badge { Label = T("Products.SavingBadgeLabel", priceModel.SavingPercent.ToString("N0")), Style = BadgeStyle.Danger }); } } return(finalPrice); }
public SearchResultModel(CatalogSearchQuery query) { Query = query; HitGroups = new List <HitGroup>(); }
public virtual void InheritAclIntoChildren( int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) { var category = GetCategoryById(categoryId); var subcategories = GetAllCategoriesByParentCategoryId(categoryId, true); var allCustomerRoles = _customerService.GetAllCustomerRoles(true); var categoryCustomerRoles = _aclService.GetCustomerRoleIdsWithAccessTo(category); var categoryIds = new HashSet <int>(subcategories.Select(x => x.Id)); categoryIds.Add(categoryId); var searchQuery = new CatalogSearchQuery() .WithCategoryIds(null, categoryIds.ToArray()); var query = _catalogSearchService.PrepareQuery(searchQuery); var products = query.OrderBy(p => p.Id).ToList(); using (var scope = new DbContextScope(ctx: _aclRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) { _aclRepository.AutoCommitEnabled = false; foreach (var subcategory in subcategories) { if (subcategory.SubjectToAcl != category.SubjectToAcl) { subcategory.SubjectToAcl = category.SubjectToAcl; _categoryRepository.Update(subcategory); } var existingAclRecords = _aclService.GetAclRecords(subcategory).ToDictionarySafe(x => x.CustomerRoleId); foreach (var customerRole in allCustomerRoles) { if (categoryCustomerRoles.Contains(customerRole.Id)) { if (!existingAclRecords.ContainsKey(customerRole.Id)) { _aclRepository.Insert(new AclRecord { CustomerRole = customerRole, CustomerRoleId = customerRole.Id, EntityId = subcategory.Id, EntityName = "Category" }); } } else { if (existingAclRecords.TryGetValue(customerRole.Id, out var aclRecordToDelete)) { _aclRepository.Delete(aclRecordToDelete); } } } } _aclRepository.Context.SaveChanges(); foreach (var product in products) { if (product.SubjectToAcl != category.SubjectToAcl) { product.SubjectToAcl = category.SubjectToAcl; _productRepository.Update(product); } var existingAclRecords = _aclService.GetAclRecords(product).ToDictionarySafe(x => x.CustomerRoleId); foreach (var customerRole in allCustomerRoles) { if (categoryCustomerRoles.Contains(customerRole.Id)) { if (!existingAclRecords.ContainsKey(customerRole.Id)) { _aclRepository.Insert(new AclRecord { CustomerRole = customerRole, CustomerRoleId = customerRole.Id, EntityId = product.Id, EntityName = "Product" }); } } else { if (existingAclRecords.TryGetValue(customerRole.Id, out var aclRecordToDelete)) { _aclRepository.Delete(aclRecordToDelete); } } } } _aclRepository.Context.SaveChanges(); } }
public async Task <IActionResult> RecentlyAddedProductsRSS(CatalogSearchQuery query) { // TODO: (mc) find a more prominent place for the "NewProducts" link (may be in main menu?) var store = Services.StoreContext.CurrentStore; var protocol = Services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; var selfLink = Url.RouteUrl("RecentlyAddedProductsRSS", null, protocol); var recentProductsLink = Url.RouteUrl("RecentlyAddedProducts", null, protocol); var title = $"{store.Name} - {T("RSS.RecentlyAddedProducts")}"; var feed = new SmartSyndicationFeed(new Uri(recentProductsLink), title, T("RSS.InformationAboutProducts")); feed.AddNamespaces(true); feed.Init(selfLink, Services.WorkContext.WorkingLanguage.LanguageCulture); if (!_catalogSettings.RecentlyAddedProductsEnabled || _catalogSettings.RecentlyAddedProductsNumber <= 0) { return(new RssActionResult { Feed = feed }); } var items = new List <SyndicationItem>(); query.Sorting.Clear(); query = query .BuildFacetMap(false) .SortBy(ProductSortingEnum.CreatedOn) .Slice(0, _catalogSettings.RecentlyAddedProductsNumber); var result = await _catalogSearchService.SearchAsync(query); var hits = await result.GetHitsAsync(); var storeUrl = store.GetHost(); // Prefetching. var fileIds = hits .Select(x => x.MainPictureId ?? 0) .Where(x => x != 0) .Distinct() .ToArray(); var files = (await Services.MediaService.GetFilesByIdsAsync(fileIds)).ToDictionarySafe(x => x.Id); foreach (var product in hits) { var productUrl = Url.RouteUrl("Product", new { SeName = await product.GetActiveSlugAsync() }, protocol); if (productUrl.HasValue()) { var content = product.GetLocalized(x => x.FullDescription).Value; if (content.HasValue()) { content = WebHelper.MakeAllUrlsAbsolute(content, Request); } var item = feed.CreateItem( product.GetLocalized(x => x.Name), product.GetLocalized(x => x.ShortDescription), productUrl, product.CreatedOnUtc, content); try { // We add only the first media file. if (files.TryGetValue(product.MainPictureId ?? 0, out var file)) { var url = Services.MediaService.GetUrl(file, _mediaSettings.ProductDetailsPictureSize, storeUrl, false); feed.AddEnclosure(item, file, url); } } catch { } items.Add(item); } } feed.Items = items; Services.DisplayControl.AnnounceRange(hits); return(new RssActionResult { Feed = feed }); }
public ActionResult Category(int categoryId, CatalogSearchQuery query) { var category = _categoryService.GetCategoryById(categoryId); if (category == null || category.Deleted) { return(HttpNotFound()); } // Check whether the current user has a "Manage catalog" permission. // It allows him to preview a category before publishing. if (!category.Published && !Services.Permissions.Authorize(Permissions.Catalog.Category.Read)) { return(HttpNotFound()); } // ACL (access control list). if (!_aclService.Authorize(category)) { return(HttpNotFound()); } // Store mapping. if (!_storeMappingService.Authorize(category)) { return(HttpNotFound()); } var store = Services.StoreContext.CurrentStore; var customer = Services.WorkContext.CurrentCustomer; // 'Continue shopping' URL. if (!Services.WorkContext.CurrentCustomer.IsSystemAccount) { _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.LastContinueShoppingPage, Services.WebHelper.GetThisPageUrl(false), store.Id); } var model = category.ToModel(); if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages) { model.Description.ChangeValue(string.Empty); model.BottomDescription.ChangeValue(string.Empty); } Services.DisplayControl.Announce(category); // Category breadcrumb. if (_catalogSettings.CategoryBreadcrumbEnabled) { _helper.GetCategoryBreadcrumb(_breadcrumb, ControllerContext); } // Products. var catIds = new int[] { categoryId }; if (_catalogSettings.ShowProductsFromSubcategories) { // Include subcategories. catIds = catIds.Concat(_helper.GetChildCategoryIds(categoryId)).ToArray(); } query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? (bool?)null : false, catIds); var searchResult = _catalogSearchService.Search(query); model.SearchResult = searchResult; var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(query.GetViewMode()); model.Products = _helper.MapProductSummaryModel(searchResult.Hits, mappingSettings); model.SubCategoryDisplayType = _catalogSettings.SubCategoryDisplayType; var customerRolesIds = customer.CustomerRoleMappings .Select(x => x.CustomerRole) .Where(x => x.Active) .Select(x => x.Id) .ToList(); var pictureSize = _mediaSettings.CategoryThumbPictureSize; var fallbackType = _catalogSettings.HideCategoryDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity; var hideSubCategories = _catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.Hide || (_catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.AboveProductList && query.IsSubPage && !_catalogSettings.ShowSubCategoriesInSubPages); var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages); // Subcategories. if (!hideSubCategories) { var subCategories = _categoryService.GetAllCategoriesByParentCategoryId(categoryId); model.SubCategories = _helper.MapCategorySummaryModel(subCategories, pictureSize); } // Featured Products. if (!hideFeaturedProducts) { CatalogSearchResult featuredProductsResult = null; string cacheKey = ModelCacheEventConsumer.CATEGORY_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(categoryId, string.Join(",", customerRolesIds), store.Id); var hasFeaturedProductsCache = Services.Cache.Get <bool?>(cacheKey); var featuredProductsQuery = new CatalogSearchQuery() .VisibleOnly(customer) .WithVisibility(ProductVisibility.Full) .WithCategoryIds(true, categoryId) .HasStoreId(Services.StoreContext.CurrentStore.Id) .WithLanguage(Services.WorkContext.WorkingLanguage) .WithCurrency(Services.WorkContext.WorkingCurrency); if (!hasFeaturedProductsCache.HasValue) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0; Services.Cache.Put(cacheKey, hasFeaturedProductsCache, TimeSpan.FromHours(6)); } if (hasFeaturedProductsCache.Value && featuredProductsResult == null) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); } if (featuredProductsResult != null) { var featuredProductsmappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid); model.FeaturedProducts = _helper.MapProductSummaryModel(featuredProductsResult.Hits, featuredProductsmappingSettings); } } // Prepare paging/sorting/mode stuff. _helper.MapListActions(model.Products, category, _catalogSettings.DefaultPageSizeOptions); // Template. var templateCacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_TEMPLATE_MODEL_KEY, category.CategoryTemplateId); var templateViewPath = Services.Cache.Get(templateCacheKey, () => { var template = _categoryTemplateService.GetCategoryTemplateById(category.CategoryTemplateId); if (template == null) { template = _categoryTemplateService.GetAllCategoryTemplates().FirstOrDefault(); } return(template.ViewPath); }); // Activity log. Services.CustomerActivity.InsertActivity("PublicStore.ViewCategory", T("ActivityLog.PublicStore.ViewCategory"), category.Name); return(View(templateViewPath, model)); }
public virtual void InheritAclIntoChildren( int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) { var allCustomerRoles = _customerService.GetAllCustomerRoles(true); var referenceCategory = GetCategoryById(categoryId); var referenceRoleIds = _aclService.GetCustomerRoleIdsWithAccessTo(referenceCategory); using (var scope = new DbContextScope(ctx: _aclRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false)) { ProcessCategory(scope, referenceCategory); } _cache.RemoveByPattern(AclService.ACL_SEGMENT_PATTERN); void ProcessCategory(DbContextScope scope, Category c) { // Process sub-categories. var subCategories = GetAllCategoriesByParentCategoryId(c.Id, true); foreach (var subCategory in subCategories) { if (subCategory.SubjectToAcl != referenceCategory.SubjectToAcl) { subCategory.SubjectToAcl = referenceCategory.SubjectToAcl; _categoryRepository.Update(subCategory); } var existingAclRecords = _aclService.GetAclRecords(subCategory).ToDictionarySafe(x => x.CustomerRoleId); foreach (var role in allCustomerRoles) { if (referenceRoleIds.Contains(role.Id)) { if (!existingAclRecords.ContainsKey(role.Id)) { _aclRepository.Insert(new AclRecord { CustomerRoleId = role.Id, EntityId = subCategory.Id, EntityName = "Category" }); } } else if (existingAclRecords.TryGetValue(role.Id, out var aclRecordToDelete)) { _aclRepository.Delete(aclRecordToDelete); } } } scope.Commit(); // Process products. var categoryIds = new HashSet <int>(subCategories.Select(x => x.Id)); categoryIds.Add(c.Id); var searchQuery = new CatalogSearchQuery().WithCategoryIds(null, categoryIds.ToArray()); var productsQuery = _catalogSearchService.PrepareQuery(searchQuery); var productsPager = new FastPager <Product>(productsQuery, 500); while (productsPager.ReadNextPage(out var products)) { foreach (var product in products) { if (product.SubjectToAcl != referenceCategory.SubjectToAcl) { product.SubjectToAcl = referenceCategory.SubjectToAcl; _productRepository.Update(product); } var existingAclRecords = _aclService.GetAclRecords(product).ToDictionarySafe(x => x.CustomerRoleId); foreach (var role in allCustomerRoles) { if (referenceRoleIds.Contains(role.Id)) { if (!existingAclRecords.ContainsKey(role.Id)) { _aclRepository.Insert(new AclRecord { CustomerRoleId = role.Id, EntityId = product.Id, EntityName = "Product" }); } } else if (existingAclRecords.TryGetValue(role.Id, out var aclRecordToDelete)) { _aclRepository.Delete(aclRecordToDelete); } } } scope.Commit(); } scope.Commit(); try { scope.DbContext.DetachEntities(x => x is Product || x is Category || x is AclRecord, false); } catch { } foreach (var subCategory in subCategories) { ProcessCategory(scope, subCategory); } } }
/// <summary> /// Create a copy of product with all depended data /// </summary> /// <param name="product">The product</param> /// <param name="newName">The name of product duplicate</param> /// <param name="isPublished">A value indicating whether the product duplicate should be published</param> /// <param name="copyImages">A value indicating whether the product images should be copied</param> /// <param name="copyAssociatedProducts">A value indicating whether the copy associated products</param> /// <returns>Product entity</returns> public virtual Product CopyProduct(Product product, string newName, bool isPublished, bool copyImages, bool copyAssociatedProducts = true) { if (product == null) { throw new ArgumentNullException("product"); } if (String.IsNullOrEmpty(newName)) { throw new ArgumentException("Product name is required"); } Product productCopy = null; var utcNow = DateTime.UtcNow; // product download & sample download int downloadId = 0; int?sampleDownloadId = null; if (product.IsDownload) { var download = _downloadService.GetDownloadById(product.DownloadId); if (download != null) { var downloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = download.UseDownloadUrl, DownloadUrl = download.DownloadUrl, ContentType = download.ContentType, Filename = download.Filename, Extension = download.Extension, IsNew = download.IsNew, UpdatedOnUtc = utcNow }; if ((download.MediaStorageId ?? 0) != 0 && download.MediaStorage != null) { _downloadService.InsertDownload(downloadCopy, download.MediaStorage.Data); } else { _downloadService.InsertDownload(downloadCopy, null); } downloadId = downloadCopy.Id; } if (product.HasSampleDownload) { var sampleDownload = _downloadService.GetDownloadById(product.SampleDownloadId.GetValueOrDefault()); if (sampleDownload != null) { var sampleDownloadCopy = new Download { DownloadGuid = Guid.NewGuid(), UseDownloadUrl = sampleDownload.UseDownloadUrl, DownloadUrl = sampleDownload.DownloadUrl, ContentType = sampleDownload.ContentType, Filename = sampleDownload.Filename, Extension = sampleDownload.Extension, IsNew = sampleDownload.IsNew, UpdatedOnUtc = utcNow }; if ((sampleDownload.MediaStorageId ?? 0) != 0 && sampleDownload.MediaStorage != null) { _downloadService.InsertDownload(sampleDownloadCopy, sampleDownload.MediaStorage.Data); } else { _downloadService.InsertDownload(sampleDownloadCopy, null); } sampleDownloadId = sampleDownloadCopy.Id; } } } // product productCopy = new Product { ProductTypeId = product.ProductTypeId, ParentGroupedProductId = product.ParentGroupedProductId, VisibleIndividually = product.VisibleIndividually, Name = newName, ShortDescription = product.ShortDescription, FullDescription = product.FullDescription, ProductTemplateId = product.ProductTemplateId, AdminComment = product.AdminComment, ShowOnHomePage = product.ShowOnHomePage, HomePageDisplayOrder = product.HomePageDisplayOrder, MetaKeywords = product.MetaKeywords, MetaDescription = product.MetaDescription, MetaTitle = product.MetaTitle, AllowCustomerReviews = product.AllowCustomerReviews, LimitedToStores = product.LimitedToStores, Sku = product.Sku, ManufacturerPartNumber = product.ManufacturerPartNumber, Gtin = product.Gtin, IsGiftCard = product.IsGiftCard, GiftCardType = product.GiftCardType, RequireOtherProducts = product.RequireOtherProducts, RequiredProductIds = product.RequiredProductIds, AutomaticallyAddRequiredProducts = product.AutomaticallyAddRequiredProducts, IsDownload = product.IsDownload, DownloadId = downloadId, UnlimitedDownloads = product.UnlimitedDownloads, MaxNumberOfDownloads = product.MaxNumberOfDownloads, DownloadExpirationDays = product.DownloadExpirationDays, DownloadActivationType = product.DownloadActivationType, HasSampleDownload = product.HasSampleDownload, SampleDownloadId = sampleDownloadId, HasUserAgreement = product.HasUserAgreement, UserAgreementText = product.UserAgreementText, IsRecurring = product.IsRecurring, RecurringCycleLength = product.RecurringCycleLength, RecurringCyclePeriod = product.RecurringCyclePeriod, RecurringTotalCycles = product.RecurringTotalCycles, IsShipEnabled = product.IsShipEnabled, IsFreeShipping = product.IsFreeShipping, AdditionalShippingCharge = product.AdditionalShippingCharge, IsEsd = product.IsEsd, IsTaxExempt = product.IsTaxExempt, TaxCategoryId = product.TaxCategoryId, ManageInventoryMethod = product.ManageInventoryMethod, StockQuantity = product.StockQuantity, DisplayStockAvailability = product.DisplayStockAvailability, DisplayStockQuantity = product.DisplayStockQuantity, MinStockQuantity = product.MinStockQuantity, LowStockActivityId = product.LowStockActivityId, NotifyAdminForQuantityBelow = product.NotifyAdminForQuantityBelow, BackorderMode = product.BackorderMode, AllowBackInStockSubscriptions = product.AllowBackInStockSubscriptions, OrderMinimumQuantity = product.OrderMinimumQuantity, OrderMaximumQuantity = product.OrderMaximumQuantity, HideQuantityControl = product.HideQuantityControl, AllowedQuantities = product.AllowedQuantities, DisableBuyButton = product.DisableBuyButton, DisableWishlistButton = product.DisableWishlistButton, AvailableForPreOrder = product.AvailableForPreOrder, CallForPrice = product.CallForPrice, Price = product.Price, OldPrice = product.OldPrice, ProductCost = product.ProductCost, SpecialPrice = product.SpecialPrice, SpecialPriceStartDateTimeUtc = product.SpecialPriceStartDateTimeUtc, SpecialPriceEndDateTimeUtc = product.SpecialPriceEndDateTimeUtc, CustomerEntersPrice = product.CustomerEntersPrice, MinimumCustomerEnteredPrice = product.MinimumCustomerEnteredPrice, MaximumCustomerEnteredPrice = product.MaximumCustomerEnteredPrice, LowestAttributeCombinationPrice = product.LowestAttributeCombinationPrice, Weight = product.Weight, Length = product.Length, Width = product.Width, Height = product.Height, AvailableStartDateTimeUtc = product.AvailableStartDateTimeUtc, AvailableEndDateTimeUtc = product.AvailableEndDateTimeUtc, DisplayOrder = product.DisplayOrder, Published = isPublished, Deleted = product.Deleted, DeliveryTimeId = product.DeliveryTimeId, QuantityUnitId = product.QuantityUnitId, BasePriceEnabled = product.BasePriceEnabled, BasePriceMeasureUnit = product.BasePriceMeasureUnit, BasePriceAmount = product.BasePriceAmount, BasePriceBaseAmount = product.BasePriceBaseAmount, BundleTitleText = product.BundleTitleText, BundlePerItemShipping = product.BundlePerItemShipping, BundlePerItemPricing = product.BundlePerItemPricing, BundlePerItemShoppingCart = product.BundlePerItemShoppingCart, CustomsTariffNumber = product.CustomsTariffNumber, CountryOfOriginId = product.CountryOfOriginId }; _productService.InsertProduct(productCopy); //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", productCopy.Name, true), 0); var languages = _languageService.GetAllLanguages(true); //localization foreach (var lang in languages) { var name = product.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.Name, name, lang.Id); } var shortDescription = product.GetLocalized(x => x.ShortDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(shortDescription)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.ShortDescription, shortDescription, lang.Id); } var fullDescription = product.GetLocalized(x => x.FullDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(fullDescription)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.FullDescription, fullDescription, lang.Id); } var metaKeywords = product.GetLocalized(x => x.MetaKeywords, lang.Id, false, false); if (!String.IsNullOrEmpty(metaKeywords)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaKeywords, metaKeywords, lang.Id); } var metaDescription = product.GetLocalized(x => x.MetaDescription, lang.Id, false, false); if (!String.IsNullOrEmpty(metaDescription)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaDescription, metaDescription, lang.Id); } var metaTitle = product.GetLocalized(x => x.MetaTitle, lang.Id, false, false); if (!String.IsNullOrEmpty(metaTitle)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.MetaTitle, metaTitle, lang.Id); } var bundleTitleText = product.GetLocalized(x => x.BundleTitleText, lang.Id, false, false); if (!String.IsNullOrEmpty(bundleTitleText)) { _localizedEntityService.SaveLocalizedValue(productCopy, x => x.BundleTitleText, bundleTitleText, lang.Id); } //search engine name _urlRecordService.SaveSlug(productCopy, productCopy.ValidateSeName("", name, false), lang.Id); } // product pictures if (copyImages) { foreach (var productPicture in product.ProductPictures) { var picture = productPicture.Picture; var pictureCopy = _pictureService.InsertPicture( _pictureService.LoadPictureBinary(picture), picture.MimeType, _pictureService.GetPictureSeName(newName), true, false, false); _productService.InsertProductPicture(new ProductPicture { ProductId = productCopy.Id, PictureId = pictureCopy.Id, DisplayOrder = productPicture.DisplayOrder }); } } // product <-> categories mappings foreach (var productCategory in product.ProductCategories) { var productCategoryCopy = new ProductCategory { ProductId = productCopy.Id, CategoryId = productCategory.CategoryId, IsFeaturedProduct = productCategory.IsFeaturedProduct, DisplayOrder = productCategory.DisplayOrder }; _categoryService.InsertProductCategory(productCategoryCopy); } // product <-> manufacturers mappings foreach (var productManufacturers in product.ProductManufacturers) { var productManufacturerCopy = new ProductManufacturer { ProductId = productCopy.Id, ManufacturerId = productManufacturers.ManufacturerId, IsFeaturedProduct = productManufacturers.IsFeaturedProduct, DisplayOrder = productManufacturers.DisplayOrder }; _manufacturerService.InsertProductManufacturer(productManufacturerCopy); } // product <-> releated products mappings foreach (var relatedProduct in _productService.GetRelatedProductsByProductId1(product.Id, true)) { _productService.InsertRelatedProduct(new RelatedProduct { ProductId1 = productCopy.Id, ProductId2 = relatedProduct.ProductId2, DisplayOrder = relatedProduct.DisplayOrder }); } // product <-> cross sells mappings foreach (var csProduct in _productService.GetCrossSellProductsByProductId1(product.Id, true)) { _productService.InsertCrossSellProduct(new CrossSellProduct { ProductId1 = productCopy.Id, ProductId2 = csProduct.ProductId2, }); } // product specifications foreach (var productSpecificationAttribute in product.ProductSpecificationAttributes) { var psaCopy = new ProductSpecificationAttribute { ProductId = productCopy.Id, SpecificationAttributeOptionId = productSpecificationAttribute.SpecificationAttributeOptionId, AllowFiltering = productSpecificationAttribute.AllowFiltering, ShowOnProductPage = productSpecificationAttribute.ShowOnProductPage, DisplayOrder = productSpecificationAttribute.DisplayOrder }; _specificationAttributeService.InsertProductSpecificationAttribute(psaCopy); } //store mapping var selectedStoreIds = _storeMappingService.GetStoresIdsWithAccess(product); foreach (var id in selectedStoreIds) { _storeMappingService.InsertStoreMapping(productCopy, id); } // product <-> attributes mappings var associatedAttributes = new Dictionary <int, int>(); var associatedAttributeValues = new Dictionary <int, int>(); foreach (var productVariantAttribute in _productAttributeService.GetProductVariantAttributesByProductId(product.Id)) { var productVariantAttributeCopy = new ProductVariantAttribute { ProductId = productCopy.Id, ProductAttributeId = productVariantAttribute.ProductAttributeId, TextPrompt = productVariantAttribute.TextPrompt, IsRequired = productVariantAttribute.IsRequired, AttributeControlTypeId = productVariantAttribute.AttributeControlTypeId, DisplayOrder = productVariantAttribute.DisplayOrder }; _productAttributeService.InsertProductVariantAttribute(productVariantAttributeCopy); //save associated value (used for combinations copying) associatedAttributes.Add(productVariantAttribute.Id, productVariantAttributeCopy.Id); // product variant attribute values var productVariantAttributeValues = _productAttributeService.GetProductVariantAttributeValues(productVariantAttribute.Id); foreach (var productVariantAttributeValue in productVariantAttributeValues) { var pvavCopy = new ProductVariantAttributeValue { ProductVariantAttributeId = productVariantAttributeCopy.Id, Name = productVariantAttributeValue.Name, Color = productVariantAttributeValue.Color, PriceAdjustment = productVariantAttributeValue.PriceAdjustment, WeightAdjustment = productVariantAttributeValue.WeightAdjustment, IsPreSelected = productVariantAttributeValue.IsPreSelected, DisplayOrder = productVariantAttributeValue.DisplayOrder, ValueTypeId = productVariantAttributeValue.ValueTypeId, LinkedProductId = productVariantAttributeValue.LinkedProductId, Quantity = productVariantAttributeValue.Quantity, }; _productAttributeService.InsertProductVariantAttributeValue(pvavCopy); //save associated value (used for combinations copying) associatedAttributeValues.Add(productVariantAttributeValue.Id, pvavCopy.Id); //localization foreach (var lang in languages) { var name = productVariantAttributeValue.GetLocalized(x => x.Name, lang.Id, false, false); if (!String.IsNullOrEmpty(name)) { _localizedEntityService.SaveLocalizedValue(pvavCopy, x => x.Name, name, lang.Id); } } } } // attribute combinations using (var scope = new DbContextScope(lazyLoading: false, forceNoTracking: false)) { scope.LoadCollection(product, (Product p) => p.ProductVariantAttributeCombinations); } foreach (var combination in product.ProductVariantAttributeCombinations) { //generate new AttributesXml according to new value IDs string newAttributesXml = ""; var parsedProductVariantAttributes = _productAttributeParser.ParseProductVariantAttributes(combination.AttributesXml); foreach (var oldPva in parsedProductVariantAttributes) { if (associatedAttributes.ContainsKey(oldPva.Id)) { int newPvaId = associatedAttributes[oldPva.Id]; var newPva = _productAttributeService.GetProductVariantAttributeById(newPvaId); if (newPva != null) { var oldPvaValuesStr = _productAttributeParser.ParseValues(combination.AttributesXml, oldPva.Id); foreach (var oldPvaValueStr in oldPvaValuesStr) { if (newPva.ShouldHaveValues()) { //attribute values int oldPvaValue = int.Parse(oldPvaValueStr); if (associatedAttributeValues.ContainsKey(oldPvaValue)) { int newPvavId = associatedAttributeValues[oldPvaValue]; var newPvav = _productAttributeService.GetProductVariantAttributeValueById(newPvavId); if (newPvav != null) { newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, newPvav.Id.ToString()); } } } else { //just a text newAttributesXml = _productAttributeParser.AddProductAttribute(newAttributesXml, newPva, oldPvaValueStr); } } } } } var combinationCopy = new ProductVariantAttributeCombination { ProductId = productCopy.Id, AttributesXml = newAttributesXml, StockQuantity = combination.StockQuantity, AllowOutOfStockOrders = combination.AllowOutOfStockOrders, // SmartStore extension Sku = combination.Sku, Gtin = combination.Gtin, ManufacturerPartNumber = combination.ManufacturerPartNumber, Price = combination.Price, AssignedPictureIds = copyImages ? combination.AssignedPictureIds : null, Length = combination.Length, Width = combination.Width, Height = combination.Height, BasePriceAmount = combination.BasePriceAmount, BasePriceBaseAmount = combination.BasePriceBaseAmount, DeliveryTimeId = combination.DeliveryTimeId, QuantityUnitId = combination.QuantityUnitId, IsActive = combination.IsActive //IsDefaultCombination = combination.IsDefaultCombination }; _productAttributeService.InsertProductVariantAttributeCombination(combinationCopy); } // tier prices foreach (var tierPrice in product.TierPrices) { _productService.InsertTierPrice(new TierPrice { ProductId = productCopy.Id, StoreId = tierPrice.StoreId, CustomerRoleId = tierPrice.CustomerRoleId, Quantity = tierPrice.Quantity, Price = tierPrice.Price }); } // product <-> discounts mapping foreach (var discount in product.AppliedDiscounts) { productCopy.AppliedDiscounts.Add(discount); _productService.UpdateProduct(productCopy); } // update "HasTierPrices" and "HasDiscountsApplied" properties _productService.UpdateHasTierPricesProperty(productCopy); _productService.UpdateLowestAttributeCombinationPriceProperty(productCopy); _productService.UpdateHasDiscountsApplied(productCopy); // associated products if (copyAssociatedProducts && product.ProductType != ProductType.BundledProduct) { var copyOf = _localizationService.GetResource("Admin.Common.CopyOf"); var searchQuery = new CatalogSearchQuery() .HasParentGroupedProduct(product.Id); var query = _catalogSearchService.PrepareQuery(searchQuery); var associatedProducts = query.OrderBy(p => p.DisplayOrder).ToList(); foreach (var associatedProduct in associatedProducts) { var associatedProductCopy = CopyProduct(associatedProduct, $"{copyOf} {associatedProduct.Name}", isPublished, copyImages, false); associatedProductCopy.ParentGroupedProductId = productCopy.Id; _productService.UpdateProduct(productCopy); } } // bundled products var bundledItems = _productService.GetBundleItems(product.Id, true); foreach (var bundleItem in bundledItems) { var newBundleItem = bundleItem.Item.Clone(); newBundleItem.BundleProductId = productCopy.Id; _productService.InsertBundleItem(newBundleItem); foreach (var itemFilter in bundleItem.Item.AttributeFilters) { var newItemFilter = itemFilter.Clone(); newItemFilter.BundleItemId = newBundleItem.Id; _productAttributeService.InsertProductBundleItemAttributeFilter(newItemFilter); } } return(productCopy); }
private void AddFacet( CatalogSearchQuery query, FacetGroupKind kind, bool isMultiSelect, FacetSorting sorting, Action <FacetDescriptor> addValues) { string fieldName; var displayOrder = 0; switch (kind) { case FacetGroupKind.Category: fieldName = _catalogSettings.IncludeFeaturedProductsInNormalLists ? "categoryid" : "notfeaturedcategoryid"; break; case FacetGroupKind.Brand: if (_searchSettings.BrandDisabled) { return; } fieldName = "manufacturerid"; displayOrder = _searchSettings.BrandDisplayOrder; break; case FacetGroupKind.Price: if (_searchSettings.PriceDisabled || !_services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices)) { return; } fieldName = "price"; displayOrder = _searchSettings.PriceDisplayOrder; break; case FacetGroupKind.Rating: if (_searchSettings.RatingDisabled) { return; } fieldName = "rating"; displayOrder = _searchSettings.RatingDisplayOrder; break; case FacetGroupKind.DeliveryTime: if (_searchSettings.DeliveryTimeDisabled) { return; } fieldName = "deliveryid"; displayOrder = _searchSettings.DeliveryTimeDisplayOrder; break; case FacetGroupKind.Availability: if (_searchSettings.AvailabilityDisabled) { return; } fieldName = "available"; displayOrder = _searchSettings.AvailabilityDisplayOrder; break; case FacetGroupKind.NewArrivals: if (_searchSettings.NewArrivalsDisabled) { return; } fieldName = "createdon"; displayOrder = _searchSettings.NewArrivalsDisplayOrder; break; default: throw new SmartException($"Unknown field name for facet group '{kind.ToString()}'"); } var descriptor = new FacetDescriptor(fieldName); descriptor.Label = _services.Localization.GetResource(FacetUtility.GetLabelResourceKey(kind) ?? kind.ToString()); descriptor.IsMultiSelect = isMultiSelect; descriptor.DisplayOrder = displayOrder; descriptor.OrderBy = sorting; descriptor.MinHitCount = _searchSettings.FilterMinHitCount; descriptor.MaxChoicesCount = _searchSettings.FilterMaxChoicesCount; addValues(descriptor); query.WithFacet(descriptor); }
private int GetPageSize(CatalogSearchQuery query, RouteData routeData, string origin) { string entityViewMode = null; // Determine entity id if possible IPagingOptions entity = null; int? entityId; if (origin.IsCaseInsensitiveEqual("Catalog/Category")) { entityId = (int?)routeData.Values["categoryId"]; if (entityId.HasValue) { entity = _services.Resolve <ICategoryService>().GetCategoryById(entityId.Value) as IPagingOptions; entityViewMode = ((Category)entity)?.DefaultViewMode; } } else if (origin.IsCaseInsensitiveEqual("Catalog/Manufacturer")) { entityId = (int?)routeData.Values["manufacturerId"]; if (entityId.HasValue) { entity = _services.Resolve <IManufacturerService>().GetManufacturerById(entityId.Value) as IPagingOptions; } } var entitySize = entity?.PageSize; var sessionKey = origin; if (entitySize.HasValue) { sessionKey += "/" + entitySize.Value; } DetectViewMode(query, sessionKey, entityViewMode); var allowChange = entity?.AllowCustomersToSelectPageSize ?? _catalogSettings.AllowCustomersToSelectPageSize; if (!allowChange) { return(entitySize ?? _catalogSettings.DefaultProductListPageSize); } sessionKey = "PageSize:" + sessionKey; // Get from form or query var selectedSize = GetValueFor <int?>("s"); if (selectedSize.HasValue) { // Save the selection in session. We'll fetch this session value // on subsequent requests for this route. if (_httpContext.Session != null) { _httpContext.Session[sessionKey] = selectedSize.Value; } return(selectedSize.Value); } // Return user size from session if (_httpContext.Session != null) { var sessionSize = _httpContext.Session[sessionKey].Convert <int?>(); if (sessionSize.HasValue) { return(sessionSize.Value); } } // Return default size for entity (IPagingOptions) if (entitySize.HasValue) { return(entitySize.Value); } // Return default page size return(_catalogSettings.DefaultProductListPageSize); }
public virtual async Task <(int AffectedCategories, int AffectedProducts)> InheritStoresIntoChildrenAsync( int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) { var categoryEntityName = nameof(Category); var productEntityName = nameof(Product); var affectedCategories = 0; var affectedProducts = 0; var allStoreIds = await _db.Stores .AsQueryable() .Select(x => x.Id) .ToListAsync(); var referenceCategory = await _db.Categories.FindByIdAsync(categoryId); var referenceStoreMappingIds = await _storeMappingService.GetAuthorizedStoreIdsAsync(referenceCategory); using (var scope = new DbContextScope(_db, autoDetectChanges: false)) { await ProcessCategory(scope, referenceCategory); } _cache.RemoveByPattern(StoreMappingService.STOREMAPPING_SEGMENT_PATTERN); return(affectedCategories, affectedProducts); async Task ProcessCategory(DbContextScope scope, Category c) { // Process sub-categories. var subCategories = await _db.Categories .AsQueryable() .Where(x => x.ParentCategoryId == c.Id) .OrderBy(x => x.DisplayOrder) .ToListAsync(); foreach (var subCategory in subCategories) { if (subCategory.LimitedToStores != referenceCategory.LimitedToStores) { subCategory.LimitedToStores = referenceCategory.LimitedToStores; } var storeMappings = await _db.StoreMappings .ApplyEntityFilter(subCategory) .ToListAsync(); var storeMappingsDic = storeMappings.ToDictionarySafe(x => x.StoreId); foreach (var storeId in allStoreIds) { if (referenceStoreMappingIds.Contains(storeId)) { if (!storeMappingsDic.ContainsKey(storeId)) { _db.StoreMappings.Add(new StoreMapping { StoreId = storeId, EntityId = subCategory.Id, EntityName = categoryEntityName }); } } else if (storeMappingsDic.TryGetValue(storeId, out var storeMappingToDelete)) { _db.StoreMappings.Remove(storeMappingToDelete); } } } await scope.CommitAsync(); affectedCategories += subCategories.Count; // Process products. var categoryIds = new HashSet <int>(subCategories.Select(x => x.Id)) { c.Id }; var searchQuery = new CatalogSearchQuery().WithCategoryIds(null, categoryIds.ToArray()); var productsQuery = _catalogSearchService.PrepareQuery(searchQuery); var productsPager = new FastPager <Product>(productsQuery, 500); while ((await productsPager.ReadNextPageAsync <Product>()).Out(out var products)) { foreach (var product in products) { if (product.LimitedToStores != referenceCategory.LimitedToStores) { product.LimitedToStores = referenceCategory.LimitedToStores; } var storeMappings = await _db.StoreMappings .ApplyEntityFilter(product) .ToListAsync(); var storeMappingsDic = storeMappings.ToDictionarySafe(x => x.StoreId); foreach (var storeId in allStoreIds) { if (referenceStoreMappingIds.Contains(storeId)) { if (!storeMappingsDic.ContainsKey(storeId)) { _db.StoreMappings.Add(new StoreMapping { StoreId = storeId, EntityId = product.Id, EntityName = productEntityName }); } } else if (storeMappingsDic.TryGetValue(storeId, out var storeMappingToDelete)) { _db.StoreMappings.Remove(storeMappingToDelete); } } } await scope.CommitAsync(); affectedProducts += products.Count; } await scope.CommitAsync(); try { scope.DbContext.DetachEntities(x => x is Product || x is Category || x is StoreMapping, false); } catch { } foreach (var subCategory in subCategories) { await ProcessCategory(scope, subCategory); } } }
public virtual void InheritStoresIntoChildren( int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) { var allStores = _storeService.GetAllStores(); var referenceCategory = GetCategoryById(categoryId); var referenceStoreMappings = _storeMappingService.GetStoresIdsWithAccess(referenceCategory); using (var scope = new DbContextScope(ctx: _storeMappingRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false)) { ProcessCategory(scope, referenceCategory); } _cache.RemoveByPattern(StoreMappingService.STOREMAPPING_SEGMENT_PATTERN); void ProcessCategory(DbContextScope scope, Category c) { // Process sub-categories. var subCategories = GetAllCategoriesByParentCategoryId(c.Id, true); foreach (var subCategory in subCategories) { if (subCategory.LimitedToStores != referenceCategory.LimitedToStores) { subCategory.LimitedToStores = referenceCategory.LimitedToStores; _categoryRepository.Update(subCategory); } var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(subCategory).ToDictionary(x => x.StoreId); foreach (var store in allStores) { if (referenceStoreMappings.Contains(store.Id)) { if (!existingStoreMappingsRecords.ContainsKey(store.Id)) { _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = subCategory.Id, EntityName = "Category" }); } } else if (existingStoreMappingsRecords.TryGetValue(store.Id, out var storeMappingToDelete)) { _storeMappingRepository.Delete(storeMappingToDelete); } } } scope.Commit(); // Process products. var categoryIds = new HashSet <int>(subCategories.Select(x => x.Id)); categoryIds.Add(c.Id); var searchQuery = new CatalogSearchQuery().WithCategoryIds(null, categoryIds.ToArray()); var productsQuery = _catalogSearchService.PrepareQuery(searchQuery); var productsPager = new FastPager <Product>(productsQuery, 500); while (productsPager.ReadNextPage(out var products)) { foreach (var product in products) { if (product.LimitedToStores != referenceCategory.LimitedToStores) { product.LimitedToStores = referenceCategory.LimitedToStores; _productRepository.Update(product); } var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(product).ToDictionary(x => x.StoreId); foreach (var store in allStores) { if (referenceStoreMappings.Contains(store.Id)) { if (!existingStoreMappingsRecords.ContainsKey(store.Id)) { _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = product.Id, EntityName = "Product" }); } } else if (existingStoreMappingsRecords.TryGetValue(store.Id, out var storeMappingToDelete)) { _storeMappingRepository.Delete(storeMappingToDelete); } } } scope.Commit(); } scope.Commit(); try { scope.DbContext.DetachEntities(x => x is Product || x is Category || x is StoreMapping, false); } catch { } foreach (var subCategory in subCategories) { ProcessCategory(scope, subCategory); } } }
public ActionResult Picker(EntityPickerModel model, FormCollection form) { try { var languageId = model.LanguageId == 0 ? Services.WorkContext.WorkingLanguage.Id : model.LanguageId; var disableIf = model.DisableIf.SplitSafe(",").Select(x => x.ToLower().Trim()).ToList(); var disableIds = model.DisableIds.SplitSafe(",").Select(x => x.ToInt()).ToList(); var selected = model.Selected.SplitSafe(","); var returnSku = model.ReturnField.IsCaseInsensitiveEqual("sku"); using (var scope = new DbContextScope(Services.DbContext, autoDetectChanges: false, proxyCreation: true, validateOnSave: false, forceNoTracking: true)) { if (model.EntityType.IsCaseInsensitiveEqual("product")) { model.SearchTerm = model.SearchTerm.TrimSafe(); var hasPermission = Services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog); var disableIfNotSimpleProduct = disableIf.Contains("notsimpleproduct"); var disableIfGroupedProduct = disableIf.Contains("groupedproduct"); var labelTextGrouped = T("Admin.Catalog.Products.ProductType.GroupedProduct.Label").Text; var labelTextBundled = T("Admin.Catalog.Products.ProductType.BundledProduct.Label").Text; var sku = T("Products.Sku").Text; var fields = new List <string> { "name" }; if (_searchSettings.SearchFields.Contains("sku")) { fields.Add("sku"); } if (_searchSettings.SearchFields.Contains("shortdescription")) { fields.Add("shortdescription"); } var searchQuery = new CatalogSearchQuery(fields.ToArray(), model.SearchTerm) .HasStoreId(model.StoreId); if (!hasPermission) { searchQuery = searchQuery.VisibleOnly(Services.WorkContext.CurrentCustomer); } if (model.ProductTypeId > 0) { searchQuery = searchQuery.IsProductType((ProductType)model.ProductTypeId); } if (model.ManufacturerId != 0) { searchQuery = searchQuery.WithManufacturerIds(null, model.ManufacturerId); } if (model.CategoryId != 0) { var node = _categoryService.GetCategoryTree(model.CategoryId, true); if (node != null) { searchQuery = searchQuery.WithCategoryIds(null, node.Flatten(true).Select(x => x.Id).ToArray()); } } var skip = model.PageIndex * model.PageSize; var query = _catalogSearchService.PrepareQuery(searchQuery); var products = query .Select(x => new { x.Id, x.Sku, x.Name, x.Published, x.ProductTypeId, x.MainPictureId }) .OrderBy(x => x.Name) .Skip(() => skip) .Take(() => model.PageSize) .ToList(); var allPictureIds = products.Select(x => x.MainPictureId.GetValueOrDefault()); var allPictureInfos = _pictureService.GetPictureInfos(allPictureIds); model.SearchResult = products .Select(x => { var item = new EntityPickerModel.SearchResultModel { Id = x.Id, Title = x.Name, Summary = x.Sku, SummaryTitle = "{0}: {1}".FormatInvariant(sku, x.Sku.NaIfEmpty()), Published = hasPermission ? x.Published : (bool?)null, ReturnValue = returnSku ? x.Sku : x.Id.ToString() }; item.Selected = selected.Contains(item.ReturnValue); if (disableIfNotSimpleProduct) { item.Disable = x.ProductTypeId != (int)ProductType.SimpleProduct; } else if (disableIfGroupedProduct) { item.Disable = x.ProductTypeId == (int)ProductType.GroupedProduct; } if (!item.Disable && disableIds.Contains(x.Id)) { item.Disable = true; } if (x.ProductTypeId == (int)ProductType.GroupedProduct) { item.LabelText = labelTextGrouped; item.LabelClassName = "badge-success"; } else if (x.ProductTypeId == (int)ProductType.BundledProduct) { item.LabelText = labelTextBundled; item.LabelClassName = "badge-info"; } var pictureInfo = allPictureInfos.Get(x.MainPictureId.GetValueOrDefault()); var fallbackType = _catalogSettings.HideProductDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity; item.ImageUrl = _pictureService.GetUrl( allPictureInfos.Get(x.MainPictureId.GetValueOrDefault()), _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage, fallbackType); return(item); }) .ToList(); } else if (model.EntityType.IsCaseInsensitiveEqual("category")) { var categories = _categoryService.GetAllCategories(model.SearchTerm, showHidden: true); var allPictureIds = categories.Select(x => x.PictureId.GetValueOrDefault()); var allPictureInfos = _pictureService.GetPictureInfos(allPictureIds); model.SearchResult = categories .Select(x => { var path = ((ICategoryNode)x).GetCategoryPath(_categoryService, languageId, "({0})"); var item = new EntityPickerModel.SearchResultModel { Id = x.Id, Title = x.Name, Summary = path, SummaryTitle = path, Published = x.Published, ReturnValue = x.Id.ToString(), Selected = selected.Contains(x.Id.ToString()), Disable = disableIds.Contains(x.Id) }; if (x.Alias.HasValue()) { item.LabelText = x.Alias; item.LabelClassName = "badge-secondary"; } var pictureInfo = allPictureInfos.Get(x.PictureId.GetValueOrDefault()); var fallbackType = _catalogSettings.HideProductDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity; item.ImageUrl = _pictureService.GetUrl( allPictureInfos.Get(x.PictureId.GetValueOrDefault()), _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage, fallbackType); return(item); }) .ToList(); } else if (model.EntityType.IsCaseInsensitiveEqual("manufacturer")) { var manufacturers = _manufacturerService.GetAllManufacturers(model.SearchTerm, model.PageIndex, model.PageSize, showHidden: true); var allPictureIds = manufacturers.Select(x => x.PictureId.GetValueOrDefault()); var allPictureInfos = _pictureService.GetPictureInfos(allPictureIds); model.SearchResult = manufacturers .Select(x => { var item = new EntityPickerModel.SearchResultModel { Id = x.Id, Title = x.Name, Published = x.Published, ReturnValue = x.Id.ToString(), Selected = selected.Contains(x.Id.ToString()), Disable = disableIds.Contains(x.Id) }; var pictureInfo = allPictureInfos.Get(x.PictureId.GetValueOrDefault()); var fallbackType = _catalogSettings.HideProductDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity; item.ImageUrl = _pictureService.GetUrl( allPictureInfos.Get(x.PictureId.GetValueOrDefault()), _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage, fallbackType); return(item); }) .ToList(); } else if (model.EntityType.IsCaseInsensitiveEqual("customer")) { var registeredRoleId = _customerService.GetCustomerRoleBySystemName("Registered").Id; var searchTermName = string.Empty; var searchTermEmail = string.Empty; var searchTermCustomerNumber = string.Empty; if (model.CustomerSearchType.IsCaseInsensitiveEqual("Name")) { searchTermName = model.SearchTerm; } else if (model.CustomerSearchType.IsCaseInsensitiveEqual("Email")) { searchTermEmail = model.SearchTerm; } else if (model.CustomerSearchType.IsCaseInsensitiveEqual("CustomerNumber")) { searchTermCustomerNumber = model.SearchTerm; } var q = new CustomerSearchQuery { SearchTerm = searchTermName, Email = searchTermEmail, CustomerNumber = searchTermCustomerNumber, CustomerRoleIds = new int[] { registeredRoleId }, PageIndex = model.PageIndex, PageSize = model.PageSize }; var customers = _customerService.SearchCustomers(q); model.SearchResult = customers .Select(x => { var fullName = x.GetFullName(); var item = new EntityPickerModel.SearchResultModel { Id = x.Id, ReturnValue = x.Id.ToString(), Title = x.Username.NullEmpty() ?? x.Email, Summary = fullName, SummaryTitle = fullName, Published = true, Selected = selected.Contains(x.Id.ToString()), Disable = disableIds.Contains(x.Id) }; return(item); }) .ToList(); } } } catch (Exception ex) { NotifyError(ex.ToAllMessages()); } return(PartialView("Picker.List", model)); }
private decimal MapSummaryItemPrice(Product product, ref Product contextProduct, ProductSummaryModel.SummaryItem item, MapProductSummaryItemContext ctx) { // Returns the final price var finalPrice = decimal.Zero; var model = ctx.Model; var priceModel = new ProductSummaryModel.PriceModel(); if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing && !ctx.BatchContext.ProductBundleItems.FullyLoaded) { ctx.BatchContext.ProductBundleItems.LoadAll(); } if (product.ProductType == ProductType.GroupedProduct) { #region Grouped product if (ctx.GroupedProducts == null) { // One-time batched retrieval of all associated products var searchQuery = new CatalogSearchQuery() .PublishedOnly(true) .HasStoreId(ctx.Store.Id) .HasParentGroupedProduct(ctx.BatchContext.ProductIds.ToArray()); // Get all associated products for this batch grouped by ParentGroupedProductId var allAssociatedProducts = _catalogSearchService.Search(searchQuery).Hits .OrderBy(x => x.ParentGroupedProductId) .ThenBy(x => x.DisplayOrder); ctx.GroupedProducts = allAssociatedProducts.ToMultimap(x => x.ParentGroupedProductId, x => x); if (ctx.GroupedProducts.Any()) { ctx.BatchContext.AppliedDiscounts.Collect(allAssociatedProducts.Select(x => x.Id)); } } var associatedProducts = ctx.GroupedProducts[product.Id]; priceModel.DisableBuyButton = true; priceModel.DisableWishlistButton = true; priceModel.AvailableForPreOrder = false; if (associatedProducts.Count > 0) { contextProduct = associatedProducts.OrderBy(x => x.DisplayOrder).First(); _services.DisplayControl.Announce(contextProduct); if (ctx.AllowPrices && _catalogSettings.PriceDisplayType != PriceDisplayType.Hide) { decimal?displayPrice = null; bool displayFromMessage = false; if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { displayPrice = _priceCalculationService.GetPreselectedPrice(contextProduct, ctx.Customer, ctx.BatchContext); } else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) { displayPrice = _priceCalculationService.GetFinalPrice(contextProduct, null, ctx.Customer, decimal.Zero, false, 1, null, ctx.BatchContext); } else { displayFromMessage = true; displayPrice = _priceCalculationService.GetLowestPrice(product, ctx.Customer, ctx.BatchContext, associatedProducts, out contextProduct); } if (contextProduct != null && !contextProduct.CustomerEntersPrice) { if (contextProduct.CallForPrice) { priceModel.RegularPriceValue = null; priceModel.PriceValue = 0; priceModel.RegularPrice = null; priceModel.Price = ctx.Resources["Products.CallForPrice"]; } else if (displayPrice.HasValue) { // Calculate prices decimal taxRate = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(contextProduct, contextProduct.OldPrice, out taxRate); decimal finalPriceBase = _taxService.GetProductPrice(contextProduct, displayPrice.Value, out taxRate); finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, ctx.Currency); priceModel.RegularPriceValue = null; priceModel.PriceValue = finalPrice; priceModel.RegularPrice = null; if (displayFromMessage) { priceModel.Price = String.Format(ctx.Resources["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); } else { priceModel.Price = _priceFormatter.FormatPrice(finalPrice); } if (oldPriceBase > 0) { priceModel.RegularPriceValue = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, ctx.Currency); } priceModel.HasDiscount = (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero); } else { // Actually it's not possible (we presume that displayPrice always has a value). We never should get here Debug.WriteLine(string.Format("Cannot calculate displayPrice for product #{0}", product.Id)); } } } } #endregion } else { #region Simple product //add to cart button priceModel.DisableBuyButton = product.DisableBuyButton || !ctx.AllowShoppingCart || !ctx.AllowPrices; //add to wishlist button priceModel.DisableWishlistButton = product.DisableWishlistButton || !ctx.AllowWishlist || !ctx.AllowPrices; //pre-order priceModel.AvailableForPreOrder = product.AvailableForPreOrder; //prices if (ctx.AllowPrices && _catalogSettings.PriceDisplayType != PriceDisplayType.Hide && !product.CustomerEntersPrice) { if (product.CallForPrice) { // call for price priceModel.RegularPriceValue = null; priceModel.PriceValue = 0; priceModel.RegularPrice = null; priceModel.Price = ctx.Resources["Products.CallForPrice"]; } else { //calculate prices bool displayFromMessage = false; decimal displayPrice = decimal.Zero; if (_catalogSettings.PriceDisplayType == PriceDisplayType.PreSelectedPrice) { displayPrice = _priceCalculationService.GetPreselectedPrice(product, ctx.Customer, ctx.BatchContext); } else if (_catalogSettings.PriceDisplayType == PriceDisplayType.PriceWithoutDiscountsAndAttributes) { displayPrice = _priceCalculationService.GetFinalPrice(product, null, ctx.Customer, decimal.Zero, false, 1, null, ctx.BatchContext); } else { displayPrice = _priceCalculationService.GetLowestPrice(product, ctx.Customer, ctx.BatchContext, out displayFromMessage); } decimal taxRate = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate); decimal finalPriceBase = _taxService.GetProductPrice(product, displayPrice, out taxRate); decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, ctx.Currency); finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, ctx.Currency); priceModel.HasDiscount = (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero); if (displayFromMessage) { priceModel.RegularPriceValue = null; priceModel.RegularPrice = null; priceModel.Price = String.Format(ctx.Resources["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice)); } else { priceModel.PriceValue = finalPrice; if (priceModel.HasDiscount) { priceModel.RegularPriceValue = oldPrice; priceModel.RegularPrice = _priceFormatter.FormatPrice(oldPrice); priceModel.Price = _priceFormatter.FormatPrice(finalPrice); } else { priceModel.RegularPriceValue = null; priceModel.RegularPrice = null; priceModel.Price = _priceFormatter.FormatPrice(finalPrice); } } } } #endregion } var regularPriceValue = priceModel.RegularPriceValue.GetValueOrDefault(); if (priceModel.HasDiscount && regularPriceValue > 0 && regularPriceValue > priceModel.PriceValue) { priceModel.SavingPercent = (float)((priceModel.RegularPriceValue - priceModel.PriceValue) / priceModel.RegularPriceValue) * 100; priceModel.SavingAmount = _priceFormatter.FormatPrice(regularPriceValue - priceModel.PriceValue, true, false); if (model.ShowDiscountBadge) { item.Badges.Add(new ProductSummaryModel.Badge { Label = T("Products.SavingBadgeLabel", priceModel.SavingPercent.ToString("N0")), Style = BadgeStyle.Danger }); } } priceModel.CallForPrice = product.CallForPrice; item.Price = priceModel; return(finalPrice); }
public ActionResult Manufacturer(int manufacturerId, CatalogSearchQuery query) { var manufacturer = _manufacturerService.GetManufacturerById(manufacturerId); if (manufacturer == null || manufacturer.Deleted) { return(HttpNotFound()); } // Check whether the current user has a "Manage catalog" permission. // It allows him to preview a manufacturer before publishing. if (!manufacturer.Published && !Services.Permissions.Authorize(Permissions.Catalog.Manufacturer.Read)) { return(HttpNotFound()); } // ACL (access control list). if (!_aclService.Authorize(manufacturer)) { return(HttpNotFound()); } // Store mapping. if (!_storeMappingService.Authorize(manufacturer)) { return(HttpNotFound()); } var store = Services.StoreContext.CurrentStore; var customer = Services.WorkContext.CurrentCustomer; // 'Continue shopping' URL. if (!customer.IsSystemAccount) { _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.LastContinueShoppingPage, Services.WebHelper.GetThisPageUrl(false), store.Id); } var model = manufacturer.ToModel(); if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages) { model.Description.ChangeValue(string.Empty); model.BottomDescription.ChangeValue(string.Empty); } model.PictureModel = _helper.PrepareManufacturerPictureModel(manufacturer, model.Name); // Featured products. var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages); if (!hideFeaturedProducts) { CatalogSearchResult featuredProductsResult = null; var customerRolesIds = customer.CustomerRoleMappings .Select(x => x.CustomerRole) .Where(x => x.Active) .Select(x => x.Id) .ToList(); var cacheKey = ModelCacheEventConsumer.MANUFACTURER_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(manufacturerId, string.Join(",", customerRolesIds), store.Id); var hasFeaturedProductsCache = Services.Cache.Get <bool?>(cacheKey); var featuredProductsQuery = new CatalogSearchQuery() .VisibleOnly(customer) .WithVisibility(ProductVisibility.Full) .WithManufacturerIds(true, manufacturerId) .HasStoreId(store.Id) .WithLanguage(Services.WorkContext.WorkingLanguage) .WithCurrency(Services.WorkContext.WorkingCurrency); if (!hasFeaturedProductsCache.HasValue) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0; Services.Cache.Put(cacheKey, hasFeaturedProductsCache, TimeSpan.FromHours(6)); } if (hasFeaturedProductsCache.Value && featuredProductsResult == null) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); } if (featuredProductsResult != null) { // TODO: (mc) determine settings properly var featuredProductsmappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid); model.FeaturedProducts = _helper.MapProductSummaryModel(featuredProductsResult.Hits, featuredProductsmappingSettings); } } // Products query.WithManufacturerIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : (bool?)false, manufacturerId); var searchResult = _catalogSearchService.Search(query); model.SearchResult = searchResult; var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(query.GetViewMode()); model.Products = _helper.MapProductSummaryModel(searchResult.Hits, mappingSettings); // Prepare paging/sorting/mode stuff _helper.MapListActions(model.Products, manufacturer, _catalogSettings.DefaultPageSizeOptions); // Template var templateCacheKey = string.Format(ModelCacheEventConsumer.MANUFACTURER_TEMPLATE_MODEL_KEY, manufacturer.ManufacturerTemplateId); var templateViewPath = Services.Cache.Get(templateCacheKey, () => { var template = _manufacturerTemplateService.GetManufacturerTemplateById(manufacturer.ManufacturerTemplateId); if (template == null) { template = _manufacturerTemplateService.GetAllManufacturerTemplates().FirstOrDefault(); } return(template.ViewPath); }); //activity log Services.CustomerActivity.InsertActivity("PublicStore.ViewManufacturer", T("ActivityLog.PublicStore.ViewManufacturer"), manufacturer.Name); Services.DisplayControl.Announce(manufacturer); return(View(templateViewPath, model)); }
public ActionResult Category(int categoryId, CatalogSearchQuery query) { var category = _categoryService.GetCategoryById(categoryId); if (category == null || category.Deleted) { return(HttpNotFound()); } // Check whether the current user has a "Manage catalog" permission // It allows him to preview a category before publishing if (!category.Published && !_services.Permissions.Authorize(StandardPermissionProvider.ManageCatalog)) { return(HttpNotFound()); } // ACL (access control list) if (!_aclService.Authorize(category)) { return(HttpNotFound()); } // Store mapping if (!_storeMappingService.Authorize(category)) { return(HttpNotFound()); } // 'Continue shopping' URL if (!_services.WorkContext.CurrentCustomer.IsSystemAccount) { _genericAttributeService.SaveAttribute(_services.WorkContext.CurrentCustomer, SystemCustomerAttributeNames.LastContinueShoppingPage, _services.WebHelper.GetThisPageUrl(false), _services.StoreContext.CurrentStore.Id); } var model = category.ToModel(); _services.DisplayControl.Announce(category); // Category breadcrumb if (_catalogSettings.CategoryBreadcrumbEnabled) { _helper.GetCategoryBreadCrumb(category.Id, 0).Select(x => x.Value).Each(x => _breadcrumb.Track(x)); } model.SubCategoryDisplayType = _catalogSettings.SubCategoryDisplayType; var customerRolesIds = _services.WorkContext.CurrentCustomer.CustomerRoles.Where(x => x.Active).Select(x => x.Id).ToList(); // subcategories model.SubCategories = _categoryService .GetAllCategoriesByParentCategoryId(categoryId) .Select(x => { var subCatName = x.GetLocalized(y => y.Name); var subCatModel = new CategoryModel.SubCategoryModel { Id = x.Id, Name = subCatName, SeName = x.GetSeName(), }; _services.DisplayControl.Announce(x); // prepare picture model int pictureSize = _mediaSettings.CategoryThumbPictureSize; var categoryPictureCacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_PICTURE_MODEL_KEY, x.Id, pictureSize, true, _services.WorkContext.WorkingLanguage.Id, _services.StoreContext.CurrentStore.Id); subCatModel.PictureModel = _services.Cache.Get(categoryPictureCacheKey, () => { var picture = _pictureService.GetPictureById(x.PictureId.GetValueOrDefault()); var pictureModel = new PictureModel { PictureId = x.PictureId.GetValueOrDefault(), Size = pictureSize, FullSizeImageUrl = _pictureService.GetPictureUrl(picture), FullSizeImageWidth = picture?.Width, FullSizeImageHeight = picture?.Height, ImageUrl = _pictureService.GetPictureUrl(picture, pictureSize, !_catalogSettings.HideCategoryDefaultPictures), Title = string.Format(T("Media.Category.ImageLinkTitleFormat"), subCatName), AlternateText = string.Format(T("Media.Category.ImageAlternateTextFormat"), subCatName) }; return(pictureModel); }, TimeSpan.FromHours(6)); return(subCatModel); }) .ToList(); // Featured Products if (!_catalogSettings.IgnoreFeaturedProducts) { CatalogSearchResult featuredProductsResult = null; string cacheKey = ModelCacheEventConsumer.CATEGORY_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(categoryId, string.Join(",", customerRolesIds), _services.StoreContext.CurrentStore.Id); var hasFeaturedProductsCache = _services.Cache.Get <bool?>(cacheKey); var featuredProductsQuery = new CatalogSearchQuery() .VisibleOnly(_services.WorkContext.CurrentCustomer) .VisibleIndividuallyOnly(true) .WithCategoryIds(true, categoryId) .HasStoreId(_services.StoreContext.CurrentStore.Id) .WithLanguage(_services.WorkContext.WorkingLanguage) .WithCurrency(_services.WorkContext.WorkingCurrency); if (!hasFeaturedProductsCache.HasValue) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0; _services.Cache.Put(cacheKey, hasFeaturedProductsCache, TimeSpan.FromHours(6)); } if (hasFeaturedProductsCache.Value && featuredProductsResult == null) { featuredProductsResult = _catalogSearchService.Search(featuredProductsQuery); } if (featuredProductsResult != null) { var featuredProductsmappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid); model.FeaturedProducts = _helper.MapProductSummaryModel(featuredProductsResult.Hits, featuredProductsmappingSettings); } } // Products int[] catIds = new int[] { categoryId }; if (_catalogSettings.ShowProductsFromSubcategories) { // Include subcategories catIds = catIds.Concat(_helper.GetChildCategoryIds(categoryId)).ToArray(); } query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? (bool?)null : false, catIds); var searchResult = _catalogSearchService.Search(query); model.SearchResult = searchResult; var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(query.GetViewMode()); model.Products = _helper.MapProductSummaryModel(searchResult.Hits, mappingSettings); // Prepare paging/sorting/mode stuff _helper.MapListActions(model.Products, category, _catalogSettings.DefaultPageSizeOptions); // template var templateCacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_TEMPLATE_MODEL_KEY, category.CategoryTemplateId); var templateViewPath = _services.Cache.Get(templateCacheKey, () => { var template = _categoryTemplateService.GetCategoryTemplateById(category.CategoryTemplateId); if (template == null) { template = _categoryTemplateService.GetAllCategoryTemplates().FirstOrDefault(); } return(template.ViewPath); }); // Activity log _services.CustomerActivity.InsertActivity("PublicStore.ViewCategory", T("ActivityLog.PublicStore.ViewCategory"), category.Name); return(View(templateViewPath, model)); }
protected virtual void OnConverted(CatalogSearchQuery query, RouteData routeData, string origin) { }
public ActionResult RecentlyAddedProductsRss(CatalogSearchQuery query) { // TODO: (mc) find a more prominent place for the "NewProducts" link (may be in main menu?) var protocol = Services.WebHelper.IsCurrentConnectionSecured() ? "https" : "http"; var selfLink = Url.RouteUrl("RecentlyAddedProductsRSS", null, protocol); var recentProductsLink = Url.RouteUrl("RecentlyAddedProducts", null, protocol); var title = "{0} - {1}".FormatInvariant(Services.StoreContext.CurrentStore.Name, T("RSS.RecentlyAddedProducts")); var feed = new SmartSyndicationFeed(new Uri(recentProductsLink), title, T("RSS.InformationAboutProducts")); feed.AddNamespaces(true); feed.Init(selfLink, Services.WorkContext.WorkingLanguage); if (!_catalogSettings.RecentlyAddedProductsEnabled || _catalogSettings.RecentlyAddedProductsNumber <= 0) { return(new RssActionResult { Feed = feed }); } var items = new List <SyndicationItem>(); query.Sorting.Clear(); query = query .BuildFacetMap(false) .SortBy(ProductSortingEnum.CreatedOn) .Slice(0, _catalogSettings.RecentlyAddedProductsNumber); var result = _catalogSearchService.Search(query); var storeUrl = Services.StoreService.GetHost(Services.StoreContext.CurrentStore); // Prefecthing var allPictureInfos = Services.PictureService.GetPictureInfos(result.Hits); //_mediaSettings.ProductDetailsPictureSize, false, storeUrl foreach (var product in result.Hits) { string productUrl = Url.RouteUrl("Product", new { SeName = product.GetSeName() }, protocol); if (productUrl.HasValue()) { var item = feed.CreateItem( product.GetLocalized(x => x.Name), product.GetLocalized(x => x.ShortDescription), productUrl, product.CreatedOnUtc, product.FullDescription); try { // we add only the first picture var picture = Services.PictureService.GetPictureById(product.MainPictureId.GetValueOrDefault()); if (picture != null) { feed.AddEnclosure(item, picture, Services.PictureService.GetUrl(picture, _mediaSettings.ProductDetailsPictureSize, FallbackPictureType.NoFallback, storeUrl)); } } catch { } items.Add(item); } } feed.Items = items; Services.DisplayControl.AnnounceRange(result.Hits); return(new RssActionResult { Feed = feed }); }
protected virtual bool GetValueFor <T>(CatalogSearchQuery query, string key, FacetGroupKind kind, out T value) { return(GetValueFor(_catalogSearchQueryAliasMapper.GetCommonFacetAliasByGroupKind(kind, query.LanguageId ?? 0) ?? key, out value)); }
public async Task <IActionResult> Manufacturer(int manufacturerId, CatalogSearchQuery query) { var manufacturer = await _db.Manufacturers.FindByIdAsync(manufacturerId, false); if (manufacturer == null || manufacturer.Deleted) { return(NotFound()); } // Check whether the current user has a "Manage catalog" permission. // It allows him to preview a manufacturer before publishing. if (!manufacturer.Published && !await Services.Permissions.AuthorizeAsync(Permissions.Catalog.Manufacturer.Read)) { return(NotFound()); } // ACL (access control list). if (!await _aclService.AuthorizeAsync(manufacturer)) { return(NotFound()); } // Store mapping. if (!await _storeMappingService.AuthorizeAsync(manufacturer)) { return(NotFound()); } var customer = Services.WorkContext.CurrentCustomer; var storeId = Services.StoreContext.CurrentStore.Id; // 'Continue shopping' URL. if (!customer.IsSystemAccount) { customer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false); } var model = await _helper.PrepareBrandModelAsync(manufacturer); if (_seoSettings.CanonicalUrlsEnabled) { model.CanonicalUrl = _urlHelper.Value.RouteUrl("Manufacturer", new { model.SeName }, Request.Scheme); } if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages) { model.Description.ChangeValue(string.Empty); model.BottomDescription.ChangeValue(string.Empty); } model.Image = await _helper.PrepareBrandImageModelAsync(manufacturer, model.Name); // Featured products. var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages); if (!hideFeaturedProducts) { CatalogSearchResult featuredProductsResult = null; var cacheKey = ModelCacheInvalidator.MANUFACTURER_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(manufacturerId, string.Join(",", customer.GetRoleIds()), storeId); var hasFeaturedProductsCache = await Services.Cache.GetAsync <bool?>(cacheKey); var featuredProductsQuery = new CatalogSearchQuery() .VisibleOnly(customer) .WithVisibility(ProductVisibility.Full) .WithManufacturerIds(true, manufacturerId) .HasStoreId(storeId) .WithLanguage(Services.WorkContext.WorkingLanguage) .WithCurrency(Services.WorkContext.WorkingCurrency); if (!hasFeaturedProductsCache.HasValue) { featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery); hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0; await Services.Cache.PutAsync(cacheKey, hasFeaturedProductsCache); } if (hasFeaturedProductsCache.Value && featuredProductsResult == null) { featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery); } if (featuredProductsResult != null) { // TODO: (mc) determine settings properly var featuredProductsmappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid); model.FeaturedProducts = await _helper.MapProductSummaryModelAsync(featuredProductsResult, featuredProductsmappingSettings); } } // Products query.WithManufacturerIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : false, manufacturerId); var searchResult = await _catalogSearchService.SearchAsync(query); model.SearchResult = searchResult; var viewMode = _helper.GetSearchQueryViewMode(query); var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(viewMode); model.Products = await _helper.MapProductSummaryModelAsync(searchResult, mappingSettings); // Prepare paging/sorting/mode stuff _helper.MapListActions(model.Products, manufacturer, _catalogSettings.DefaultPageSizeOptions); // Template. var templateCacheKey = string.Format(ModelCacheInvalidator.MANUFACTURER_TEMPLATE_MODEL_KEY, manufacturer.ManufacturerTemplateId); var templateViewPath = await Services.Cache.GetAsync(templateCacheKey, async() => { var template = await _db.ManufacturerTemplates.FindByIdAsync(manufacturer.ManufacturerTemplateId, false) ?? await _db.ManufacturerTemplates.FirstOrDefaultAsync(); return(template.ViewPath); }); // Activity log. Services.ActivityLogger.LogActivity("PublicStore.ViewManufacturer", T("ActivityLog.PublicStore.ViewManufacturer"), manufacturer.Name); Services.DisplayControl.Announce(manufacturer); return(View(templateViewPath, model)); }
public CatalogSearchQuery CreateFromQuery() { var ctx = _httpContext; if (ctx.Request == null) { return(null); } var routeData = ctx.Request.RequestContext.RouteData; var area = routeData.GetAreaName(); var controller = routeData.GetRequiredString("controller"); var action = routeData.GetRequiredString("action"); var origin = "{0}{1}/{2}".FormatInvariant(area == null ? "" : area + "/", controller, action); var fields = new List <string> { "name" }; var term = GetValueFor <string>("q"); var isInstantSearch = origin.IsCaseInsensitiveEqual("Search/InstantSearch"); if (isInstantSearch) { fields.Add("shortdescription"); fields.Add("tagname"); foreach (var fieldName in _instantSearchFields) { if (_searchSettings.SearchFields.Contains(fieldName)) { fields.Add(fieldName); } } } else { fields.AddRange(_searchSettings.SearchFields); } var query = new CatalogSearchQuery(fields.ToArray(), term, _searchSettings.SearchMode) .OriginatesFrom(origin) .WithLanguage(_services.WorkContext.WorkingLanguage) .WithCurrency(_services.WorkContext.WorkingCurrency) .VisibleIndividuallyOnly(true) .BuildFacetMap(!isInstantSearch); // Visibility. query.VisibleOnly(!QuerySettings.IgnoreAcl ? _services.WorkContext.CurrentCustomer : null); // Store. if (!QuerySettings.IgnoreMultiStore) { query.HasStoreId(_services.StoreContext.CurrentStore.Id); } // Availability. ConvertAvailability(query, routeData, origin); // Instant-Search never uses these filter parameters. if (!isInstantSearch) { ConvertPagingSorting(query, routeData, origin); ConvertPrice(query, routeData, origin); ConvertCategory(query, routeData, origin); ConvertManufacturer(query, routeData, origin); ConvertRating(query, routeData, origin); ConvertNewArrivals(query, routeData, origin); ConvertDeliveryTime(query, routeData, origin); } OnConverted(query, routeData, origin); Current = query; return(query); }
public async Task <IActionResult> Category(int categoryId, CatalogSearchQuery query) { var category = await _db.Categories .Include(x => x.MediaFile) .FindByIdAsync(categoryId, false); if (category == null || category.Deleted) { return(NotFound()); } // Check whether the current user has a "Manage catalog" permission. // It allows him to preview a category before publishing. if (!category.Published && !await Services.Permissions.AuthorizeAsync(Permissions.Catalog.Category.Read)) { return(NotFound()); } // ACL (access control list). if (!await _aclService.AuthorizeAsync(category)) { return(NotFound()); } // Store mapping. if (!await _storeMappingService.AuthorizeAsync(category)) { return(NotFound()); } var customer = Services.WorkContext.CurrentCustomer; var storeId = Services.StoreContext.CurrentStore.Id; // 'Continue shopping' URL. if (!customer.IsSystemAccount) { customer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false); } var model = await _helper.PrepareCategoryModelAsync(category); if (_seoSettings.CanonicalUrlsEnabled) { model.CanonicalUrl = _urlHelper.Value.RouteUrl("Category", new { model.SeName }, Request.Scheme); } if (query.IsSubPage && !_catalogSettings.ShowDescriptionInSubPages) { model.Description.ChangeValue(string.Empty); model.BottomDescription.ChangeValue(string.Empty); } model.Image = await _helper.PrepareCategoryImageModelAsync(category, model.Name); // Category breadcrumb. if (_catalogSettings.CategoryBreadcrumbEnabled) { await _helper.GetBreadcrumbAsync(_breadcrumb, ControllerContext); } // Products. var catIds = new int[] { categoryId }; if (_catalogSettings.ShowProductsFromSubcategories) { // Include subcategories. catIds = catIds.Concat(await _helper.GetChildCategoryIdsAsync(categoryId)).ToArray(); } query.WithCategoryIds(_catalogSettings.IncludeFeaturedProductsInNormalLists ? null : false, catIds); var searchResult = await _catalogSearchService.SearchAsync(query); model.SearchResult = searchResult; var viewMode = _helper.GetSearchQueryViewMode(query); var mappingSettings = _helper.GetBestFitProductSummaryMappingSettings(viewMode); model.Products = await _helper.MapProductSummaryModelAsync(searchResult, mappingSettings); model.SubCategoryDisplayType = _catalogSettings.SubCategoryDisplayType; var pictureSize = _mediaSettings.CategoryThumbPictureSize; var fallbackType = _catalogSettings.HideCategoryDefaultPictures ? FallbackPictureType.NoFallback : FallbackPictureType.Entity; var hideSubCategories = _catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.Hide || (_catalogSettings.SubCategoryDisplayType == SubCategoryDisplayType.AboveProductList && query.IsSubPage && !_catalogSettings.ShowSubCategoriesInSubPages); var hideFeaturedProducts = _catalogSettings.IgnoreFeaturedProducts || (query.IsSubPage && !_catalogSettings.IncludeFeaturedProductsInSubPages); // Subcategories. if (!hideSubCategories) { var subCategories = await _categoryService.GetCategoriesByParentCategoryIdAsync(categoryId); model.SubCategories = await _helper.MapCategorySummaryModelAsync(subCategories, pictureSize); } // Featured Products. if (!hideFeaturedProducts) { CatalogSearchResult featuredProductsResult = null; string cacheKey = ModelCacheInvalidator.CATEGORY_HAS_FEATURED_PRODUCTS_KEY.FormatInvariant(categoryId, string.Join(",", customer.GetRoleIds()), storeId); var hasFeaturedProductsCache = await Services.Cache.GetAsync <bool?>(cacheKey); var featuredProductsQuery = new CatalogSearchQuery() .VisibleOnly(customer) .WithVisibility(ProductVisibility.Full) .WithCategoryIds(true, categoryId) .HasStoreId(storeId) .WithLanguage(Services.WorkContext.WorkingLanguage) .WithCurrency(Services.WorkContext.WorkingCurrency); if (!hasFeaturedProductsCache.HasValue) { featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery); hasFeaturedProductsCache = featuredProductsResult.TotalHitsCount > 0; await Services.Cache.PutAsync(cacheKey, hasFeaturedProductsCache); } if (hasFeaturedProductsCache.Value && featuredProductsResult == null) { featuredProductsResult = await _catalogSearchService.SearchAsync(featuredProductsQuery); } if (featuredProductsResult != null) { var featuredProductsMappingSettings = _helper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Grid); model.FeaturedProducts = await _helper.MapProductSummaryModelAsync(featuredProductsResult, featuredProductsMappingSettings); } } // Prepare paging/sorting/mode stuff. _helper.MapListActions(model.Products, category, _catalogSettings.DefaultPageSizeOptions); // Template. var templateCacheKey = string.Format(ModelCacheInvalidator.CATEGORY_TEMPLATE_MODEL_KEY, category.CategoryTemplateId); var templateViewPath = await Services.Cache.GetAsync(templateCacheKey, async() => { var template = await _db.CategoryTemplates.FindByIdAsync(category.CategoryTemplateId, false) ?? await _db.CategoryTemplates.FirstOrDefaultAsync(); return(template.ViewPath); }); // Activity log. Services.ActivityLogger.LogActivity("PublicStore.ViewCategory", T("ActivityLog.PublicStore.ViewCategory"), category.Name); Services.DisplayControl.Announce(category); return(View(templateViewPath, model)); }
public async Task <IActionResult> Search(CatalogSearchQuery query) { var model = new SearchResultModel(query); CatalogSearchResult result = null; if (query.Term == null || query.Term.Length < _searchSettings.InstantSearchTermMinLength) { model.SearchResult = new CatalogSearchResult(query); model.Error = T("Search.SearchTermMinimumLengthIsNCharacters", _searchSettings.InstantSearchTermMinLength); return(View(model)); } Services.WorkContext.CurrentCustomer.GenericAttributes.LastContinueShoppingPage = Services.WebHelper.GetCurrentPageUrl(false); try { if (_searchSettings.SearchProductByIdentificationNumber) { var(product, attributeCombination) = await _productService.Value.GetProductByIdentificationNumberAsync(query.Term); if (product != null) { if (attributeCombination != null) { return(Redirect(await _productUrlHelper.GetProductUrlAsync(product.Id, await product.GetActiveSlugAsync(), attributeCombination.AttributeSelection))); } return(RedirectToRoute("Product", new { SeName = await product.GetActiveSlugAsync() })); } } result = await _catalogSearchService.SearchAsync(query); } catch (Exception ex) { model.Error = ex.ToString(); result = new CatalogSearchResult(query); } if (result.TotalHitsCount == 0 && result.SpellCheckerSuggestions.Any()) { // No matches, but spell checker made a suggestion. // We implicitly search again with the first suggested term. var oldSuggestions = result.SpellCheckerSuggestions; var oldTerm = query.Term; query.Term = oldSuggestions[0]; result = await _catalogSearchService.SearchAsync(query); if (result.TotalHitsCount > 0) { model.AttemptedTerm = oldTerm; // Restore the original suggestions. result.SpellCheckerSuggestions = oldSuggestions.Where(x => x != query.Term).ToArray(); } else { query.Term = oldTerm; } } model.SearchResult = result; model.Term = query.Term; model.TotalProductsCount = result.TotalHitsCount; var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(_catalogHelper.GetSearchQueryViewMode(query)); var summaryModel = await _catalogHelper.MapProductSummaryModelAsync(await result.GetHitsAsync(), mappingSettings); // Prepare paging/sorting/mode stuff. _catalogHelper.MapListActions(summaryModel, null, _catalogSettings.DefaultPageSizeOptions); // Add product hits. model.TopProducts = summaryModel; return(View(model)); }
public virtual void InheritStoresIntoChildren( int categoryId, bool touchProductsWithMultipleCategories = false, bool touchExistingAcls = false, bool categoriesOnly = false) { var category = GetCategoryById(categoryId); var subcategories = GetAllCategoriesByParentCategoryId(categoryId, true); var allStores = _storeService.GetAllStores(); var categoryStoreMappings = _storeMappingService.GetStoresIdsWithAccess(category); var categoryIds = new HashSet <int>(subcategories.Select(x => x.Id)); categoryIds.Add(categoryId); var searchQuery = new CatalogSearchQuery() .WithCategoryIds(null, categoryIds.ToArray()); var query = _catalogSearchService.PrepareQuery(searchQuery); var products = query.OrderBy(p => p.Id).ToList(); using (var scope = new DbContextScope(ctx: _storeMappingRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) { _storeMappingRepository.AutoCommitEnabled = false; foreach (var subcategory in subcategories) { if (subcategory.LimitedToStores != category.LimitedToStores) { subcategory.LimitedToStores = category.LimitedToStores; _categoryRepository.Update(subcategory); } var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(subcategory).ToDictionary(x => x.StoreId); foreach (var store in allStores) { if (categoryStoreMappings.Contains(store.Id)) { if (!existingStoreMappingsRecords.ContainsKey(store.Id)) { _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = subcategory.Id, EntityName = "Category" }); } } else { if (existingStoreMappingsRecords.TryGetValue(store.Id, out var storeMappingToDelete)) { _storeMappingRepository.Delete(storeMappingToDelete); } } } } _storeMappingRepository.Context.SaveChanges(); foreach (var product in products) { if (product.LimitedToStores != category.LimitedToStores) { product.LimitedToStores = category.LimitedToStores; _productRepository.Update(product); } var existingStoreMappingsRecords = _storeMappingService.GetStoreMappings(product).ToDictionary(x => x.StoreId); foreach (var store in allStores) { if (categoryStoreMappings.Contains(store.Id)) { if (!existingStoreMappingsRecords.ContainsKey(store.Id)) { _storeMappingRepository.Insert(new StoreMapping { StoreId = store.Id, EntityId = product.Id, EntityName = "Product" }); } } else { if (existingStoreMappingsRecords.TryGetValue(store.Id, out var storeMappingToDelete)) { _storeMappingRepository.Delete(storeMappingToDelete); } } } } _storeMappingRepository.Context.SaveChanges(); } }
public ActionResult Search(CatalogSearchQuery query) { var model = new SearchResultModel(query); CatalogSearchResult result = null; if (query.Term == null || query.Term.Length < _searchSettings.InstantSearchTermMinLength) { model.SearchResult = new CatalogSearchResult(query); model.Error = T("Search.SearchTermMinimumLengthIsNCharacters", _searchSettings.InstantSearchTermMinLength); return(View(model)); } // 'Continue shopping' URL _genericAttributeService.SaveAttribute(Services.WorkContext.CurrentCustomer, SystemCustomerAttributeNames.LastContinueShoppingPage, Services.WebHelper.GetThisPageUrl(false), Services.StoreContext.CurrentStore.Id); try { result = _catalogSearchService.Search(query); } catch (Exception ex) { model.Error = ex.ToString(); result = new CatalogSearchResult(query); } if (result.TotalHitsCount == 0 && result.SpellCheckerSuggestions.Any()) { // No matches, but spell checker made a suggestion. // We implicitly search again with the first suggested term. var oldSuggestions = result.SpellCheckerSuggestions; var oldTerm = query.Term; query.Term = oldSuggestions[0]; result = _catalogSearchService.Search(query); if (result.TotalHitsCount > 0) { model.AttemptedTerm = oldTerm; // Restore the original suggestions. result.SpellCheckerSuggestions = oldSuggestions.Where(x => x != query.Term).ToArray(); } else { query.Term = oldTerm; } } model.SearchResult = result; model.Term = query.Term; model.TotalProductsCount = result.TotalHitsCount; var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(query.GetViewMode()); var summaryModel = _catalogHelper.MapProductSummaryModel(result.Hits, mappingSettings); // Prepare paging/sorting/mode stuff. _catalogHelper.MapListActions(summaryModel, null, _catalogSettings.DefaultPageSizeOptions); // Add product hits. model.TopProducts = summaryModel; return(View(model)); }