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;
            }
        }
Ejemplo n.º 2
0
        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();
            }
        }
Ejemplo n.º 3
0
        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);
            }
        }
Ejemplo n.º 4
0
        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();
            }
        }
Ejemplo n.º 5
0
        /// <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);
        }
Ejemplo n.º 6
0
        /// <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);
        }
Ejemplo n.º 7
0
 /// <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;
         }
     }
 }
Ejemplo n.º 8
0
 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);
 }
Ejemplo n.º 9
0
 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();
     }
 }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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;
            }
        }
Ejemplo n.º 13
0
 /// <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)));
 }
Ejemplo n.º 14
0
        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);
                }
            }
        }
Ejemplo n.º 15
0
        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;
            }
        }
Ejemplo n.º 16
0
        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);
        }