private OptionChoice GetSelectedChoice(OptionChoiceCollection options) { foreach (OptionChoice choice in options) { if (choice.OptionChoiceId == this.SelectedChoiceId) { return(choice); } } return(null); }
/// <summary> /// Gets the name of the selected option choice /// </summary> /// <param name="choices">Collection of option choices</param> /// <returns>The name of the selected option choice</returns> public string GetSelectedOptionChoiceName(OptionChoiceCollection choices) { int index = choices.IndexOf(this.Option1); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option2); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option3); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option4); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option5); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option6); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option7); if (index > -1) { return(choices[index].Name); } index = choices.IndexOf(this.Option8); if (index > -1) { return(choices[index].Name); } return(""); }
/// <summary> /// Gets available choices for a product for given option /// </summary> /// <param name="productId">Id of the product</param> /// <param name="targetOptionId">Id of the option to check for choices</param> /// <param name="selectedChoices">A Dictionary<int, int> of option choices already selected. The dictionary key is the OptionId and the value is the OptionChoiceId.</param> /// <returns>Collection of OptionChoice objects</returns> public static OptionChoiceCollection GetAvailableChoices(int productId, int targetOptionId, Dictionary <int, int> selectedChoices) { OptionChoiceCollection availableOptionChoices = new OptionChoiceCollection(); Product product = ProductDataSource.Load(productId); if (product != null) { // SEE IF OPTIONS EXIST, NOTE WE ARE LOADING THE OPTIONS ACCORDING TO THE SORT SPECIFIED FOR VARIANT MANAGEMENT // THIS WILL NOT BE THE SAME AS THE DEFAULT SORT ORDER THAT IS DETERMINED BY THE MERCHANT OptionCollection options = OptionDataSource.LoadForProduct(productId, ProductVariant.VARIANT_SORT_EXPRESSION); if (options.Count > 0) { //CAST OFF ANY ATTRIBUTES PAST THE MAXIMUM ALLOWED COUNT while (options.Count > ProductVariant.MAXIMUM_ATTRIBUTES) { options.RemoveAt(ProductVariant.MAXIMUM_ATTRIBUTES); } // DETERMINE THE INDEX USED OR VARIANT MANAGEMENT, THIS ROUGHLY CORRESPONDS TO THE COLUMN NAMES IN ac_ProductVariants TABLE // BUT NOTE THIS VARIANT INDEX IS ZERO BASED, WHERE THE TABLE COLUMN NAMES ARE 1 BASED: OPTION1, OPTION2, ETC. int targetOptionVariantIndex = options.IndexOf(targetOptionId); if (targetOptionVariantIndex > -1) { // SET THE TARGET OPTION Option targetOption = options[targetOptionVariantIndex]; // BUILD THE LIST OF CHOICES SELECTED SO FAR // SELECTED CHOICES KEY IS OPTION INDEX FOR VARIANT MANAGER // THE VALUE IS THE SELECTED CHOICE FOR THAT OPTION INDEX Dictionary <int, int> validSelectedChoices = new Dictionary <int, int>(); for (int i = 0; i < options.Count; i++) { Option option = options[i]; // IGNORE ANY SELECTED CHOICE FOR THE TARGET OPTION if (option.OptionId != targetOptionId && selectedChoices.ContainsKey(option.OptionId)) { // SEE IF THERE IS A CHOICE INDICATED FOR THIS OPTION IN THE QUERY STRING int choiceId = selectedChoices[option.OptionId]; int choiceIndex = option.Choices.IndexOf(choiceId); if (choiceIndex > -1) { // THIS IS A VALID SELECTED CHOICE validSelectedChoices.Add(i, choiceId); } } } // IF INVENTORY IS ENABLED, WE SIMPLY QUERY THE VARIANT GRID if (Token.Instance.Store.EnableInventory && !product.AllowBackorder && product.InventoryMode == InventoryMode.Variant) { List <int> probableChoices = OptionChoiceDataSource.GetAvailableChoicesFromInventory(productId, validSelectedChoices, targetOptionVariantIndex); // THIS STEP IS PROBABLY UNNEEDED, BUT LETS CONFIRM THE CHOICES FROM THE DATABASE ARE VALID // (THE VARIANT TABLE CANNOT BENEFIT FROM CONSTRAINTS TO ENFORCE DATA INTEGRITY) foreach (int choiceId in probableChoices) { int choiceIndex = targetOption.Choices.IndexOf(choiceId); if (choiceIndex > -1) { // THIS IS A VALID OPTION CHOICE ID availableOptionChoices.Add(targetOption.Choices[choiceIndex]); } } } else { // CALCULATE THE REMAINING POSSIBLE OPTION COMBINATIONS FOR EACH CHOICE int possibleCount = 1; foreach (Option option in options) { // WE SHOULD NOT INCLUDE THE TARGET OPTION IN THIS COUNT if (option.OptionId != targetOptionId) { // WE SHOULD NOT INCLUDE ANY OPTION THAT HAS ALREADY BEEN SELECTED int variantIndex = options.IndexOf(option.OptionId); if (!validSelectedChoices.ContainsKey(variantIndex)) { // WE HAVE FOUND A CHOICE THAT IS NOT SELECTED AND IS NOT // THE TARGET CHOICE. SO WE MUST CONSIDER ALL CHOICES AS POTENTIAL // AND INCLUDE THEM IN THE COUNT possibleCount = possibleCount * option.Choices.Count; } } } // BUILD THE DICTIONARY OF UNAVAILABLE COUNTS // THIS WILL BE GROUPED BY THE CHOICEID FOR THE TARGET OPTION // AND WILL TELL US HOW MANY COMBINATIONS ARE INVALID FOR THAT CHOICE // IF THE NUMBER MATCHES THE POSSIBLE COUNT, THEN ALL COMBINATIONS ARE UNAVAILABLE // AND THIS CHOICE SHOULD NOT BE INCLUDED AS AVAILABLE Dictionary <int, int> unavailableVariantCounts = OptionChoiceDataSource.GetUnavailableVariantCounts(productId, validSelectedChoices, targetOptionVariantIndex); foreach (OptionChoice possibleChoice in targetOption.Choices) { // CHECK IF THERE ARE NO UNAVAILABLE VARIANTS FOR THIS CHOICE // OR THE UNAVAILABLE COUNT IS LESS THAN THE POSSIBLE COMBINATION COUNT if (!unavailableVariantCounts.ContainsKey(possibleChoice.OptionChoiceId) || unavailableVariantCounts[possibleChoice.OptionChoiceId] < possibleCount) { // THIS IS A VALID CHOICE availableOptionChoices.Add(possibleChoice); } } } } } } return(availableOptionChoices); }
/// <summary> /// Calculates variant /// </summary> /// <returns><b>true</b> if calculation successful, <b>false</b> otherwise</returns> public bool CalculateVariant() { _Calculated = false; int[] choiceIds = this.GetOptionChoices(OptionCountBehavior.ActualCount); if (choiceIds != null && choiceIds.Length > 0) { //INITIALIZE THE CALCULATED VALUES _CalculatedPrice = 0; _CalculatedWeight = 0; //BUILD CRITERIA TO LOAD CORRECT OPTIONS string criteria; if (choiceIds.Length == 1) { criteria = "OptionChoiceId = " + choiceIds[0].ToString(); } else { string idList = AlwaysConvert.ToList(",", choiceIds); criteria = "OptionChoiceId IN (" + idList + ")"; } //RECALCULATE ALL ITEMS OptionChoiceCollection choices = OptionChoiceDataSource.LoadForCriteria(criteria); OptionChoice choice; List <string> names = new List <string>(); StringBuilder sku = new StringBuilder(); sku.Append(this.Product.Sku); //LOOP ALL CHOICES INDICATED FOR THIS VARIANT AND CALCULATE THE MODIFIERS foreach (int optionChoiceId in choiceIds) { int index = choices.IndexOf(optionChoiceId); if (index > -1) { choice = choices[index]; names.Add(choice.Name); _CalculatedPrice += choice.PriceModifier; _CalculatedWeight += choice.WeightModifier; sku.Append(choice.SkuModifier); } } //SET THE CALCULATED VALUES _CalculatedName = String.Join(", ", names.ToArray()); _CalculatedSku = sku.ToString(); if (this.VariantName == string.Empty) { this.VariantName = _CalculatedName; } if (this.Price == 0) { this.Price = _CalculatedPrice; } if (this.Weight == 0) { this.Weight = _CalculatedWeight; } if (this.Sku == string.Empty) { this.Sku = _CalculatedSku; } _Calculated = true; } return(_Calculated); }
protected override void Render(HtmlTextWriter output) { StringBuilder html = new StringBuilder(); if (this.RenderOptions) { if (_Option != null) { int productId = 0; if (_Option.ProductOptions.Count > 0) { productId = _Option.ProductOptions[0].ProductId; } OptionChoiceCollection availableChoices = null; if (ForceToLoadAllChoices) { availableChoices = _Option.Choices; } else { availableChoices = OptionChoiceDataSource.GetAvailableChoices(productId, _Option.OptionId, _SelectedChoices); } if (availableChoices.Count > 0) { //ADD REQUIRED STYLING FOR SWATCH //SET THE HEIGHT AND WIDTH html.Append("<style>\n"); html.Append(" ." + this.ClientID + " td { padding:0px !important;width:" + _Option.ActiveThumbnailWidth + "px;height:" + _Option.ActiveThumbnailHeight + "px;cursor:pointer; }\n"); html.Append("</style>\n"); html.Append("<div class=\"" + this.ClientID); if (!string.IsNullOrEmpty(this.CssClass)) { html.Append(" " + this.CssClass); } html.Append("\">\n"); //OUTPUT THE CURRENT SELECTION html.Append("<span id=\"" + this.ClientID + "Text\">"); OptionChoice selOpt = GetSelectedChoice(availableChoices); if (selOpt != null) { html.Append(selOpt.Name); } html.Append("</span>\n"); //OUTPUT THE SWATCH PICKER html.Append(" <table cellpadding=\"0\" cellspacing=\"2\" onclick=\"javascript:OptionPickerClick(event, '" + this.ClientID + "');"); if (this.AutoPostBack) { PostBackOptions options = new PostBackOptions(this, string.Empty); options.AutoPostBack = true; html.Append(this.Page.ClientScript.GetPostBackEventReference(options, true)); } html.Append("\">\n"); for (int i = 0; i < availableChoices.Count; i++) { if (i % _Option.ActiveThumbnailColumns == 0) { if (i > 0) { html.Append(" </tr>\n"); } html.Append(" <tr>\n"); } OptionChoice choice = availableChoices[i]; html.Append(" <td"); if (choice.OptionChoiceId == this.SelectedChoiceId) { html.Append(" class=\"selected\""); } html.Append(" title=\"" + HttpUtility.HtmlEncode(choice.Name) + "\""); html.Append(" style=\"background-image:url(" + this.Page.ResolveUrl(choice.ThumbnailUrl) + ");z-index:" + choice.OptionChoiceId.ToString() + "\"> </td>\n"); } html.Append(" </tr>\n"); html.Append(" </table>\n"); html.Append("</div>\n"); } else { html.Append("(no options available)"); } html.Append("<input type=\"hidden\" id=\"" + this.ClientID + "\" name=\"" + this.UniqueID + "\" value=\"" + this.SelectedChoiceId.ToString() + "\">\n"); } else { WebTrace.Write(this.UniqueID, "Invalid Option " + this.OptionId.ToString()); } } output.Write(html.ToString()); }