protected virtual List <KeyVariantAttributeItem> EnableKvasInStock(GenerateKvaItemsParam kvaParam, List <KeyVariantAttributeItem> kvas) { //Enable available kvas foreach (var kva in kvaParam.SelectedKvas) { //get all enabled variants for the first level. i.e.: for color "black" this list would contain all sizes available for black in the first loop //and the second loop all colors for the size 5 var enabledList = kvaParam.ProductVariants.Where(x => x.Kvas[kva.Key].Equals(kva.Value)).SelectMany(x => x.Kvas).Where(x => !x.Key.Equals(kva.Key)).ToList(); foreach (var enabledItem in enabledList) { var property = kvas.First(x => x.PropertyName.Equals(enabledItem.Key)); if (property.Values.Any(x => x.Value.ToString().Equals(enabledItem.Value.ToString()))) { property.Values.First(x => x.Value.ToString().Equals(enabledItem.Value.ToString())).Disabled = false; } } ; } ; return(kvas); }
private List <KeyVariantAttributeItem> DisableMissingKvas(GenerateKvaItemsParam kvaParam, List <KeyVariantAttributeItem> kvas) { foreach (var selectedKva in kvaParam.SelectedKvas) { var existingKvasOtherThanSelected = kvaParam.ProductVariants //All product variants that have the same KVA as our selected one .Where(productVariant => productVariant.Kvas[selectedKva.Key].Equals(selectedKva.Value)) .SelectMany(productVariant => productVariant.Kvas) //Flatten our product variants to their KVA values //Ignore the KVAs retrieved that are the same type as our selected one (i.e. if our selected is Color, ignore all Color KVAs and keep the other ones) .Where(productVariantKva => !productVariantKva.Key.Equals(selectedKva.Key)) .ToList(); var allPossibleKvasOtherThanSelected = kvas .Where(kva => !kva.PropertyName.Equals(selectedKva.Key)) .SelectMany(v => v.Values); var notExistingKva = allPossibleKvasOtherThanSelected.Where(x => !existingKvasOtherThanSelected.Any(ekva => ekva.Value.Equals(x.Value))); foreach (var kva in notExistingKva) { kva.Disabled = true; } ; } ; return(kvas); }
/// <summary> /// Generates the kva items that will be used to display the product properties values. Basically, this /// method generates a flat list of key value properties and their possible values. /// </summary> /// <param name="kvaParam">The GenerateKvaItemsParam</param> protected virtual List <KeyVariantAttributeItem> CreateKvaItems(GenerateKvaItemsParam kvaParam) { var kvas = new List <KeyVariantAttributeItem>(); if (kvaParam.Product.Variants == null) { return(kvas); } var productFormatter = new ProductFormatter(LocalizationProvider, LookupService); var properties = kvaParam.ProductDefinition.VariantProperties .Where(v => v.IsKeyVariant) .OrderBy(v => v.KeyVariantOrder) .ThenBy(v => v.DisplayOrder) .ToList(); foreach (var property in properties) { //Get Values var items = kvaParam.Product.Variants .Where(v => v.Active.GetValueOrDefault()) .SelectMany(v => v.PropertyBag.Select(pb => new { Variant = v, PB = pb })) .Where(o => o.PB.Key == property.PropertyName) .GroupBy(o => o.PB.Value) .Select(g => new KeyVariantAttributeItemValue { Title = productFormatter.FormatValue(property, g.Key, kvaParam.CultureInfo) ?? (g.Key ?? string.Empty).ToString(), Value = g.Key, Selected = false, Disabled = false, RelatedVariantIds = g.Select(o => o.Variant.Id).ToList() }) .ToList(); //Sort if (property.DataType == PropertyDataType.Boolean || property.DataType == PropertyDataType.Text) { //Localised Alphabetic Order items = items.OrderBy(i => i.Title) .ThenBy(i => i.Value) .ToList(); } else if (property.DataType == PropertyDataType.Lookup) { var lookupValues = kvaParam.ProductLookups .Where(l => l.LookupName == property.LookupDefinition.LookupName) .Select(l => l.Values) .FirstOrDefault() ?? new List <LookupValue>(); //Weight Defined SortOrder (with fallback to Alphabetic) items = items.Join(lookupValues, i => i.Value, lv => lv.Value, (i, lv) => new { Item = i, LookupValue = lv }) .OrderBy(o => o.LookupValue.SortOrder) .ThenBy(o => o.Item.Title) .ThenBy(o => o.Item.Value) .Select(o => o.Item) .ToList(); } else { //Semantic Order (Numerical or Chronological) items = items.OrderBy(i => i.Value).ToList(); } //Bind Images from LookupValues if (property.LookupDefinition != null) { string lookupName = property.LookupDefinition.LookupName; items.ForEach(item => item.ImageUrl = GetLookupImageUrl(lookupName, item.Value) ); } //BindSelected if (kvaParam.SelectedKvas.TryGetValue(property.PropertyName, out object selectedValue)) { var item = items.FirstOrDefault(i => i.Value.Equals(selectedValue)); if (item != null) { item.Selected = true; item.Disabled = false; } } //Stock kvas.Add(new KeyVariantAttributeItem { DisplayName = property.DisplayName.GetLocalizedValue(kvaParam.CultureInfo.Name) ?? property.PropertyName, PropertyName = property.PropertyName, PropertyDataType = property.DataType.ToString("g"), Values = items }); } kvas = DisableMissingKvas(kvaParam, kvas); return(EnableKvasInStock(kvaParam, kvas)); }