public async Task <IActionResult> UpdateProductDetails(int productId, string itemType, int bundleItemId, ProductVariantQuery query) { // TODO: (core) UpdateProductDetails action needs some decent refactoring. var form = HttpContext.Request.Form; int quantity = 1; int galleryStartIndex = -1; string galleryHtml = null; string dynamicThumbUrl = null; var isAssociated = itemType.EqualsNoCase("associateditem"); var product = await _db.Products.FindByIdAsync(productId); var batchContext = _productService.CreateProductBatchContext(new[] { product }, includeHidden: false); var bItem = await _db.ProductBundleItem .Include(x => x.BundleProduct) .FindByIdAsync(bundleItemId, false); IList <ProductBundleItemData> bundleItemDatas = null; ProductBundleItemData bundleItem = bItem == null ? null : new ProductBundleItemData(bItem); // Quantity required for tier prices. string quantityKey = form.Keys.FirstOrDefault(k => k.EndsWith("EnteredQuantity")); if (quantityKey.HasValue()) { _ = int.TryParse(form[quantityKey], out quantity); } if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { var bundleItemQuery = await _db.ProductBundleItem .AsNoTracking() .ApplyBundledProductsFilter(new[] { product.Id }) .Include(x => x.Product) .Include(x => x.BundleProduct) .ToListAsync(); if (bundleItemQuery.Count > 0) { bundleItemDatas = new List <ProductBundleItemData>(); bundleItemQuery.Each(x => bundleItemDatas.Add(new ProductBundleItemData(x))); } if (query.Variants.Count > 0) { batchContext.Collect(bundleItemDatas.Select(x => x.Item.Product.Id).ToArray()); // May add elements to query object if they are preselected by bundle item filter. foreach (var itemData in bundleItemDatas) { await _helper.MapProductDetailsPageModelAsync(new ProductDetailsModelContext { Product = itemData.Item.Product, BatchContext = batchContext, VariantQuery = query, ProductBundleItem = itemData }); } } } var modelContext = new ProductDetailsModelContext { Product = product, BatchContext = batchContext, VariantQuery = query, IsAssociatedProduct = isAssociated, ProductBundleItem = bundleItem, BundleItemDatas = bundleItemDatas, Customer = batchContext.Customer, Store = batchContext.Store, Currency = Services.WorkContext.WorkingCurrency }; // Get merged model data. var model = new ProductDetailsModel(); await _helper.PrepareProductDetailModelAsync(model, modelContext, quantity); if (bundleItem != null) { // Update bundle item thumbnail. if (!bundleItem.Item.HideThumbnail) { var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? Array.Empty <int>(); var hasFile = assignedMediaIds.Any() && await _db.MediaFiles.AnyAsync(x => x.Id == assignedMediaIds[0]); if (assignedMediaIds.Any() && hasFile) { var file = await _db.ProductMediaFiles .AsNoTracking() .ApplyProductFilter(new[] { bundleItem.Item.ProductId }, 1) .Select(x => x.MediaFile) .FirstOrDefaultAsync(); dynamicThumbUrl = _mediaService.GetUrl(file, _mediaSettings.BundledProductPictureSize, null, false); } } } else if (isAssociated) { // Update associated product thumbnail. var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? new int[0]; var hasFile = await _db.MediaFiles.AnyAsync(x => x.Id == assignedMediaIds[0]); if (assignedMediaIds.Any() && hasFile) { var file = await _db.ProductMediaFiles .AsNoTracking() .ApplyProductFilter(new[] { productId }, 1) .Select(x => x.MediaFile) .FirstOrDefaultAsync(); dynamicThumbUrl = _mediaService.GetUrl(file, _mediaSettings.AssociatedProductPictureSize, null, false); } } else if (product.ProductType != ProductType.BundledProduct) { // Update image gallery. var files = await _db.ProductMediaFiles .AsNoTracking() .ApplyProductFilter(new[] { productId }) .Select(x => _mediaService.ConvertMediaFile(x.MediaFile)) .ToListAsync(); if (product.HasPreviewPicture && files.Count > 1) { files.RemoveAt(0); } if (files.Count <= _catalogSettings.DisplayAllImagesNumber) { // All pictures rendered... only index is required. galleryStartIndex = 0; var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? new int[0]; if (assignedMediaIds.Any()) { var file = files.FirstOrDefault(p => p.Id == assignedMediaIds[0]); galleryStartIndex = file == null ? 0 : files.IndexOf(file); } } else { var allCombinationPictureIds = await _productAttributeService.GetAttributeCombinationFileIdsAsync(product.Id); var mediaModel = _helper.PrepareProductDetailsMediaGalleryModel( files, product.GetLocalized(x => x.Name), allCombinationPictureIds, false, bundleItem, model.SelectedCombination); galleryStartIndex = mediaModel.GalleryStartIndex; galleryHtml = (await this.InvokeViewAsync("Product.Media", mediaModel)).ToString(); } model.PriceDisplayStyle = _catalogSettings.PriceDisplayStyle; model.DisplayTextForZeroPrices = _catalogSettings.DisplayTextForZeroPrices; } object partials = null; if (model.IsBundlePart) { partials = new { BundleItemPrice = await this.InvokeViewAsync("Product.Offer.Price", model), BundleItemStock = await this.InvokeViewAsync("Product.StockInfo", model), BundleItemVariants = await this.InvokeViewAsync("Product.Variants", model.ProductVariantAttributes) }; } else { var dataDictAddToCart = new ViewDataDictionary(ViewData) { Model = model }; dataDictAddToCart.TemplateInfo.HtmlFieldPrefix = $"addtocart_{model.Id}"; decimal adjustment = decimal.Zero; decimal taxRate = decimal.Zero; // TODO: (mh) (core) Implement when pricing is available. //var finalPriceWithDiscountBase = _taxService.GetProductPrice(product, product.Price, Services.WorkContext.CurrentCustomer, out taxRate); //if (!_taxSettings.Value.PricesIncludeTax && Services.WorkContext.TaxDisplayType == TaxDisplayType.IncludingTax) //{ // adjustment = (m.ProductPrice.PriceValue - finalPriceWithDiscountBase) / (taxRate / 100 + 1); //} //else if (_taxSettings.Value.PricesIncludeTax && Services.WorkContext.TaxDisplayType == TaxDisplayType.ExcludingTax) //{ // adjustment = (m.ProductPrice.PriceValue - finalPriceWithDiscountBase) * (taxRate / 100 + 1); //} //else //{ // adjustment = m.ProductPrice.PriceValue - finalPriceWithDiscountBase; //} partials = new { Attrs = await this.InvokeViewAsync("Product.Attrs", model), Price = await this.InvokeViewAsync("Product.Offer.Price", model), Stock = await this.InvokeViewAsync("Product.StockInfo", model), Variants = await this.InvokeViewAsync("Product.Variants", model.ProductVariantAttributes), OfferActions = await this.InvokeViewAsync("Product.Offer.Actions", dataDictAddToCart), TierPrices = await this.InvokeViewAsync("Product.TierPrices", model.TierPrices), BundlePrice = product.ProductType == ProductType.BundledProduct ? await this.InvokeViewAsync("Product.Bundle.Price", model) : null }; } object data = new { Partials = partials, DynamicThumblUrl = dynamicThumbUrl, GalleryStartIndex = galleryStartIndex, GalleryHtml = galleryHtml }; return(new JsonResult(new { Data = data })); }
public async Task <IActionResult> UpdateProductDetails(int productId, string itemType, int bundleItemId, ProductVariantQuery query) { // TODO: (core) UpdateProductDetails action needs some decent refactoring. var form = HttpContext.Request.Form; var quantity = 1; var galleryStartIndex = -1; string galleryHtml = null; string dynamicThumbUrl = null; var isAssociated = itemType.EqualsNoCase("associateditem"); var currency = Services.WorkContext.WorkingCurrency; var displayPrices = await Services.Permissions.AuthorizeAsync(Permissions.Catalog.DisplayPrice); var product = await _db.Products.FindByIdAsync(productId); var batchContext = _productService.CreateProductBatchContext(new[] { product }, includeHidden: false); var bundleItem = await _db.ProductBundleItem .Include(x => x.BundleProduct) .FindByIdAsync(bundleItemId, false); // Quantity required for tier prices. string quantityKey = form.Keys.FirstOrDefault(k => k.EndsWith("EnteredQuantity")); if (quantityKey.HasValue()) { _ = int.TryParse(form[quantityKey], out quantity); } var modelContext = new ProductDetailsModelContext { Product = product, BatchContext = batchContext, VariantQuery = query, IsAssociatedProduct = isAssociated, ProductBundleItem = bundleItem, Customer = batchContext.Customer, Store = batchContext.Store, Currency = currency, DisplayPrices = displayPrices }; // Get merged model data. var model = new ProductDetailsModel(); await _helper.PrepareProductDetailModelAsync(model, modelContext, quantity); if (bundleItem != null) { // Update bundle item thumbnail. if (!bundleItem.HideThumbnail) { var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? Array.Empty <int>(); if (assignedMediaIds.Any() && await _db.MediaFiles.AnyAsync(x => x.Id == assignedMediaIds[0])) { var file = await _db.ProductMediaFiles .AsNoTracking() .Include(x => x.MediaFile) .ApplyProductFilter(bundleItem.ProductId) .FirstOrDefaultAsync(); dynamicThumbUrl = _mediaService.GetUrl(file?.MediaFile, _mediaSettings.BundledProductPictureSize, null, false); } } } else if (isAssociated) { // Update associated product thumbnail. var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? Array.Empty <int>(); if (assignedMediaIds.Any() && await _db.MediaFiles.AnyAsync(x => x.Id == assignedMediaIds[0])) { var file = await _db.ProductMediaFiles .AsNoTracking() .Include(x => x.MediaFile) .ApplyProductFilter(productId) .FirstOrDefaultAsync(); dynamicThumbUrl = _mediaService.GetUrl(file?.MediaFile, _mediaSettings.AssociatedProductPictureSize, null, false); } } else if (product.ProductType != ProductType.BundledProduct) { // Update image gallery. var files = await _db.ProductMediaFiles .AsNoTracking() .Include(x => x.MediaFile) .ApplyProductFilter(productId) .ToListAsync(); if (product.HasPreviewPicture && files.Count > 1) { files.RemoveAt(0); } if (files.Count <= _catalogSettings.DisplayAllImagesNumber) { // All pictures rendered... only index is required. galleryStartIndex = 0; var assignedMediaIds = model.SelectedCombination?.GetAssignedMediaIds() ?? Array.Empty <int>(); if (assignedMediaIds.Any()) { var file = files.FirstOrDefault(p => p.Id == assignedMediaIds[0]); galleryStartIndex = file == null ? 0 : files.IndexOf(file); } } else { var allCombinationPictureIds = await _productAttributeService.GetAttributeCombinationFileIdsAsync(product.Id); var mediaFiles = files .Where(x => x.MediaFile != null) .Select(x => _mediaService.ConvertMediaFile(x.MediaFile)) .ToList(); var mediaModel = _helper.PrepareProductDetailsMediaGalleryModel( mediaFiles, product.GetLocalized(x => x.Name), allCombinationPictureIds, false, bundleItem, model.SelectedCombination); galleryStartIndex = mediaModel.GalleryStartIndex; galleryHtml = (await this.InvokeViewAsync("Product.Media", mediaModel)).ToString(); } model.PriceDisplayStyle = _catalogSettings.PriceDisplayStyle; model.DisplayTextForZeroPrices = _catalogSettings.DisplayTextForZeroPrices; } object partials = null; if (model.IsBundlePart) { partials = new { BundleItemPrice = await this.InvokeViewAsync("Product.Offer.Price", model), BundleItemStock = await this.InvokeViewAsync("Product.StockInfo", model), BundleItemVariants = await this.InvokeViewAsync("Product.Variants", model.ProductVariantAttributes) }; } else { var dataDictAddToCart = new ViewDataDictionary(ViewData) { Model = model }; dataDictAddToCart.TemplateInfo.HtmlFieldPrefix = $"addtocart_{model.Id}"; partials = new { Attrs = await this.InvokeViewAsync("Product.Attrs", model), Price = await this.InvokeViewAsync("Product.Offer.Price", model), Stock = await this.InvokeViewAsync("Product.StockInfo", model), Variants = await this.InvokeViewAsync("Product.Variants", model.ProductVariantAttributes), OfferActions = await this.InvokeViewAsync("Product.Offer.Actions", dataDictAddToCart), TierPrices = await this.InvokeViewAsync("Product.TierPrices", model.TierPrices), BundlePrice = product.ProductType == ProductType.BundledProduct ? await this.InvokeViewAsync("Product.Bundle.Price", model) : null }; } object data = new { Partials = partials, DynamicThumblUrl = dynamicThumbUrl, GalleryStartIndex = galleryStartIndex, GalleryHtml = galleryHtml }; return(new JsonResult(data)); }