/// <summary>
        /// Gets a dictionary of potential discounts for the basket.
        /// </summary>
        /// <param name="basket">Basket to check for potential discounts</param>
        /// <param name="productsToExclude">Products that should not be considered for discounts.</param>
        /// <param name="groupingMode">Grouping mode in use</param>
        /// <returns>A dictionary of potential discounts for the order.</returns>
        private static Dictionary <int, List <PotentialDiscount> > GetPotentialDiscounts(Basket basket, List <int> productsToExclude, GroupingMode groupingMode)
        {
            //INITIALIZE THE RETURN VALUE
            Dictionary <int, List <PotentialDiscount> > potentialDiscounts = new Dictionary <int, List <PotentialDiscount> >();

            //KEEP TRACK OF PRODUCTS TO EXCLUDE FROM GLOBAL DISCOUNTS
            List <int> excludeGlobal = new List <int>();

            //BUILD CRITERIA FOR PRODUCTS TO EXCLUDE FROM QUERY
            string excludedProducts = string.Empty;

            if (productsToExclude.Count > 0)
            {
                if (productsToExclude.Count == 1)
                {
                    excludedProducts = " AND ProductId <> " + productsToExclude[0].ToString();
                }
                else
                {
                    excludedProducts = " AND ProductId NOT IN (" + AlwaysConvert.ToList(",", productsToExclude.ToArray()) + ")";
                }
                //ALSO EXCLUDE THESE PRODUCTS FROM GLOBAL DISCOUNTS
                excludeGlobal.AddRange(productsToExclude);
            }

            //FIND ALL DISCOUNTS THAT ARE ASSOCIATED WITH PRODUCTS IN THE BASKET
            StringBuilder categorySql = new StringBuilder();

            categorySql.Append("SELECT DISTINCT CP.ParentId, CP.ParentLevel, CVD.VolumeDiscountId");
            if (groupingMode == GroupingMode.Product)
            {
                categorySql.Append(", CN.CatalogNodeId");
            }
            categorySql.Append(" FROM (ac_BasketItems BI INNER JOIN ac_CatalogNodes CN ON BI.ProductId = CN.CatalogNodeId");
            categorySql.Append(" INNER JOIN ac_CategoryParents CP ON CN.CategoryId = CP.CategoryId");
            categorySql.Append(" INNER JOIN ac_CategoryVolumeDiscounts CVD ON CP.ParentId = CVD.CategoryId)");
            categorySql.Append(" WHERE BI.BasketId = @basketId ");
            categorySql.Append(" AND CN.CatalogNodeTypeId = 1");
            categorySql.Append(excludedProducts);
            //ORDER FROM THE MOST SPECIFIC CATEGORY TO THE LEAST (PARENTLEVEL)
            categorySql.Append(" ORDER BY CP.ParentLevel DESC");
            if (groupingMode == GroupingMode.Product)
            {
                categorySql.Append(", CN.CatalogNodeId ASC");
            }

            //CREATE THE COMMAND
            Database  database = Token.Instance.Database;
            DbCommand command  = database.GetSqlStringCommand(categorySql.ToString());

            database.AddInParameter(command, "@basketId", System.Data.DbType.Int32, basket.BasketId);
            DataSet allDiscounts = database.ExecuteDataSet(command);

            //LOOP ALL DISCOUNTS, BUILD LIST OF POTENTIAL DISCOUNTS THAT COULD APPLY TO USER
            User user = basket.User;

            foreach (DataRow row in allDiscounts.Tables[0].Rows)
            {
                //GET THE DISCOUNTED OBJECT (EITHER PRODUCT OR CATEGORY LEVEL)
                int key;
                if (groupingMode == GroupingMode.Product)
                {
                    key = (int)row[3];
                }
                else
                {
                    key = Convert.ToInt32((byte)row[1]);
                }

                //GET THE LEVEL OF THE CATEGORY (DETERMINES PRECEDENCE)
                int categoryLevel = Convert.ToInt32((byte)row[1]);

                //FIND THE LIST OF POTENTIAL DISCOUNTS FOR THIS KEY
                if (!potentialDiscounts.ContainsKey(key))
                {
                    potentialDiscounts[key] = new List <PotentialDiscount>();
                }
                List <PotentialDiscount> discountGroup = potentialDiscounts[key];

                //DECIDE WHETHER THIS DISCOUNT HAS ENOUGH PRECDENCE TO CHECK
                bool checkDiscount = true;
                if (discountGroup.Count > 0)
                {
                    //THE CURRENT ROW COULD HAVE THE SAME LEVEL AS THE DISCOUNTS ALREADY FOUND
                    if (categoryLevel < discountGroup[0].CategoryLevel)
                    {
                        checkDiscount = false;
                    }
                    //WE DO NOT HAVE TO CHECK FOR LEVEL BEING GREATER, BECAUSE
                    //THE QUERY INCLUDES PARENT LEVEL IN THE ORDERBY CLAUSE
                }

                if (checkDiscount)
                {
                    //THIS COULD BE A VALID DISCOUNT
                    int volumeDiscountId = (int)row[2];
                    //CHECK FOR USER EXCLUSIONS
                    VolumeDiscount v = VolumeDiscountDataSource.Load(volumeDiscountId);
                    if ((v != null) && (v.IsValidForUser(user)))
                    {
                        //THE DISCOUNT IS VALID FOR THIS USER
                        //ADD TO THE LIST OF POTENTIALS
                        PotentialDiscount pd = new PotentialDiscount();
                        pd.CategoryId       = (int)row[0];
                        pd.CategoryLevel    = categoryLevel;
                        pd.VolumeDiscountId = volumeDiscountId;
                        if (groupingMode == GroupingMode.Product)
                        {
                            pd.ProductId = key;
                            //SINCE THERE IS A CATEGORY DISCOUNT, WE DO
                            //NOT WANT TO USE ANY GLOBAL DISCOUNTS FOR THIS PRODUCT
                            excludeGlobal.Add(key);
                        }
                        discountGroup.Add(pd);
                    }
                }
            }

            List <int> globalDiscountProducts = new List <int>();

            if (groupingMode == GroupingMode.Product)
            {
                //CHECK WHETHER ANY PRODUCTS REMAIN IN ORDER THAT ARE ELIGIBLE
                //FOR GLOBAL DISCOUNTS
                foreach (BasketItem item in basket.Items)
                {
                    //MAKE SURE THIS IS A PRODUCT AND IS NOT EXCLUDED FROM GLOBAL DISCOUNT
                    if ((item.ProductId > 0) && (excludeGlobal.IndexOf(item.ProductId) < 0))
                    {
                        //ADD THIS PRODUCT TO THE GLOBAL DISCOUNT LIST (IF NOT ALREADY THERE)
                        if (globalDiscountProducts.IndexOf(item.ProductId) < 0)
                        {
                            globalDiscountProducts.Add(item.ProductId);
                        }
                    }
                }
            }

            //ARE WE CALCULATING DISCOUNTS USING CATEGORY GROUPING MODE?
            //OR ARE THERE ANY PRODUCTS THAT COULD HAVE GLOBAL DISCOUNTS?
            if (groupingMode == GroupingMode.Category || globalDiscountProducts.Count > 0)
            {
                //FIND ANY GLOBAL DISCOUNTS
                VolumeDiscountCollection globalDiscounts = VolumeDiscountDataSource.LoadGlobal();
                if (globalDiscounts.Count > 0)
                {
                    if (groupingMode == GroupingMode.Product)
                    {
                        foreach (int productId in globalDiscountProducts)
                        {
                            potentialDiscounts[productId] = new List <PotentialDiscount>();
                            List <PotentialDiscount> discountGroup = potentialDiscounts[productId];
                            foreach (VolumeDiscount v in globalDiscounts)
                            {
                                //VERIFY USER RESTRICTION ON GLOBAL DISCOUNT
                                if (v.IsValidForUser(user))
                                {
                                    PotentialDiscount pd = new PotentialDiscount();
                                    pd.CategoryId       = 0;
                                    pd.CategoryLevel    = 0;
                                    pd.VolumeDiscountId = v.VolumeDiscountId;
                                    pd.ProductId        = productId;
                                    discountGroup.Add(pd);
                                }
                            }
                        }
                    }
                    else
                    {
                        potentialDiscounts[0] = new List <PotentialDiscount>();
                        List <PotentialDiscount> discountGroup = potentialDiscounts[0];
                        foreach (VolumeDiscount v in globalDiscounts)
                        {
                            //VERIFY USER RESTRICTION ON GLOBAL DISCOUNT
                            if (v.IsValidForUser(user))
                            {
                                PotentialDiscount pd = new PotentialDiscount();
                                pd.CategoryId       = 0;
                                pd.CategoryLevel    = 0;
                                pd.VolumeDiscountId = v.VolumeDiscountId;
                                pd.ProductId        = 0;
                                discountGroup.Add(pd);
                            }
                        }
                    }
                }
            }

            //REMOVE ANY ENTRIES FROM THE LIST THAT HAVE NO DISCOUNTS
            List <int> emptyKeys = new List <int>();

            foreach (int key in potentialDiscounts.Keys)
            {
                if (potentialDiscounts[key].Count == 0)
                {
                    emptyKeys.Add(key);
                }
            }
            foreach (int key in emptyKeys)
            {
                potentialDiscounts.Remove(key);
            }

            //RETURN POTENTIAL DISCOUNTS FOR BASKET
            return(potentialDiscounts);
        }
示例#2
0
        /// <summary>
        /// Get discounts that apply to a product by virtue of category assignment.
        /// </summary>
        /// <param name="productId">The product to check for category discounts</param>
        /// <returns>The discounts that apply to a product</returns>
        private static VolumeDiscountCollection GetCategoryDiscountsForProduct(int productId)
        {
            //FIND ALL PRODUCTS THAT ARE A DESCENDANT OF THE CATEGORY
            StringBuilder categorySql = new StringBuilder();

            categorySql.Append("SELECT DISTINCT CP.ParentLevel,CVD.VolumeDiscountId");
            categorySql.Append(" FROM ((ac_CatalogNodes CN INNER JOIN ac_CategoryParents CP ON CN.CategoryId = CP.CategoryId)");
            categorySql.Append(" INNER JOIN ac_CategoryVolumeDiscounts CVD ON CP.ParentId = CVD.CategoryId)");
            categorySql.Append(" WHERE CN.CatalogNodeId = @productId");
            categorySql.Append(" AND CN.CatalogNodeTypeId = 1");
            categorySql.Append(" ORDER BY CP.ParentLevel DESC");

            //EXECUTE THE QUERY
            Database  database = Token.Instance.Database;
            DbCommand command  = database.GetSqlStringCommand(categorySql.ToString());

            database.AddInParameter(command, "@productId", System.Data.DbType.Int32, productId);

            //BUILD LIST OF VOLUME DISCOUNT IDS APPLICABLE FOR THE USER
            User       user = Token.Instance.User;
            List <int> volumeDiscountIds = new List <int>();
            int        lastLevel         = -1;
            bool       levelChanged      = false;

            using (IDataReader dr = database.ExecuteReader(command))
            {
                while (dr.Read() && !levelChanged)
                {
                    int            thisLevel        = (int)dr.GetByte(0);
                    int            volumeDiscountId = dr.GetInt32(1);
                    VolumeDiscount v = VolumeDiscountDataSource.Load(volumeDiscountId);
                    if (v.IsValidForUser(user))
                    {
                        if ((lastLevel > -1) && (lastLevel != thisLevel))
                        {
                            levelChanged = true;
                        }
                        else
                        {
                            volumeDiscountIds.Add(dr.GetInt32(1));
                            lastLevel = thisLevel;
                        }
                    }
                }
                dr.Close();
            }

            //INITIALIZE THE RETURN SET
            VolumeDiscountCollection discounts = new VolumeDiscountCollection();

            //DID WE FIND DISCOUNTS ON A CATEGORY?
            if (volumeDiscountIds.Count > 0)
            {
                //BUILD THE COLLECTION OF DISCOUNTS
                foreach (int id in volumeDiscountIds)
                {
                    VolumeDiscount v = VolumeDiscountDataSource.Load(id);
                    if (v != null)
                    {
                        discounts.Add(v);
                    }
                }
            }
            else
            {
                //NO DISCOUNT FOUND ON A CATEGORY, RETURN ANY GLOBAL DISCOUNTS
                VolumeDiscountCollection globalDiscounts = VolumeDiscountDataSource.LoadGlobal();
                foreach (VolumeDiscount v in globalDiscounts)
                {
                    if (v.IsValidForUser(user))
                    {
                        discounts.Add(v);
                    }
                }
            }
            //RETURN ANY CATEGORY DISCOUNTS FOUND
            return(discounts);
        }