protected void Page_Init(object sender, EventArgs e) { _ProductId = AlwaysConvert.ToInt(Request.QueryString["ProductId"]); string optionList = EncryptionHelper.DecryptAES(Request.QueryString["Options"]); _OptionList = ProductVariantManager.ValidateOptionList(optionList); _Product = ProductDataSource.Load(_ProductId); string productName = _Product.Name; _VariantManager = new ProductVariantManager(_ProductId); ProductVariant v = _VariantManager.GetVariantFromOptions(_OptionList); if (v != null) { productName = _Product.Name + " (" + v.VariantName + ")"; } else { _OptionList = string.Empty; } Caption.Text = string.Format(Caption.Text, productName); CancelButton.NavigateUrl = "DigitalGoods.aspx?ProductId=" + _ProductId.ToString(); if (!Page.IsPostBack) { SearchResultsGrid.Visible = false; } }
protected void AddButton_Click(object sender, EventArgs e) { if (Page.IsValid) { Option option = new Option(); option.Name = AddOptionName.Text; option.CreatedDate = LocaleHelper.LocalNow; string[] choices = AddOptionChoices.Text.Split(",".ToCharArray()); foreach (string item in choices) { string choiceName = item.Trim(); if (choiceName != String.Empty) { OptionChoice choice = new OptionChoice(); choice.Option = option; choice.Name = StringHelper.Truncate(choiceName, 50); choice.OrderBy = -1; option.Choices.Add(choice); } } option.Save(); ProductOption productOption = new ProductOption(_Product, option, -1); productOption.Save(); // RESET VARIANT GRID FOR THE ASSOCIATED PRODUCT ProductVariantManager.ResetVariantGrid(_Product.Id); option.ProductOptions.Add(productOption); _Options.Add(option); AddOptionName.Text = string.Empty; AddOptionChoices.Text = string.Empty; BindOptionsGrid(); } }
protected void Page_PreRender(object sender, EventArgs e) { // REGISTER WARNING SCRIPTS IF THE PRODUCT HAS CUSTOMIZED VARIANTS string warnScript; int productId = AbleCommerce.Code.PageHelper.GetProductId(); Product product = ProductDataSource.Load(productId); if (product != null) { bool hasDigitalGoods = ProductVariantManager.HasDigitalGoodData(productId); if (hasDigitalGoods || product.KitStatus == KitStatus.Member) { String delMesssage = String.Empty; if (hasDigitalGoods) { delMesssage += "WARNING: If there are digital goods linked to variants with this choice, deleting the choice will unlink these digital goods.\\n\\n"; } if (product.KitStatus == KitStatus.Member) { delMesssage += "WARNING: This product is part of one or more kit products. Deleting this choice will remove any variants with this choice from those kit products.\\n\\n"; } warnScript = "function confirmDel(){return confirm('" + delMesssage + "Are you sure you want to delete this choice?');}"; } else { warnScript = "function confirmDel(){return confirm('Are you sure you want to delete this choice?');}"; } this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "checkVariant", warnScript, true); } }
protected void OptionChoicesGrid_RowDeleting(object sender, GridViewDeleteEventArgs e) { int optionId = (int)OptionChoicesGrid.DataKeys[e.RowIndex].Value; //FIND THE OPTION IList <OptionChoice> options = _Option.Choices; int index = -1; int i = 0; while ((i < options.Count) && (index < 0)) { if (options[i].Id == optionId) { index = i; } i++; } if (index >= 0) { options.DeleteAt(index); //REBUILD VARIANT GRID FOR THIS PRODUCT int productId = AbleCommerce.Code.PageHelper.GetProductId(); if (productId > 0) { ProductVariantManager.ScrubVariantGrid(productId, optionId); } BindChoicesGrid(); } }
/// <summary> /// Deletes this ProductOption object from the database /// </summary> /// <returns><b>true</b> if delete successful, <b>false</b> otherwise.</returns> public virtual bool Delete() { bool result = this.BaseDelete(); OptionDataSource.DeleteOrphanedOptions(); //REBUILD VARIANT GRID FOR THIS PRODUCT ProductVariantManager.ResetVariantGrid(this.ProductId); return(result); }
/// <summary> /// Saves this ProductOption object to the database /// </summary> /// <returns><b>SaveResult</b> enumeration that represents the result of the save operation.</returns> public virtual SaveResult Save() { SaveResult baseResult = this.BaseSave(); if (baseResult == SaveResult.RecordInserted) { //REBUILD VARIANT GRID FOR THIS PRODUCT ProductVariantManager.ResetVariantGrid(this.ProductId); } return(baseResult); }
/// <summary> /// Updates the inventory mode of this product /// </summary> public void UpdateInventoryMode() { if (this.InventoryMode == InventoryMode.Variant) { ProductVariantManager vm = new ProductVariantManager(this.ProductId); if (vm.Count == 0) { ProductDataSource.UpdateInventoryMode(this.ProductId, InventoryMode.None); _InventoryModeId = (byte)InventoryMode.None; } } }
protected void Page_Init(object sender, EventArgs e) { _CategoryId = AbleCommerce.Code.PageHelper.GetCategoryId(); _Category = CategoryDataSource.Load(_CategoryId); _ProductId = AlwaysConvert.ToInt(Request.QueryString["ProductId"]); _Product = ProductDataSource.Load(_ProductId); if (_Product == null) { Response.Redirect("~/Admin/Catalog/Browse.aspx?CategoryId=" + _CategoryId.ToString()); } _VariantManager = new ProductVariantManager(_ProductId); //BIND GOODS FOR PRODUCT BindDigitalGoodsGrid(); //UPDATE ATTACH BUTTON AllVariants.NavigateUrl += _ProductId.ToString(); //FIGURE OUT PAGING SETTINGS _VariantCount = _VariantManager.CountVariantGrid(); if (_VariantCount > 0) { _WholePages = _VariantCount / _PageSize; _LeftOverItems = _VariantCount % _PageSize; if (_LeftOverItems > 0) { _TotalPages = _WholePages + 1; } else { _TotalPages = _WholePages; } if (_TotalPages == 1) { VariantPager.Visible = false; } //LOAD VIEW STATE LoadCustomViewState(); //SAVE THIS TEXT FOR LATER _DisplayRangeLabelText = DisplayRangeLabel.Text; //INITIALIZE THE GRID BindVariantGrid(); } else { VariantGoodsPanel.Visible = false; } //UPDATE THE CAPTION Caption.Text = string.Format(Caption.Text, _Product.Name); }
protected void Page_Load(object sender, System.EventArgs e) { if (this.Visible) { _ProductId = AlwaysConvert.ToInt(Request.QueryString["ProductId"]); _Product = ProductDataSource.Load(_ProductId); if (_Product != null) { _VariantManager = new ProductVariantManager(_ProductId); _AvailableVariants = _VariantManager.LoadAvailableVariantGrid(); CreateDynamicGrid(); } else { this.Controls.Clear(); } } else { this.Controls.Clear(); } }
/// <summary> /// Deletes this OptionChoice object from database /// </summary> /// <returns><b>true</b> if delete successful, <b>false</b> otherwise.</returns> public bool Delete() { //STORE DATA NECESSARY TO SCRUB VARIANT GRID AFTER DELETE int deletedChoiceId = this.OptionChoiceId; List <int> associatedProducts = new List <int>(); foreach (ProductOption po in this.Option.ProductOptions) { associatedProducts.Add(po.ProductId); } //NOW CALL THE DELETE if (BaseDelete()) { //DELETE SUCCEEDED, SCRUB THE VARIANT GRID foreach (int productId in associatedProducts) { ProductVariantManager.ScrubVariantGrid(productId, deletedChoiceId); } //RETURN SUCCESS return(true); } //BASE DELETE FAILED return(false); }
protected void Page_PreRender(object sender, EventArgs e) { string warnScript; bool hasVariantData = ProductVariantManager.HasVariantData(_ProductId); bool hasDigitalGoods = ProductVariantManager.HasDigitalGoodData(_ProductId); if (hasVariantData || hasDigitalGoods || _Product.KitStatus == KitStatus.Member) { String delMesssage = String.Empty; String addMessage = String.Empty; if (hasVariantData) { delMesssage += "WARNING: If you have made changes to the variant grid, such as adjusting the variant price or in-stock levels, deleting an option will reset this data.\\n\\n"; addMessage += "WARNING: If you have made changes to the variant grid, such as adjusting the variant price or in-stock levels, adding an option will reset this data. \\n\\n"; } if (hasDigitalGoods) { delMesssage += "WARNING: There are digital goods attached to one or more variants, deleting this option will remove all associated digital goods.\\n\\n"; addMessage += "WARNING: There are digital goods attached to one or more existing variants, adding an option will remove all associated digital goods.\\n\\n"; } if (_Product.KitStatus == KitStatus.Member) { addMessage += "WARNING: This product is part of one or more kit products, adding an option will remove this product from those kit products.\\n\\n"; delMesssage += "WARNING: This product is part of one or more kit products, deleting an option will remove this product from those kit products.\\n\\n"; } warnScript = "function confirmAdd(){return confirm('" + addMessage + " Are you sure you want to continue?');}\r\n"; warnScript += "function confirmDel(){return confirm('" + delMesssage + "Are you sure you want to delete this option?');}"; } else { warnScript = "function confirmAdd(){return true;}"; warnScript += "function confirmDel(){return confirm('Are you sure you want to delete this option?');}"; } ScriptManager.RegisterStartupScript(OptionsPanel, OptionsPanel.GetType(), "checkVariant", warnScript, true); }
protected void Page_Load(object sender, EventArgs e) { // ensure we have a valid product int productId = AbleCommerce.Code.PageHelper.GetProductId(); _Product = ProductDataSource.Load(productId); if (_Product == null) { Response.Redirect("~/Admin/Products/ManageProducts.aspx"); } // initialize the page caption Page.Title = string.Format(Page.Title, _Product.Name); Caption.Text = string.Format(Caption.Text, _Product.Name); if (!Page.IsPostBack) { if (Request.UrlReferrer != null && Request.UrlReferrer.AbsolutePath.EndsWith("ManageProducts.aspx")) { CancelButton.NavigateUrl = "~/Admin/Products/ManageProducts.aspx"; CancelButton2.NavigateUrl = "~/Admin/Products/ManageProducts.aspx"; } else { CancelButton.NavigateUrl = "~/Admin/Catalog/Browse.aspx?CategoryId=" + AbleCommerce.Code.PageHelper.GetCategoryId(); CancelButton2.NavigateUrl = "~/Admin/Catalog/Browse.aspx?CategoryId=" + AbleCommerce.Code.PageHelper.GetCategoryId(); } // SHOW SAVE CONFIRMATION NOTIFICATION IF NEEDED if (Request.UrlReferrer != null && Request.UrlReferrer.AbsolutePath.ToLowerInvariant().EndsWith("addproduct.aspx")) { SavedMessage.Visible = true; SavedMessage.Text = string.Format(SavedMessage.Text, LocaleHelper.LocalNow); } } //delete prouduct confirmation string confirmationJS = String.Format("return confirm('Are you sure you want to delete product \"{0}\"?');", _Product.Name); DeleteButton.Attributes.Add("onclick", confirmationJS); DeleteButton1.Attributes.Add("onclick", confirmationJS); // adjust form for store settings if (!AbleContext.Current.Store.Settings.EnableInventory) { CurrentInventoryMode.Visible = false; InventoryDisabledMessage.Visible = true; } else if (!Page.IsPostBack) { ProductVariantManager vm = new ProductVariantManager(_Product.Id); if (vm.Count == 0) { CurrentInventoryMode.Items.RemoveAt(2); if (_Product.InventoryMode == InventoryMode.Variant) { _Product.InventoryMode = InventoryMode.None; } } } AllowReviewsPanel.Visible = (AbleContext.Current.Store.Settings.ProductReviewEnabled != CommerceBuilder.Users.UserAuthFilter.None); // initialize product form if (!Page.IsPostBack) { LoadProduct(); } TIC.Text = HiddenTIC.Value; // initialize form helpers WeightUnit.Text = AbleContext.Current.Store.WeightUnit.ToString(); MeasurementUnit.Text = AbleContext.Current.Store.MeasurementUnit.ToString(); MetaKeywordsCharCount.Text = ((int)(MetaKeywordsValue.MaxLength - MetaKeywordsValue.Text.Length)).ToString(); AbleCommerce.Code.PageHelper.SetMaxLengthCountDown(MetaKeywordsValue, MetaKeywordsCharCount); MetaDescriptionCharCount.Text = ((int)(MetaDescriptionValue.MaxLength - MetaDescriptionValue.Text.Length)).ToString(); AbleCommerce.Code.PageHelper.SetMaxLengthCountDown(MetaDescriptionValue, MetaDescriptionCharCount); // VALIDATE GOOGLE CATEGORY PublishAsVariants.Attributes.Add("onclick", "if(this.checked && document.getElementById('" + GoogleCategory.ClientID + "').value.toLowerCase().indexOf('apparel & accessories') != 0) { alert('You can only submit variant products for google feed if product belongs to \"Apparel & Accessories\" google category or a sub-category.'); return false; }"); if (!AbleContext.Current.Store.Settings.EnableWysiwygEditor) { AbleCommerce.Code.PageHelper.SetHtmlEditor(Summary, SummaryHtmlButton); AbleCommerce.Code.PageHelper.SetHtmlEditor(Description, DescriptionHtmlButton); AbleCommerce.Code.PageHelper.SetHtmlEditor(ExtendedDescription, ExtendedDescriptionHtmlButton); } else { SummaryHtmlButton.Visible = false; DescriptionHtmlButton.Visible = false; ExtendedDescriptionHtmlButton.Visible = false; } }
/// <summary> /// Load the specified product variant /// </summary> /// <param name="productId">The Id of the product</param> /// <param name="optionChoices">A dictionary with OptionId as the key and the selected OptionChoiceId as the value.</param> /// <returns><b>true</b> if load successful, <b>false</b> otherwise</returns> public bool Load(int productId, Dictionary <int, int> optionChoices) { return(Load(productId, ProductVariantManager.GetSortedOptionChoices(productId, optionChoices))); }
protected void Page_Init(object sender, EventArgs e) { _ProductId = AbleCommerce.Code.PageHelper.GetProductId(); _Product = ProductDataSource.Load(_ProductId); _ShowInventory = (_Product.InventoryMode == InventoryMode.Variant && AbleContext.Current.Store.Settings.EnableInventory); if (_Product == null) { Response.Redirect("../../Catalog/Browse.aspx?CategoryId=" + AbleCommerce.Code.PageHelper.GetCategoryId()); } _VariantManager = new ProductVariantManager(_ProductId); if (_VariantManager.Count == 0) { Response.Redirect("Options.aspx?ProductId=" + _ProductId.ToString()); } if (_Product.ProductOptions.Count > ProductVariant.MAXIMUM_ATTRIBUTES) { TooManyVariantsPanel.Visible = true; TooManyVariantsMessage.Text = string.Format(TooManyVariantsMessage.Text, _Product.Name, ProductVariant.MAXIMUM_ATTRIBUTES); } //FIGURE OUT PAGING SETTINGS _VariantCount = _VariantManager.CountVariantGrid(); _WholePages = _VariantCount / _PageSize; _LeftOverItems = _VariantCount % _PageSize; if (_LeftOverItems > 0) { _TotalPages = _WholePages + 1; } else { _TotalPages = _WholePages; } PagerPanel.Visible = (_TotalPages > 1); if (!Page.IsPostBack) { _optionsGridKey = _optionsGridKey + _ProductId; string optionsGridColumns = AbleContext.Current.User.Settings.GetValueByKey(_optionsGridKey); if (!string.IsNullOrEmpty(optionsGridColumns)) { string[] cols = optionsGridColumns.Split(','); if (cols != null) { names = cols.ToList <string>(); foreach (string name in names) { ListItem li = FieldNamesList.Items.FindByValue(name); if (li != null && !li.Selected) { li.Selected = true; } } } } } //LOAD VIEW STATE LoadCustomViewState(); //SAVE THIS TEXT FOR LATER _DisplayRangeLabelText = DisplayRangeLabel.Text; //CONVERT VARIANT FORM DATA TO STRING DICTIONARY ParseFormData(); //INITIALIZE THE GRID BindVariantGrid(); //UPDATE THE CAPTION Caption.Text = string.Format(Caption.Text, _Product.Name); //HIDE THE FIELDS WHEN INVENTORY IS DISABLED FOR VARIANT PRODUCT if (!_ShowInventory) { List <ListItem> removeItems = new List <ListItem>(); for (int i = 0; i < FieldNamesList.Items.Count; i++) { ListItem item = FieldNamesList.Items[i]; if ((item.Value == "InStock") || (item.Value == "Availability") || (item.Value == "LowStock")) { removeItems.Add(item); } } foreach (ListItem li in removeItems) { FieldNamesList.Items.Remove(li); } } }
protected void Page_Load(object sender, EventArgs e) { // a category is required to add a product int categoryId = AbleCommerce.Code.PageHelper.GetCategoryId(); Category category = CategoryDataSource.Load(categoryId); if (category == null) { Response.Redirect("~/Admin/Products/ManageProducts.aspx"); } // initialize the page caption Caption.Text = string.Format(Caption.Text, category.Name); if (!Page.IsPostBack) { if (Request.UrlReferrer != null && Request.UrlReferrer.AbsolutePath.EndsWith("ManageProducts.aspx")) { CancelButton.NavigateUrl = "~/Admin/Products/ManageProducts.aspx"; CancelButton2.NavigateUrl = "~/Admin/Products/ManageProducts.aspx"; } else { CancelButton.NavigateUrl = "~/Admin/Catalog/Browse.aspx?CategoryId=" + categoryId.ToString(); CancelButton2.NavigateUrl = "~/Admin/Catalog/Browse.aspx?CategoryId=" + categoryId.ToString(); } ProductGroups.Attributes.Add("disabled", "true"); if (trTIC.Visible && product.TIC.HasValue && product.TIC != 0) { TIC.Text = product.TIC.ToString(); } } // adjust form for store settings if (!AbleContext.Current.Store.Settings.EnableInventory) { CurrentInventoryMode.Visible = false; InventoryDisabledMessage.Visible = true; } else { ProductVariantManager vm = new ProductVariantManager(product.Id); if (vm.Count == 0) { CurrentInventoryMode.Items.RemoveAt(2); if (product.InventoryMode == InventoryMode.Variant) { product.InventoryMode = InventoryMode.None; } } if (product.InventoryMode == InventoryMode.Product) { InStock.Text = product.InStock.ToString(); LowStock.Text = product.InStockWarningLevel.ToString(); AvailabilityDate.SelectedDate = product.AvailabilityDate.HasValue ? product.AvailabilityDate.Value: DateTime.MinValue; BackOrder.Checked = product.AllowBackorder; } else if (product.InventoryMode == InventoryMode.Variant) { BackOrder.Checked = product.AllowBackorder; } } AllowReviewsPanel.Visible = (AbleContext.Current.Store.Settings.ProductReviewEnabled != CommerceBuilder.Users.UserAuthFilter.None); // initialize form helpers WeightUnit.Text = AbleContext.Current.Store.WeightUnit.ToString(); MeasurementUnit.Text = AbleContext.Current.Store.MeasurementUnit.ToString(); MetaKeywordsCharCount.Text = ((int)(MetaKeywordsValue.MaxLength - MetaKeywordsValue.Text.Length)).ToString(); AbleCommerce.Code.PageHelper.SetMaxLengthCountDown(MetaKeywordsValue, MetaKeywordsCharCount); MetaDescriptionCharCount.Text = ((int)(MetaDescriptionValue.MaxLength - MetaDescriptionValue.Text.Length)).ToString(); AbleCommerce.Code.PageHelper.SetMaxLengthCountDown(MetaDescriptionValue, MetaDescriptionCharCount); // VALIDATE GOOGLE CATEGORY PublishAsVariants.Attributes.Add("onclick", "if(this.checked && document.getElementById('" + GoogleCategory.ClientID + "').value.toLowerCase().indexOf('apparel & accessories') != 0) { alert('You can only submit variant products for google feed if product belongs to \"Apparel & Accessories\" google categoryor a sub-category.'); return false; }"); if (!AbleContext.Current.Store.Settings.EnableWysiwygEditor) { AbleCommerce.Code.PageHelper.SetHtmlEditor(Summary, SummaryHtmlButton); AbleCommerce.Code.PageHelper.SetHtmlEditor(Description, DescriptionHtmlButton); AbleCommerce.Code.PageHelper.SetHtmlEditor(ExtendedDescription, ExtendedDescriptionHtmlButton); } else { SummaryHtmlButton.Visible = false; DescriptionHtmlButton.Visible = false; ExtendedDescriptionHtmlButton.Visible = false; } }
private static IList <Variant> GetAvailableVariants(Product product) { IList <Variant> variants = new List <Variant>(); List <Option> relatedOptions = new List <Option>(); int lastIndex = -1, colorOptionIndex = -1, sizeOptionIndex = -1, materialOptionIndex = -1, patternOptionIndex = -1; Option colorOption = null, sizeOption = null, materialOption = null, patternOption = null; string optionListPattern = string.Empty; if (product.ProductOptions.Count > 0) { // check variants and options IList <ProductOption> options = product.ProductOptions; foreach (ProductOption pOption in options) { if (!string.IsNullOrEmpty(optionListPattern)) { optionListPattern += ","; } string optionName = pOption.Option.Name.ToLowerInvariant(); if (optionName == "color") { colorOption = pOption.Option; colorOptionIndex = ++lastIndex; relatedOptions.Add(colorOption); optionListPattern += "{C}"; } else if (optionName == "size") { sizeOption = pOption.Option; sizeOptionIndex = ++lastIndex; relatedOptions.Add(sizeOption); optionListPattern += "{S}"; } else if (optionName == "material") { materialOption = pOption.Option; materialOptionIndex = ++lastIndex; relatedOptions.Add(materialOption); optionListPattern += "{M}"; } else if (optionName == "pattern") { patternOption = pOption.Option; patternOptionIndex = ++lastIndex; relatedOptions.Add(patternOption); optionListPattern += "{P}"; } else { optionListPattern += "0"; // fill the options list pattern with zero } } } if (relatedOptions.Count > 0) { Store store = AbleContext.Current.Store; string storeUrl = store.StoreUrl; if (!storeUrl.EndsWith("/")) { storeUrl += "/"; } // calculate all valid combinations using the option choices List <int[]> choiceCombinations = GetAllChoicesCombinations(relatedOptions); ProductVariantManager variantManager = new ProductVariantManager(product.Id); IList <string> imageUrlList = new List <string>(); // require to keep track of unique images for variants foreach (int[] choicesCombination in choiceCombinations) { // collect the choice id values int colorChoiceId = 0, sizeChoiceId = 0, materialChoiceId = 0, patternChoiceId = 0; if (colorOptionIndex >= 0) { colorChoiceId = choicesCombination[colorOptionIndex]; } if (sizeOptionIndex >= 0) { sizeChoiceId = choicesCombination[sizeOptionIndex]; } if (materialOptionIndex >= 0) { materialChoiceId = choicesCombination[materialOptionIndex]; } if (patternOptionIndex >= 0) { patternChoiceId = choicesCombination[patternOptionIndex]; } // build option list, fill the color, size, material, and pattern choice id values while for rest of options fill in zero value string optionList = optionListPattern; optionList = optionList.Replace("{C}", colorChoiceId.ToString()); optionList = optionList.Replace("{S}", sizeChoiceId.ToString()); optionList = optionList.Replace("{M}", materialChoiceId.ToString()); optionList = optionList.Replace("{P}", patternChoiceId.ToString()); ProductVariant productVariant = variantManager.GetVariantFromOptions(optionList); if (productVariant != null) { // check availability if (!productVariant.Available) { continue; } Variant variant = new Variant(); variant.Product = product; string variantNamePart = string.Empty; string variantoptionsList = string.Empty; if (colorChoiceId > 0) { variant.Color = EntityLoader.Load <OptionChoice>(colorChoiceId).Name; variantNamePart += string.IsNullOrEmpty(variantNamePart) ? variant.Color : "," + variant.Color; variantoptionsList += string.IsNullOrEmpty(variantoptionsList) ? colorChoiceId.ToString() : "," + colorChoiceId.ToString(); } if (sizeChoiceId > 0) { variant.Size = EntityLoader.Load <OptionChoice>(sizeChoiceId).Name; variantNamePart += string.IsNullOrEmpty(variantNamePart) ? variant.Size : "," + variant.Size; variantoptionsList += string.IsNullOrEmpty(variantoptionsList) ? sizeChoiceId.ToString() : "," + sizeChoiceId.ToString(); } if (materialChoiceId > 0) { variant.Material = EntityLoader.Load <OptionChoice>(materialChoiceId).Name; variantNamePart += string.IsNullOrEmpty(variantNamePart) ? variant.Material : "," + variant.Material; variantoptionsList += string.IsNullOrEmpty(variantoptionsList) ? materialChoiceId.ToString() : "," + materialChoiceId.ToString(); } if (patternChoiceId > 0) { variant.Pattern = EntityLoader.Load <OptionChoice>(patternChoiceId).Name; variantNamePart += string.IsNullOrEmpty(variantNamePart) ? variant.Pattern : "," + variant.Pattern; variantoptionsList += string.IsNullOrEmpty(variantoptionsList) ? patternChoiceId.ToString() : "," + patternChoiceId.ToString(); } variant.Name = string.Format("{0} - {1}", product.Name, variantNamePart); variant.Link = ResolveUrl(product.NavigateUrl, storeUrl) + string.Format("?Options={0}", variantoptionsList); // WE CAN ONLY USE ALPHANUMERIC CHARACTERS FOR ID, CREATE ID VALUE USING THE APAREL OPTIONS // [Product_Id]C[COLOR_CHOICE_ID]S[SIZE_CHOICE_ID]M[MATERIAL_CHOICE_ID]P[PATTERN_CHOICE_ID] variant.Id = string.Format("{0}C{1}S{2}M{3}P{4}", product.Id, (colorOptionIndex > -1 ? colorChoiceId.ToString() : string.Empty), (sizeOptionIndex > -1 ? sizeChoiceId.ToString() : string.Empty), (materialOptionIndex > -1 ? materialChoiceId.ToString() : string.Empty), (patternOptionIndex > -1 ? patternChoiceId.ToString() : string.Empty)); // VERIFY UNIQUE IMAGE LINK CONSIDERING FOLLOWING GOOGLE FEED REQUIREMENTS // For products that fall under “Apparel & Accessories” and all corresponding sub-categories in feeds targeting the US, UK, DE, FR, and JP: // If you are submitting product variants that differ in ‘‘color’, or ‘pattern’, or ‘material’, // we require you to submit specific images corresponding to each of these variants. // If you do not have the correct image for the variation of the product, you may not submit that variant. // We recommend specific images for ‘size’ variants too. However, if these are not available you may submit the same image URL for items that differ in ‘size’. string imageUrl = string.Empty; if (!string.IsNullOrEmpty(productVariant.ImageUrl)) { imageUrl = productVariant.ImageUrl.ToLowerInvariant(); } if (string.IsNullOrEmpty(imageUrl) && !string.IsNullOrEmpty(product.ImageUrl)) { imageUrl = product.ImageUrl.ToLowerInvariant(); // use product image if no image } if (string.IsNullOrEmpty(imageUrl)) { continue; // skip if no image } if (!IsAbsoluteURL(imageUrl)) { imageUrl = ResolveUrl(imageUrl, storeUrl); } // verify unique image for each combination of ‘color’, ‘pattern’, and ‘material’ if (imageUrlList.Contains(imageUrl)) { bool isUniqueImage = true; // MAKE SURE OTHER VARIANTS ONLY DIFFER BY SIZE, OTHERWISE SKIP THIS foreach (Variant otherVariant in variants) { if (imageUrl == otherVariant.ImageUrl) { if (!(variant.Color == otherVariant.Color && variant.Pattern == otherVariant.Pattern && variant.Material == otherVariant.Material && variant.Size != otherVariant.Size)) { isUniqueImage = false; break; } } } // SKIP THIS VARIANT, AS WE DO NOT HAVE A UNIQUE IMAGE FOR THIS VARIANT AS THIS IMAGE ALREADY USED FOR ANOTHER VARIANT, WHICH DIFFERS FOR MORE THEN SIZE if (!isUniqueImage) { continue; } } // else add to variant image dictionary to keep track of rest of variants imageUrlList.Add(imageUrl); variant.ImageUrl = imageUrl; // use product id as item group id, this must be same for all variants of same product, but must be unique for variants of each product variant.ItemGroupId = product.Id.ToString(); ProductCalculator productCalculator = ProductCalculator.LoadForProduct(product.Id, 1, productVariant.OptionList, string.Empty, 0); variant.Weight = productCalculator.Weight; variant.Price = productCalculator.Price; variant.Sku = productCalculator.Sku; string gtin = productVariant.GTIN; if (string.IsNullOrEmpty(gtin)) { // for compatibility with AC7 data check if SKU is a UPC gtin = IsUpcCode(productVariant.Sku) ? productVariant.Sku : string.Empty; } variant.GTIN = gtin; variant.ModelNumber = productVariant.ModelNumber; variant.InStock = productVariant.InStock; variants.Add(variant); } } } return(variants); }