private InventoryInfo GetInventoryInfo(Dictionary <string, InventoryInfo> inventories, BasketItem item)
        {
            // KEY MUST BE UNIQUE FOR THE PRODUCT (INCLUDING OPTIONS AND KITS)
            string key = item.Product.Id + "_" + item.OptionList + "_" + item.KitList;

            if (inventories.ContainsKey(key))
            {
                // RETURN THE INVENTORY INFO FROM CACHE
                return(inventories[key]);
            }
            else
            {
                // CREATE A NEW INVENTORY INFO STRUCTURE
                InventoryManagerData invd = _InventoryManager.CheckStock(item);
                InventoryInfo        info = new InventoryInfo(invd);
                inventories[key] = info;

                // POPULATE THE INVENTORY INFO FOR ANY CHILD PRODUCTS
                foreach (InventoryManagerData invd1 in invd.ChildItemInventoryData)
                {
                    // CHILD KEY WILL NOT CONTAIN THE KIT LIST PART AS WE DO NOT ALLOW TO NEXT KITS
                    string childKey = invd1.ProductId + "_" + invd1.OptionList + "_";
                    if (!inventories.ContainsKey(childKey))
                    {
                        inventories[childKey] = new InventoryInfo(invd1);
                    }
                }
                return(info);
            }
        }
        protected string GetAvailableQuantity(object dataItem)
        {
            BasketItem item = (BasketItem)dataItem;

            if (_StoreInventoryEnabled && item.Product != null && item.Product.InventoryMode != InventoryMode.None)
            {
                List <int> kitList = null;
                if (!string.IsNullOrEmpty(item.KitList))
                {
                    kitList = new List <int>();
                    kitList.AddRange(AlwaysConvert.ToIntArray(item.KitList));
                }
                InventoryManagerData inv = _InventoryManager.CheckStock(item.ProductId, item.OptionList, kitList);
                return(inv.InStock.ToString());
            }
            else
            {
                return("n/a");
            }
        }
        protected void InventoryAlertUpdate()
        {
            if (_Product != null)
            {
                // WE HAVE A VALID PRODUCT, ARE ANY AVAILABLE OPTIONS SELECTED?
                bool allProductOptionsSelected = (_SelectedOptions.Count == _Product.ProductOptions.Count);
                if (allProductOptionsSelected)
                {
                    // OPTIONS ARE GOOD, VERIFY ANY REQUIRED KIT OPTIONS ARE SELECTED
                    GetSelectedKitOptions(_Product);
                    bool requiredKitOptionsSelected = AbleCommerce.Code.ProductHelper.RequiredKitOptionsSelected(_Product, _SelectedKitProducts);
                    if (requiredKitOptionsSelected)
                    {
                        // KIT OPTIONS ARE ALSO VALID, DETERMINE APPROPRIATE WARNINGS
                        Store         store           = AbleContext.Current.Store;
                        List <string> warningMessages = new List <string>();

                        string optionList = string.Empty;
                        if (_Product.ProductOptions.Count > 0)
                        {
                            // OPTIONS ARE PRESENT, CHECK AVAILABLILITY
                            optionList = ProductVariantDataSource.GetOptionList(_ProductId, _SelectedOptions, true);
                            ProductVariant variant = ProductVariantDataSource.LoadForOptionList(_Product.Id, optionList);
                            if (!variant.Available)
                            {
                                warningMessages.Add("The selected variant is marked as unavailable.");
                            }

                            // WE ALSO NEED TO ALERT INVENTORY IF ENABLED AT VARIANT LEVEL AND THIS IS NOT A KIT
                            if (store.Settings.EnableInventory &&
                                _Product.KitStatus != KitStatus.Master &&
                                _Product.InventoryMode == InventoryMode.Variant)
                            {
                                warningMessages.Add("The selected variant has a current stock level of " + variant.InStock + ".");
                            }
                        }

                        // CHECK STOCK QUANTITY FOR PRODUCT, IF STORE INVENTORY IS ENABLED
                        // AND THE STOCK IS MANAGED AT THE PRODUCT LEVEL OR THIS IS A KIT
                        if (store.Settings.EnableInventory && (_Product.InventoryMode == InventoryMode.Product || _Product.KitStatus == KitStatus.Master))
                        {
                            IInventoryManager    inventoryManager = AbleContext.Resolve <IInventoryManager>();
                            InventoryManagerData inv = inventoryManager.CheckStock(_ProductId, optionList, _SelectedKitProducts);
                            if (!inv.AllowBackorder)
                            {
                                if (_Product.KitStatus == KitStatus.Master)
                                {
                                    // INVENTORY MESSAGE FOR KIT PRODUCTS
                                    warningMessages.Add("The selected configuration has a current stock level of " + inv.InStock + ".");
                                }
                                else
                                {
                                    // NOT KIT OR VARIANT
                                    warningMessages.Add("This product has a current stock level of " + inv.InStock + ".");
                                }
                            }
                        }

                        // SHOW ANY WARNING MESSAGES
                        if (warningMessages.Count > 0)
                        {
                            InventoryWarningMessage.Text = "Note: " + string.Join(" ", warningMessages.ToArray());
                            trInventoryWarning.Visible   = true;
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the InventoryInfo struct.
 /// </summary>
 /// <param name="invd">Inventory manager data.</param>
 public InventoryInfo(InventoryManagerData invd)
 {
     InventoryStatus = invd;
     NowAvailable    = invd.InStock;
 }