public static VolumeDiscount Load(Int32 volumeDiscountId, bool useCache) { if (volumeDiscountId == 0) { return(null); } VolumeDiscount volumeDiscount = null; string key = "VolumeDiscount_" + volumeDiscountId.ToString(); if (useCache) { volumeDiscount = ContextCache.GetObject(key) as VolumeDiscount; if (volumeDiscount != null) { return(volumeDiscount); } } volumeDiscount = new VolumeDiscount(); if (volumeDiscount.Load(volumeDiscountId)) { if (useCache) { ContextCache.SetObject(key, volumeDiscount); } return(volumeDiscount); } return(null); }
/// <summary> /// Creates a copy of a volume discount /// </summary> /// <param name="volumeDiscountId">Id of the volume discount of which to create a copy</param> /// <param name="deepCopy">If <b>true</b> all child references are also copied</param> /// <returns>Copy of the given volume discount</returns> public static VolumeDiscount Copy(int volumeDiscountId, bool deepCopy) { //LOAD COPY (NO CACHE) VolumeDiscount source = new VolumeDiscount(); if (source.Load(volumeDiscountId)) { //IF DEEP COPY, RESET ALL CHILD REFERENCES if (deepCopy) { foreach (VolumeDiscountLevel child in source.Levels) { child.VolumeDiscountLevelId = 0; child.VolumeDiscountId = 0; } foreach (VolumeDiscountGroup child in source.VolumeDiscountGroups) { child.VolumeDiscountId = 0; } foreach (CategoryVolumeDiscount child in source.CategoryVolumeDiscounts) { child.VolumeDiscountId = 0; } foreach (ProductVolumeDiscount child in source.ProductVolumeDiscounts) { child.VolumeDiscountId = 0; } } source.VolumeDiscountId = 0; source.Save(); return(source); } return(null); }
public static bool Delete(Int32 volumeDiscountId) { VolumeDiscount volumeDiscount = new VolumeDiscount(); if (volumeDiscount.Load(volumeDiscountId)) { return(volumeDiscount.Delete()); } return(false); }
/// <summary> /// Loads the given VolumeDiscount object from the given database data reader. /// </summary> /// <param name="volumeDiscount">The VolumeDiscount object to load.</param> /// <param name="dr">The database data reader to read data from.</param> public static void LoadDataReader(VolumeDiscount volumeDiscount, IDataReader dr) { //SET FIELDS FROM ROW DATA volumeDiscount.VolumeDiscountId = dr.GetInt32(0); volumeDiscount.StoreId = dr.GetInt32(1); volumeDiscount.Name = dr.GetString(2); volumeDiscount.IsValueBased = dr.GetBoolean(3); volumeDiscount.IsGlobal = dr.GetBoolean(4); volumeDiscount.IsDirty = false; }
public static VolumeDiscountCollection LoadForGroup(Int32 groupId, int maximumRows, int startRowIndex, string sortExpression) { //CREATE THE DYNAMIC SQL TO LOAD OBJECT StringBuilder selectQuery = new StringBuilder(); selectQuery.Append("SELECT"); if (maximumRows > 0) { selectQuery.Append(" TOP " + (startRowIndex + maximumRows).ToString()); } selectQuery.Append(" " + VolumeDiscount.GetColumnNames("ac_VolumeDiscounts")); selectQuery.Append(" FROM ac_VolumeDiscounts, ac_VolumeDiscountGroups"); selectQuery.Append(" WHERE ac_VolumeDiscounts.VolumeDiscountId = ac_VolumeDiscountGroups.VolumeDiscountId"); selectQuery.Append(" AND ac_VolumeDiscountGroups.GroupId = @groupId"); selectQuery.Append(" AND StoreId = @storeId"); if (!string.IsNullOrEmpty(sortExpression)) { selectQuery.Append(" ORDER BY " + sortExpression); } Database database = Token.Instance.Database; DbCommand selectCommand = database.GetSqlStringCommand(selectQuery.ToString()); database.AddInParameter(selectCommand, "@groupId", System.Data.DbType.Int32, groupId); database.AddInParameter(selectCommand, "@storeId", System.Data.DbType.Int32, Token.Instance.StoreId); //EXECUTE THE COMMAND VolumeDiscountCollection results = new VolumeDiscountCollection(); int thisIndex = 0; int rowCount = 0; using (IDataReader dr = database.ExecuteReader(selectCommand)) { while (dr.Read() && ((maximumRows < 1) || (rowCount < maximumRows))) { if (thisIndex >= startRowIndex) { VolumeDiscount volumeDiscount = new VolumeDiscount(); VolumeDiscount.LoadDataReader(volumeDiscount, dr); results.Add(volumeDiscount); rowCount++; } thisIndex++; } dr.Close(); } return(results); }
public static VolumeDiscountCollection LoadForCriteria(string sqlCriteria, int maximumRows, int startRowIndex, string sortExpression) { //CREATE THE DYNAMIC SQL TO LOAD OBJECT StringBuilder selectQuery = new StringBuilder(); selectQuery.Append("SELECT"); if (maximumRows > 0) { selectQuery.Append(" TOP " + (startRowIndex + maximumRows).ToString()); } selectQuery.Append(" " + VolumeDiscount.GetColumnNames(string.Empty)); selectQuery.Append(" FROM ac_VolumeDiscounts"); string whereClause = string.IsNullOrEmpty(sqlCriteria) ? string.Empty : " WHERE " + sqlCriteria; selectQuery.Append(whereClause); if (!string.IsNullOrEmpty(sortExpression)) { selectQuery.Append(" ORDER BY " + sortExpression); } Database database = Token.Instance.Database; DbCommand selectCommand = database.GetSqlStringCommand(selectQuery.ToString()); //EXECUTE THE COMMAND VolumeDiscountCollection results = new VolumeDiscountCollection(); int thisIndex = 0; int rowCount = 0; using (IDataReader dr = database.ExecuteReader(selectCommand)) { while (dr.Read() && ((maximumRows < 1) || (rowCount < maximumRows))) { if (thisIndex >= startRowIndex) { VolumeDiscount volumeDiscount = new VolumeDiscount(); VolumeDiscount.LoadDataReader(volumeDiscount, dr); results.Add(volumeDiscount); rowCount++; } thisIndex++; } dr.Close(); } return(results); }
/// <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); }
private static LSDecimal Calculate_LineItemMode(Basket basket) { //KEEP TRACK OF TOTAL DISCOUNT APPLIED LSDecimal totalDiscount = 0; //CLEAR EXISTING DISCOUNTS FROM THE BASKET ClearExistingDiscounts(basket); //BUILD A LIST OF PRODUCTS THAT HAVE DISCOUNTS SPECIFICALLY APPLIED //THESE PRODUCTS CANNOT RECEIVE ANY FURTHER DISCOUNTS List <int> productsToExclude = new List <int>(); //INITIALLY POPULATE THE LIST WITH ANY GIFT CERTIFICATE PRODUCT IS AS THESE //PRODUCTS ARE NOT ALLOWED TO BE DISCOUNTED productsToExclude.AddRange(DiscountCalculator.GetGiftCertificateProductIds(basket.BasketId)); //CALCULATE THE PRODUCT LEVEL DISCOUNTS totalDiscount += CalculateProductDiscounts(basket, productsToExclude); //GET POTENTIAL PRODUCT DISCOUNTS Dictionary <int, List <PotentialDiscount> > potentialDiscounts = DiscountCalculator.GetPotentialDiscounts(basket, productsToExclude, GroupingMode.Product); //BUILD A QUANTITY AND VALUE LOOKUP TABLE, IF NEEDED TO COMBINE OPTIONS Dictionary <int, int> productQuantityLookup = null; Dictionary <int, LSDecimal> productValueLookup = null; bool combineVariantsInLineItemDiscountMode = Store.GetCachedSettings().CombineVariantsInLineItemDiscountMode; if (combineVariantsInLineItemDiscountMode) { productQuantityLookup = new Dictionary <int, int>(); productValueLookup = new Dictionary <int, LSDecimal>(); foreach (BasketItem bi in basket.Items) { if (productQuantityLookup.ContainsKey(bi.ProductId)) { productQuantityLookup[bi.ProductId] += bi.Quantity; productValueLookup[bi.ProductId] += bi.ExtendedPrice; } else { productQuantityLookup[bi.ProductId] = bi.Quantity; productValueLookup[bi.ProductId] = bi.ExtendedPrice; } } } //LOOP BASKET ITEMS List <BasketItem> newItems = new List <BasketItem>(); foreach (BasketItem bi in basket.Items) { //SEE WHETHER THIS PRODUCT HAS ANY POTENTIAL DISCOUNTS if (potentialDiscounts.ContainsKey(bi.ProductId)) { //GET THE POTENTIAL DISCOUNTS FOR THIS PRODUCT List <PotentialDiscount> productDiscounts = potentialDiscounts[bi.ProductId]; //FIND THE BEST DISCOUNT VolumeDiscount appliedDiscount = null; LSDecimal discountAmount = -1; for (int i = 0; i < productDiscounts.Count; i++) { VolumeDiscount tempDiscount = VolumeDiscountDataSource.Load(productDiscounts[i].VolumeDiscountId); //DETERMINE THE QUANTITY USED TO CALCULATE DISCOUNT int totalProductQuantity; LSDecimal totalProductValue; if (combineVariantsInLineItemDiscountMode) { totalProductQuantity = productQuantityLookup[bi.ProductId]; totalProductValue = productValueLookup[bi.ProductId]; } else { totalProductQuantity = bi.Quantity; totalProductValue = bi.ExtendedPrice; } //CHECK THIS DISCOUNT AMOUNT LSDecimal tempDiscountAmount = tempDiscount.CalculateDiscount(bi.Quantity, totalProductQuantity, bi.ExtendedPrice, totalProductValue); //SEE WHETHER THIS CALCULATED DISCOUNT IS THE GREATEST VALUE if (tempDiscountAmount > discountAmount) { //THIS DISCOUNT HAS A HIGHER VALUE THAN THE LAST TESTED //MAKE THIS THE APPLIED DISCOUNT discountAmount = tempDiscountAmount; appliedDiscount = tempDiscount; } } //CREATE THE DISCOUNT ITEM IF REQUIRED if (discountAmount > 0) { //DISCOUNT AMOUNT SHOULD NOT BE GREATER THEN PARENT ITEM TOTAL if (discountAmount > bi.ExtendedPrice) { discountAmount = bi.ExtendedPrice; } BasketItem discountLineItem = new BasketItem(); discountLineItem.BasketId = basket.BasketId; discountLineItem.OrderItemType = OrderItemType.Discount; discountLineItem.ParentItemId = bi.BasketItemId; discountLineItem.BasketShipmentId = bi.BasketShipmentId; discountLineItem.Name = appliedDiscount.Name; discountLineItem.Sku = appliedDiscount.VolumeDiscountId.ToString(); discountLineItem.Price = (-1 * discountAmount); discountLineItem.Quantity = 1; //bi.Quantity; discountLineItem.TaxCodeId = bi.TaxCodeId; discountLineItem.Shippable = bi.Shippable; newItems.Add(discountLineItem); totalDiscount += discountAmount; } } } //ADD DISCOUNT ITEMS TO BASKET foreach (BasketItem bi in newItems) { basket.Items.Add(bi); bi.Save(); } //RETURN THE TOTAL DISCOUNT APPLIED return(totalDiscount); }
/// <summary> /// Calculates any product specific discounts for the basket /// </summary> /// <param name="basket">Basket to calculate discounts for</param> /// <param name="productsToExclude">Any products to exclude from discounting</param> /// <returns>The total discount applied to the basket</returns> private static LSDecimal CalculateProductDiscounts(Basket basket, List <int> productsToExclude) { LSDecimal totalDiscount = 0; //GET ALL PRODUCTS FROM THE BASKET THAT HAVE DISCOUNTS DIRECTLY ASSOCIATED //TODO: UPDATE THE METHOD BELOW TO FACTOR IN THE COMBINE VARIANTS IN LINE ITEM DISCOUNT MODE SETTING DiscountedBasketProduct[] discountedItems = DiscountCalculator.GetDiscountedBasketProducts(basket.BasketId, productsToExclude); if (discountedItems != null && discountedItems.Length > 0) { //EVALUATE EACH ITEM TO SEE WHETHER THE PRODUCT DISCOUNT APPLIES foreach (DiscountedBasketProduct discountedProduct in discountedItems) { VolumeDiscount appliedDiscount = null; LSDecimal discountAmount = -1; //LOOP ALL AVAILABLE DISCOUNTS AND FIND THE BEST ONE VolumeDiscountCollection availableDiscounts = VolumeDiscountDataSource.LoadForProduct(discountedProduct.ProductId); foreach (VolumeDiscount testDiscount in availableDiscounts) { if (testDiscount.IsValidForUser(basket.User)) { LSDecimal tempDiscountAmount = testDiscount.CalculateDiscount(discountedProduct.Quantity, discountedProduct.Quantity, discountedProduct.ExtendedPrice, discountedProduct.ExtendedPrice); if (tempDiscountAmount > discountAmount) { discountAmount = tempDiscountAmount; appliedDiscount = testDiscount; } } } //CHECK WHETHER A DISCOUNT APPLIES TO THIS PRODUCT FOR THIS USER if (appliedDiscount != null) { //productsToExclude.Add(discountedProduct.ProductId); List <BasketItem> newItems = new List <BasketItem>(); //LOOP ALL ITEMS IN BASKET, CALCULATE DISCOUNT FOR MATCHING PRODUCTS foreach (BasketItem basketItem in basket.Items) { if (basketItem.ProductId == discountedProduct.ProductId) { //THIS IS A DISCOUNTED PRODUCT, CREATE THE DISCOUNT LINE ITEM discountAmount = appliedDiscount.CalculateDiscount(basketItem.Quantity, discountedProduct.Quantity, basketItem.ExtendedPrice, discountedProduct.ExtendedPrice); if (discountAmount > 0) { //DISCOUNT AMOUNT SHOULD NOT BE GREATER THEN PARENT ITEM TOTAL if (discountAmount > basketItem.ExtendedPrice) { discountAmount = basketItem.ExtendedPrice; } //DISCOUNT MUST BE ADJUSTED FOR OPTIONS THAT ARE GROUPED BasketItem discountLineItem = new BasketItem(); discountLineItem.BasketId = basket.BasketId; discountLineItem.OrderItemType = OrderItemType.Discount; discountLineItem.ParentItemId = basketItem.BasketItemId; discountLineItem.BasketShipmentId = basketItem.BasketShipmentId; discountLineItem.Name = appliedDiscount.Name; discountLineItem.Sku = appliedDiscount.VolumeDiscountId.ToString(); discountLineItem.Price = (-1 * discountAmount); discountLineItem.Quantity = 1; // basketItem.Quantity; discountLineItem.TaxCodeId = basketItem.TaxCodeId; discountLineItem.Shippable = basketItem.Shippable; discountLineItem.Save(); newItems.Add(discountLineItem); totalDiscount += discountAmount; } } } //ADD ANY NEW ITEMS TO THE BASKET COLLECTION foreach (BasketItem basketItem in newItems) { basket.Items.Add(basketItem); } //AT LEAST ONE DISCOUNT WAS APPLICABLE TO THIS USER //ADD THIS PRODUCT TO EXCLUDE LIST if (productsToExclude.IndexOf(discountedProduct.ProductId) < 0) { productsToExclude.Add(discountedProduct.ProductId); } } } } return(totalDiscount); }
private static LSDecimal Calculate_GroupingMode(Basket basket) { //KEEP TRACK OF TOTAL DISCOUNT APPLIED LSDecimal totalDiscount = 0; //CLEAR EXISTING DISCOUNTS FROM THE BASKET ClearExistingDiscounts(basket); //BUILD A LIST OF PRODUCTS THAT HAVE DISCOUNTS SPECIFICALLY APPLIED //THESE PRODUCTS CANNOT RECEIVE ANY FURTHER DISCOUNTS List <int> productsToExclude = new List <int>(); //INITIALLY POPULATE THE LIST WITH ANY GIFT CERTIFICATE PRODUCT IS AS THESE //PRODUCTS ARE NOT ALLOWED TO BE DISCOUNTED productsToExclude.AddRange(DiscountCalculator.GetGiftCertificateProductIds(basket.BasketId)); //CALCULATE THE PRODUCT LEVEL DISCOUNTS totalDiscount += CalculateProductDiscounts(basket, productsToExclude); //GET POTENTIAL CATEGORY DISCOUNTS //THE DICTIONARY KEY WILL BE CATEGORY LEVEL //POTENTIAL DISCOUNTS ARE THOSE THAT COULD APPLY AT THE SAME SPECIFICITY //THE POTENTIAL DISCOUNTS ARE ORDERED FROM MOST SPECIFIC CATEGORY LEVEL TO LEAST Dictionary <int, List <PotentialDiscount> > potentialDiscounts = DiscountCalculator.GetPotentialDiscounts(basket, productsToExclude, GroupingMode.Category); //LOOP THE DISCOUNTED CATEGORIES //WE HAVE TO CHECK ALL POTENTIAL DISCOUNTS AT EACH CATEGORY LEVEL //TO DETERMINE WHICH ONE TO APPLY List <BasketItem> newItems = new List <BasketItem>(); foreach (int categoryLevel in potentialDiscounts.Keys) { //IF WE FIND A DISCOUNT AT THIS LEVEL, IT SHOULD BE APPLIED, THEN WE //SHOULD RECHECK DISCOUNTS AT THIS LEVEL TO SEE IF ANY OTHERS APPLY bool recheckThisLevel = false; List <int> appliedCategories = new List <int>(); do { LSDecimal appliedDiscountAmount = -1; VolumeDiscount appliedDiscount = null; int appliedCategoryId = 0; List <PotentialDiscount> discountGroup = potentialDiscounts[categoryLevel]; foreach (PotentialDiscount pd in discountGroup) { if (appliedCategories.IndexOf(pd.CategoryId) < 0) { //GET ALL BASKET ITEMS ELIGIBLE FOR DISCOUNT IN THIS CATEGORY BasketItemCollection eligibleItems = DiscountCalculator.GetCategoryItems(pd.CategoryId, basket, productsToExclude); //TOTAL UP ITEMS FOR GROUPING MODE int totalQuantity = eligibleItems.TotalQuantity(); if (totalQuantity > 0) { LSDecimal totalPrice = eligibleItems.TotalPrice(); VolumeDiscount tempDiscount = VolumeDiscountDataSource.Load(pd.VolumeDiscountId); //JUST USE TOTALS TO DETERMINE OVERALL DISCOUNT LSDecimal tempDiscountAmount = tempDiscount.CalculateDiscount(totalQuantity, totalQuantity, totalPrice, totalPrice); if (tempDiscountAmount > appliedDiscountAmount) { appliedDiscountAmount = tempDiscountAmount; appliedDiscount = tempDiscount; appliedCategoryId = pd.CategoryId; } } } } //SEE WHETHER WE FOUND A DISCOUNT AT THIS LEVEL if (appliedDiscount != null) { //GET ALL BASKET ITEMS ELIGIBLE FOR DISCOUNT IN THIS CATEGORY BasketItemCollection eligibleItems = DiscountCalculator.GetCategoryItems(appliedCategoryId, basket, productsToExclude); //TOTAL UP ITEMS FOR GROUPING MODE int totalQuantity = eligibleItems.TotalQuantity(); LSDecimal totalPrice = eligibleItems.TotalPrice(); //LOOP ALL BASKET ITEMS TO ADD DISCOUNTS TO BASKET foreach (BasketItem bi in eligibleItems) { LSDecimal discountAmount = appliedDiscount.CalculateDiscount(bi.Quantity, totalQuantity, bi.ExtendedPrice, totalPrice); if (discountAmount > 0) { //DISCOUNT AMOUNT SHOULD NOT BE GREATER THEN PARENT ITEM TOTAL if (discountAmount > bi.ExtendedPrice) { discountAmount = bi.ExtendedPrice; } //DISCOUNT MUST BE ADJUSTED FOR OPTIONS THAT ARE GROUPED BasketItem discountLineItem = new BasketItem(); discountLineItem.BasketId = basket.BasketId; discountLineItem.OrderItemType = OrderItemType.Discount; discountLineItem.ParentItemId = bi.BasketItemId; discountLineItem.BasketShipmentId = bi.BasketShipmentId; discountLineItem.Name = appliedDiscount.Name; discountLineItem.Sku = appliedDiscount.VolumeDiscountId.ToString(); discountLineItem.Price = (-1 * discountAmount); discountLineItem.Quantity = 1; //bi.Quantity; discountLineItem.TaxCodeId = bi.TaxCodeId; discountLineItem.Shippable = bi.Shippable; basket.Items.Add(discountLineItem); discountLineItem.Save(); totalDiscount += discountAmount; } if (productsToExclude.IndexOf(bi.ProductId) < 0) { productsToExclude.Add(bi.ProductId); } } } //IF A CATEGORY DISCOUNT WAS APPLIED //AND THERE IS MORE THAN ONE DISCOUNT AT THIS LEVEL, //WE MUST RECHECK THIS LEVEL recheckThisLevel = ((appliedCategoryId > 0) && (potentialDiscounts[categoryLevel].Count > 1)); } while (recheckThisLevel); } //ADD DISCOUNT ITEMS TO BASKET foreach (BasketItem bi in newItems) { basket.Items.Add(bi); bi.Save(); } //RETURN THE CALCULATED DISCOUNT return(totalDiscount); }
public static SaveResult Update(VolumeDiscount volumeDiscount) { return(volumeDiscount.Save()); }
public static SaveResult Insert(VolumeDiscount volumeDiscount) { return(volumeDiscount.Save()); }
public static bool Delete(VolumeDiscount volumeDiscount) { return(volumeDiscount.Delete()); }
/// <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); }