//EndDocSection:DisplayProduct //DocSection:DisplayVariant /// <summary> /// Displays product detail page of a product or a product variant specified by ID of the product's or variant's page. /// </summary> /// <param name="id">Node ID of the product's (variant's) page.</param> /// <param name="productAlias">Node alias of the product's (variant's) page.</param> public ActionResult Detail(int id, string productAlias) { // Gets the product from Kentico SKUTreeNode product = GetProduct(id); // If the product is not found or if it is not allowed for sale, redirects to error 404 if ((product == null) || !product.SKU.SKUEnabled) { return(HttpNotFound()); } // Redirects if the specified page alias does not match if (!string.IsNullOrEmpty(productAlias) && !product.NodeAlias.Equals(productAlias, StringComparison.InvariantCultureIgnoreCase)) { return(RedirectToActionPermanent("Detail", new { id = product.NodeID, productAlias = product.NodeAlias })); } // Gets all product variants of the product List <Variant> variants = variantRepository.GetByProductId(product.NodeSKUID).OrderBy(v => v.VariantPrice).ToList(); // Selects the first product variant Variant selectedVariant = variants.FirstOrDefault(); // Calculates the price of the product or the variant ShoppingCart cart = shoppingService.GetCurrentShoppingCart(); ProductPrice priceDetail = selectedVariant != null?pricingService.CalculatePrice(selectedVariant, cart) : pricingService.CalculatePrice(product.SKU, cart); // Initializes the view model of the product or product variant ProductViewModel viewModel = new ProductViewModel(product, priceDetail, variants, selectedVariant?.VariantSKUID ?? 0); // Displays the product detail page return(View(viewModel)); }
/// <summary> /// Creates a new product model with variants. /// </summary> /// <param name="productPage">Product's page.</param> /// <param name="priceDetail">Price of the selected variant.</param> /// <param name="variants">Collection of selectable variants.</param> /// <param name="selectedVariantID">ID of the selected variant.</param> public ProductViewModel(SKUTreeNode productPage, ProductPrice priceDetail, List <Variant> variants, int selectedVariantID) : this(productPage, priceDetail) { // Fills the selectable variants ProductVariants = variants; // Continues if the product has any variants if (variants.Any()) { // Pre select variant var selectedVariant = variants.FirstOrDefault(v => v.VariantSKUID == selectedVariantID); if (selectedVariant != null) { IsInStock = !selectedVariant.InventoryTracked || selectedVariant.AvailableItems > 0; SelectedVariantID = selectedVariantID; } // Creates a list of product variants VariantSelectList = new SelectList(variants.Select(v => new SelectListItem { Text = string.Join(", ", v.ProductAttributes.Select(a => a.SKUName)), Value = v.VariantSKUID.ToString() }), "Value", "Text"); } }
/// <summary> /// Creates a new product model. /// </summary> /// <param name="productPage">Product's page.</param> /// <param name="priceDetail">Price of the product.</param> public ProductViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail) { // Fills the page information Name = productPage.DocumentName; Description = productPage.DocumentSKUDescription; ShortDescription = productPage.DocumentSKUShortDescription; // Fills the SKU information SKUInfo sku = productPage.SKU; SKUID = sku.SKUID; ImagePath = string.IsNullOrEmpty(sku.SKUImagePath) ? null : new FileUrl(sku.SKUImagePath, true) .WithSizeConstraint(SizeConstraint.MaxWidthOrHeight(400)) .RelativePath; IsInStock = sku.SKUTrackInventory == TrackInventoryTypeEnum.Disabled || sku.SKUAvailableItems > 0; PriceDetail = new PriceDetailViewModel() { Price = priceDetail.Price, ListPrice = priceDetail.ListPrice, CurrencyFormatString = priceDetail.Currency.CurrencyFormatString }; }
private SKUTreeNode AppendProduct(TreeNode parent, CampaignProductDto product, SKUInfo sku, int siteId) { if (parent == null || product == null) { return(null); } TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser); SKUTreeNode existingProduct = (SKUTreeNode)parent.Children.FirstOrDefault(c => c.NodeSKUID == sku.SKUID); SKUTreeNode newProduct = existingProduct ?? (SKUTreeNode)TreeNode.New(CampaignsProduct.CLASS_NAME, tree); Program program = GetProgram(product.Campaign, product.ProgramName); ProductCategory productCategory = GetProductCategory(product.ProductCategory); newProduct.DocumentName = product.ProductName; newProduct.DocumentSKUName = product.ProductName; newProduct.NodeSKUID = sku.SKUID; newProduct.NodeName = product.ProductName; newProduct.DocumentCulture = _culture; newProduct.SetValue("ProductName", product.ProductName); newProduct.SetValue("BrandID", GetBrandID(product.Brand)); SetProductItemSpecs(ref newProduct, product); if (program != null) { newProduct.SetValue("ProgramID", program.ProgramID); } if (!string.IsNullOrWhiteSpace(product.AllowedStates)) { newProduct.SetValue("State", GetStatesGroupID(product.AllowedStates)); } if (!string.IsNullOrWhiteSpace(product.EstimatedPrice)) { newProduct.SetValue("EstimatedPrice", product.EstimatedPrice); } if (productCategory != null) { newProduct.SetValue("CategoryID", productCategory.ProductCategoryID); } if (!string.IsNullOrWhiteSpace(product.BundleQuantity)) { newProduct.SetValue("QtyPerPack", product.BundleQuantity); } if (existingProduct == null) { newProduct.Insert(parent); } if (!string.IsNullOrEmpty(product.ImageURL) && !string.IsNullOrEmpty(product.ThumbnailURL)) { GetAndSaveProductImages(newProduct, product.ImageURL, product.ThumbnailURL); } else { RemoveProductImages(newProduct); } newProduct.Update(); return(newProduct); }
/// <summary> /// Creates a new product model with variants. /// </summary> /// <param name="productPage">Product's page.</param> /// <param name="priceDetail">Price of the selected variant.</param> /// <param name="variants">Collection of selectable variants.</param> /// <param name="selectedVariantID">ID of the selected variant.</param> public ProductViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail, List <ProductVariant> variants, int selectedVariantID) : this(productPage, priceDetail) { // Fills the selectable variants HasProductVariants = variants.Any(); // Continues if the product has any variants if (HasProductVariants) { // Selects a default variant var selectedVariant = variants.FirstOrDefault(v => v.Variant.SKUID == selectedVariantID); if (selectedVariant != null) { IsInStock = (selectedVariant.Variant.SKUTrackInventory == TrackInventoryTypeEnum.Disabled) || (selectedVariant.Variant.SKUAvailableItems > 0); SelectedVariantID = selectedVariantID; } // Creates a list of product variants VariantSelectList = new SelectList(variants.Select(v => new SelectListItem { Text = string.Join(", ", v.ProductAttributes.Select(a => a.SKUName)), Value = v.Variant.SKUID.ToString() }), "Value", "Text"); } }
private Variant GetCheapestVariant(SKUTreeNode product) { var variants = mVariantRepository.GetByProductId(product.NodeSKUID).OrderBy(v => v.VariantPrice).ToList(); var cheapestVariant = variants.FirstOrDefault(); return(cheapestVariant); }
//EndDocSection:Constructor //DocSection:DisplayProduct /// <summary> /// Displays a product detail page of a product specified by the GUID of the product's page. /// </summary> /// <param name="guid">Node GUID of the product's page.</param> /// <param name="productAlias">Node alias of the product's page.</param> public ActionResult BasicDetail(Guid guid, string productAlias) { // Gets the product from the connected Kentico database SKUTreeNode product = GetProduct(guid); // If the product is not found or if it is not allowed for sale, redirects to error 404 if ((product == null) || (product.SKU == null) || !product.SKU.SKUEnabled) { return(HttpNotFound()); } // Redirects if the specified page alias does not match if (!string.IsNullOrEmpty(productAlias) && !product.NodeAlias.Equals(productAlias, StringComparison.InvariantCultureIgnoreCase)) { return(RedirectToActionPermanent("Detail", new { guid = product.NodeGUID, productAlias = product.NodeAlias })); } // Initializes the view model of the product with a calculated price ShoppingCartInfo cart = shoppingService.GetCurrentShoppingCart(); ProductCatalogPrices price = calculatorFactory .GetCalculator(cart.ShoppingCartSiteID) .GetPrices(product.SKU, Enumerable.Empty <SKUInfo>(), cart); // Fills the product model with retrieved data ProductViewModel viewModel = new ProductViewModel(product, price); // Displays the product details page return(View(viewModel)); }
public SearchResultProductItemModel(SearchResultItem resultItem, SKUTreeNode page, ProductCatalogPrices priceDetail, IPageUrlRetriever pageUrlRetriever) : base(resultItem, page, pageUrlRetriever) { Description = page.DocumentSKUDescription; ShortDescription = HTMLHelper.StripTags(page.DocumentSKUShortDescription, false); PriceDetail = priceDetail; }
/// <summary> /// Process added product in Recombee. /// </summary> /// <param name="productPage">Product page.</param> public void AddProduct(SKUTreeNode productPage) { if (productPage is null) { throw new ArgumentNullException(nameof(productPage)); } UpdateProduct(productPage); }
/// <summary> /// Updates given product from recombee database. /// </summary> /// <param name="user">Product to update.</param> public void UpdateProduct(SKUTreeNode productPage) { if (productPage is null) { throw new ArgumentNullException(nameof(productPage)); } recombeeClientService.UpdateProduct(productPage); }
private static void AttachThumbnail(SKUTreeNode product, string fromUrl) { var newAttachment = DownloadAttachmentThumbnail(product, fromUrl); if (newAttachment != null) { product.SetValue("ProductThumbnail", newAttachment.AttachmentGUID); } }
private static AttachmentInfo DownloadAttachmentThumbnail(SKUTreeNode product, string fromUrl) { if (product.SKU == null) { throw new ArgumentNullException(nameof(product.SKU)); } using (var client = new HttpClient()) { using (var request = new HttpRequestMessage(HttpMethod.Get, fromUrl)) { using (var response = client.SendAsync(request).Result) { if (response.StatusCode == System.Net.HttpStatusCode.OK) { var mimetype = response.Content?.Headers?.ContentType?.MediaType ?? string.Empty; if (!mimetype.StartsWith("image/")) { throw new Exception("Thumbnail is not of image MIME type"); } var stream = response.Content.ReadAsStreamAsync().Result; var extension = Path.GetExtension(fromUrl); if (string.IsNullOrEmpty(extension) && mimetype.StartsWith("image/")) { extension = mimetype.Split('/')[1]; } // attach file as page attachment and set it's GUID as ProductThumbnail (of type guid) property of Product var newAttachment = new AttachmentInfo() { InputStream = stream, AttachmentSiteID = product.NodeSiteID, AttachmentDocumentID = product.DocumentID, AttachmentExtension = extension, AttachmentName = $"Thumbnail{product.SKU.GetStringValue("SKUProductCustomerReferenceNumber", product.SKU.SKUNumber)}.{extension}", AttachmentLastModified = DateTime.Now, AttachmentMimeType = mimetype, AttachmentSize = (int)stream.Length }; AttachmentInfoProvider.SetAttachmentInfo(newAttachment); return(newAttachment); } else { throw new Exception("Failed to download thumbnail image"); } } } } }
/// <summary> /// Gets ViewModel for <paramref name="product"/>. /// </summary> /// <param name="product">Product.</param> /// <returns>Hydrated ViewModel.</returns> public static ProductCardViewModel GetViewModel(SKUTreeNode product) { return(product == null ? new ProductCardViewModel() : new ProductCardViewModel { Heading = product.DocumentSKUName, Image = product.SKU.SKUImagePath, Text = product.DocumentSKUShortDescription }); }
/// <summary> /// Gets ViewModel for <paramref name="product"/>. /// </summary> /// <param name="product">Product.</param> /// <returns>Hydrated ViewModel.</returns> public static ProductCardViewModel GetViewModel(SKUTreeNode product) { return(product == null ? new ProductCardViewModel() : new ProductCardViewModel { Heading = product.DocumentSKUName, ImagePath = string.IsNullOrEmpty(product.SKU.SKUImagePath) ? null : new FileUrl(product.SKU.SKUImagePath, true).WithSizeConstraint(SizeConstraint.MaxWidthOrHeight(300)).RelativePath, Text = product.DocumentSKUShortDescription }); }
public SearchResultProductItemModel(SearchResultItem resultItem, SKUTreeNode skuTreeNode, ProductCatalogPrices priceDetail) : base(resultItem, skuTreeNode) { Description = skuTreeNode.DocumentSKUDescription; ShortDescription = HTMLHelper.StripTags(skuTreeNode.DocumentSKUShortDescription, false); PriceDetail = priceDetail; var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); Url = urlHelper.Action("Detail", "Product", new { guid = skuTreeNode.NodeGUID, productAlias = skuTreeNode.NodeAlias }); }
/// <summary> /// Deletes given product from recombee database. /// </summary> /// <param name="user">Product to delete.</param> public void Delete(SKUTreeNode productPage) { var deleteRequest = new DeleteItem(productPage.DocumentGUID.ToString()); try { client.Send(deleteRequest); } catch (Exception ex) { Service.Resolve <IEventLogService>().LogException("RecombeeAdminModule", "ON_PRODUCT_DELETE", ex); } }
private string GetProductStatus(SKUTreeNode accessory) { if (accessory is FilterPack filterPack) { return(filterPack.Product.PublicStatus?.PublicStatusDisplayName); } if (accessory is Tableware tableware) { return(tableware.Product.PublicStatus?.PublicStatusDisplayName); } return(string.Empty); }
private static void RemoveTumbnail(SKUTreeNode product) { var oldAttachmentGuid = product.GetGuidValue("ProductThumbnail", Guid.Empty); var siteName = (product.Site ?? SiteInfoProvider.GetSiteInfo(product.NodeSiteID)).SiteName; if (oldAttachmentGuid != Guid.Empty) { var oldAttachment = AttachmentInfoProvider.GetAttachmentInfo(oldAttachmentGuid, siteName); if (oldAttachment != null) { AttachmentInfoProvider.DeleteAttachmentInfo(oldAttachment); } } }
/// <summary> /// Creates an instance of the <see cref="RecommendedProductViewModel"/> view model- /// </summary> /// <param name="productPage">Product page.</param> /// <param name="priceDetail">Price.</param> public RecommendedProductViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail) { // Set page information Name = productPage.DocumentName; ProductPageGUID = productPage.NodeGUID; ProductPageAlias = productPage.NodeAlias; // Set SKU information ImagePath = productPage.SKU.SKUImagePath; Available = !productPage.SKU.SKUSellOnlyAvailable || productPage.SKU.SKUAvailableItems > 0; // Set additional info PriceDetail = priceDetail; }
private string GetProductStatus(SKUTreeNode grinder) { if (grinder is ManualGrinder manualGrinder) { return(manualGrinder.Product.PublicStatus?.PublicStatusDisplayName); } if (grinder is ElectricGrinder electricGrinder) { return(electricGrinder.Product.PublicStatus?.PublicStatusDisplayName); } return(string.Empty); }
public ProductListItemViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail, string publicStatusName, IPageUrlRetriever pageUrlRetriever) { // Set page information Name = productPage.DocumentName; Url = pageUrlRetriever.Retrieve(productPage).RelativePath; // Set SKU information ImagePath = string.IsNullOrEmpty(productPage.SKU.SKUImagePath) ? null : new FileUrl(productPage.SKU.SKUImagePath, true).WithSizeConstraint(SizeConstraint.Size(452, 452)).RelativePath; Available = !productPage.SKU.SKUSellOnlyAvailable || productPage.SKU.SKUAvailableItems > 0; PublicStatusName = publicStatusName; // Set additional info PriceDetail = priceDetail; }
private void SetProductItemSpecs(ref SKUTreeNode newProduct, CampaignProductDto product) { if (!string.IsNullOrWhiteSpace(product.ItemSpecs)) { ProductItemSpecsItem itemSpecs = CustomTableItemProvider.GetItems <ProductItemSpecsItem>().WhereEquals("ItemSpec", product.ItemSpecs); if (itemSpecs != null) { newProduct.SetValue("ItemSpecs", itemSpecs.ItemID); } } if (!string.IsNullOrWhiteSpace(product.CustomItemSpecs)) { newProduct.SetValue("CustomItemSpecs", product.CustomItemSpecs); } }
public ProductListItemViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail, string publicStatusName) { // Set page information Name = productPage.DocumentName; ProductPageGUID = productPage.NodeGUID; ProductPageAlias = productPage.NodeAlias; // Set SKU information ImagePath = productPage.SKU.SKUImagePath; Available = !productPage.SKU.SKUSellOnlyAvailable || productPage.SKU.SKUAvailableItems > 0; PublicStatusName = publicStatusName; // Set additional info PriceDetail = priceDetail; }
/// <summary> /// Updates given product <paramref name="productPage"/> in Recombee database. /// </summary> /// <param name="productPage">Product to update.</param> public void UpdateProduct(SKUTreeNode productPage) { var updateRequest = new SetItemValues( productPage.DocumentGUID.ToString(), ProductMapper.Map(productPage), true); try { client.Send(updateRequest); } catch (Exception ex) { Service.Resolve <IEventLogService>().LogException("RecombeeAdminModule", "ON_PRODUCT_CREATED", ex); } }
// ready for potential use in Product upload private static void GetAndSaveProductImages(SKUTreeNode product, string imageUrl, string thumbnailUrl) { var library = new MediaLibrary { SiteId = product.NodeSiteID, LibraryName = "ProductImages", LibraryFolder = "Products", LibraryDescription = "Media library for storing product images" }; var libraryImageUrl = library.DownloadImageToMedialibrary(imageUrl, $"Image{product.SKU.SKUNumber}", $"Product image for SKU {product.SKU.SKUNumber}"); product.RemoveImage(); product.SetImage(libraryImageUrl); RemoveTumbnail(product); AttachThumbnail(product, thumbnailUrl); }
public ProductViewModel(SKUTreeNode productPage, ProductPrice price, ITypedProductViewModel typedProductViewModel, Variant defaultVariant, IEnumerable <ProductOptionCategoryViewModel> categories) : this(productPage, price, typedProductViewModel) { if (defaultVariant == null) { throw new ArgumentNullException(nameof(defaultVariant)); } IsInStock = !defaultVariant.InventoryTracked || defaultVariant.AvailableItems > 0; SelectedVariantID = defaultVariant.VariantSKUID; // Variant categories which will be rendered ProductOptionCategories = categories; }
public void SetUp() { Fake <SKUInfo, SKUInfoProvider>().WithData(sku = new SKUInfo { SKUID = SKU_ID }, variant = new SKUInfo { SKUID = VARIANT_ID }); Fake <VariantOptionInfo, VariantOptionInfoProvider>().WithData(); page = Substitute.For <SKUTreeNode>(); retiever = Substitute.For <IPageDataContextRetriever>(); variantRepository = Substitute.For <IVariantRepository>(); controller = new ProductController(retiever, null, variantRepository, null, null, SKUInfo.Provider); }
public ProductViewModel(SKUTreeNode productPage, ProductCatalogPrices price, ITypedProductViewModel typedProductViewModel, ProductVariant defaultVariant, IEnumerable <ProductOptionCategoryViewModel> categories) : this(productPage, price, typedProductViewModel) { if (defaultVariant == null) { throw new ArgumentNullException(nameof(defaultVariant)); } var variant = defaultVariant.Variant; IsInStock = ((variant.SKUTrackInventory == TrackInventoryTypeEnum.Disabled) || (variant.SKUAvailableItems > 0)); SelectedVariantID = variant.SKUID; // Variant categories which will be rendered ProductOptionCategories = categories; }
/// <summary> /// Maps <paramref name="productPage"/> to Recombee structure. /// </summary> /// <param name="productPage">Product page.</param> public static Dictionary <string, object> Map(SKUTreeNode productPage) { if (productPage is null) { throw new ArgumentNullException(nameof(productPage)); } return(new Dictionary <string, object> { { "Name", productPage.DocumentSKUName }, { "Description", productPage.DocumentSKUShortDescription }, { "Content", productPage.DocumentSKUDescription }, { "Culture", productPage.DocumentCulture }, { "ClassName", productPage.ClassName }, { "Price", productPage.SKU.SKUPrice }, { "Type", "Product" }, }); }
/// <summary> /// Creates a new product model. /// </summary> /// <param name="productPage">Product's page.</param> /// <param name="priceDetail">Price of the product.</param> public ProductViewModel(SKUTreeNode productPage, ProductPrice priceDetail) { // Fills the page information Name = productPage.DocumentName; Description = productPage.DocumentSKUDescription; ShortDescription = productPage.DocumentSKUShortDescription; ProductPageID = productPage.NodeID; ProductPageAlias = productPage.NodeAlias; // Fills the SKU information SKUInfo sku = productPage.SKU; SKUID = sku.SKUID; ImagePath = sku.SKUImagePath; IsInStock = sku.SKUTrackInventory == TrackInventoryTypeEnum.Disabled || sku.SKUAvailableItems > 0; PriceDetail = priceDetail; }