/// <summary> /// Evaluates the promotions. /// </summary> /// <param name="useCache">if set to <c>true</c> [use cache].</param> /// <param name="context">The context.</param> /// <param name="filter">The filter.</param> /// <returns>Collection of promotions that were applied. Look inside PromotionContext for actual rewards and for items that have been affected by these promotions.</returns> public PromotionItemCollection EvaluatePromotions(bool useCache, PromotionContext context, PromotionFilter filter) { MarketingHelper helper = GetMarketingHelper(useCache); PromotionItemCollection dto = new PromotionItemCollection(helper); // Remove current customer promotion history if we opted to not use cache (which happens during checkout) if (!useCache) { string cacheKey = MarketingCache.CreateCacheKey("MarketingHelper-customer", context.CustomerId.ToString()); MarketingCache.Remove(cacheKey); } return(EvaluatePromotions(context, dto, filter)); }
/// <summary> /// Evaluates the promotions. /// </summary> /// <param name="context">The context.</param> /// <param name="promotions">The promotions.</param> /// <param name="filter">The filter.</param> /// <returns>Collection of promotions that were applied. Look inside PromotionContext for actual rewards and for items /// that have been affected by these promotions.</returns> public PromotionItemCollection EvaluatePromotions(PromotionContext context, PromotionItemCollection promotions, PromotionFilter filter) { // Start checking discounts List <int> rowIndexes = new List <int>(); // Retrieve all the coupons customer entered List <string> coupons = context.Coupons; // Retrieve customer segments, it should be initialized beforehand List <int> segments = context.Segments; // Retrieve customer id, it should be initialized beforehand Guid customerId = context.CustomerId; foreach (PromotionItem item in promotions) { // Set currently executed promotion context.CurrentPromotion = item; // If discount is global and other discount has been applied already, skip it if (item.DataRow.ExclusivityType.Equals(ExclusionType.GlobalLevel) && rowIndexes.Count != 0) { continue; } // Check if it belongs to a group specified if (!String.IsNullOrEmpty(context.TargetGroup) && !context.TargetGroup.Equals(item.DataRow.PromotionGroup, StringComparison.OrdinalIgnoreCase)) { continue; } // Check group exclusivity if (context.ExclusiveGroups.Contains(item.DataRow.PromotionGroup)) { continue; } // Check limits here int currentOrderPromotionCount = context.PromotionResult.GetCount(item.DataRow.PromotionId); // Start with per order limit if (item.DataRow.PerOrderLimit > 0 && currentOrderPromotionCount >= item.DataRow.PerOrderLimit) { continue; } // Check application limit limit, only check when limit is set if (item.DataRow.ApplicationLimit > 0 && item.TotalUsedCount - context.ReservedCount + currentOrderPromotionCount >= item.DataRow.ApplicationLimit) { continue; } // Check customer limit, only check when limit is set and customer id is set if ((item.DataRow.CustomerLimit > 0 && customerId == Guid.Empty) || item.DataRow.CustomerLimit > 0 && item.GetCustomerUsageCount(customerId) - context.ReservedCount + currentOrderPromotionCount >= item.DataRow.CustomerLimit) { continue; } // First do simply checks that will take little time and save us from wasting processor time // ----------------------------------------------------------------------------------------- if (!filter.IncludeInactive) { // Skip if start date is past now if (!item.Campaign.IsActive) { continue; } if (item.Campaign.StartDate > FrameworkContext.Current.CurrentDateTime) { continue; } // Skip if end date is in the past if (item.Campaign.EndDate < FrameworkContext.Current.CurrentDateTime) { continue; } // Skip if start date is past now if (item.DataRow.StartDate > FrameworkContext.Current.CurrentDateTime) { continue; } // Skip if end date is in the past if (item.DataRow.EndDate < FrameworkContext.Current.CurrentDateTime) { continue; } // Check promotion status if (!item.DataRow.Status.Equals(PromotionStatus.Active)) { continue; } } if (!filter.IncludeCoupons) { // Check coupons string couponCode = item.DataRow.CouponCode; if (!String.IsNullOrEmpty(couponCode)) { if (coupons == null) { continue; } bool foundCoupon = false; foreach (string coupon in coupons) { if (couponCode.Equals(coupon, StringComparison.OrdinalIgnoreCase)) { foundCoupon = true; } } if (!foundCoupon) { continue; } } } // Check catalog / node / entry filtering if (context.TargetEntriesSet.Entries.Count > 0) { bool isValid = true; foreach (PromotionEntry entry in context.TargetEntriesSet.Entries) { string catalogEntryId = entry.CatalogEntryCode; string catalogNodeId = entry.CatalogNodeCode; string catalogName = entry.CatalogName; if (!String.IsNullOrEmpty(catalogEntryId) || !String.IsNullOrEmpty(catalogNodeId) || !String.IsNullOrEmpty(catalogName)) { PromotionDto.PromotionConditionRow[] conditions = item.DataRow.GetPromotionConditionRows(); if (conditions != null && conditions.Length > 0) { foreach (PromotionDto.PromotionConditionRow condition in conditions) { if (!String.IsNullOrEmpty(catalogEntryId) && !condition.IsCatalogEntryIdNull() && !condition.CatalogEntryId.Equals(catalogEntryId)) { isValid = false; break; } else if (!String.IsNullOrEmpty(catalogNodeId) && !condition.IsCatalogNodeIdNull() && !condition.CatalogNodeId.Equals(catalogNodeId)) { isValid = false; break; } else if (!String.IsNullOrEmpty(catalogName) && !condition.IsCatalogNameNull() && !condition.CatalogName.Equals(catalogName)) { isValid = false; break; } } if (!isValid) { continue; } } } } if (!isValid) { continue; } } // Start doing more expensive checks here // ----------------------------------------------------------------------------------------- if (!filter.IgnoreSegments) { // Check customer segments, customer should belong to a segment for promotion to apply CampaignDto.CampaignSegmentRow[] segmentRows = item.Campaign.GetCampaignSegmentRows(); // if there are no segments defined assume it applies to everyone if (segmentRows != null && segmentRows.Length > 0) { // customer is not within any segment, so promotion does not apply if (segments == null || segments.Count == 0) { continue; } // start checking segments bool apply = false; foreach (CampaignDto.CampaignSegmentRow row in segmentRows) { if (segments.Contains(row.SegmentId)) { // mark promotion as apply and leave loop apply = true; break; } } // if does not apply continue with a next promotion if (!apply) { continue; } } } if (!filter.IgnoreConditions) { // Validate expressions if (item.Expressions.Count > 0) { bool isValid = true; foreach (ExpressionDto.ExpressionRow expression in item.Expressions) { if (!String.IsNullOrEmpty(expression.ExpressionXml)) { ValidationResult result = ValidateExpression(expression.ApplicationId.ToString() + "-" + expression.Category + "-" + expression.ExpressionId.ToString(), expression.ExpressionXml, context); if (!result.IsValid) { isValid = false; break; } } } if (!isValid) { continue; } } } else { // Create Award manually based on default settings PromotionReward reward = new PromotionReward(PromotionRewardType.EachAffectedEntry, item.DataRow.OfferAmount, item.DataRow.OfferType == 0 ? PromotionRewardAmountType.Percentage : PromotionRewardAmountType.Value); PromotionItemRecord record = new PromotionItemRecord(context.TargetEntriesSet, context.TargetEntriesSet, reward); record.PromotionItem = context.CurrentPromotion; context.PromotionResult.PromotionRecords.Add(record); } if (!filter.IgnorePolicy) { // Validate store policies if (item.PolicyExpressions.Count > 0) { bool isValid = true; foreach (ExpressionDto.ExpressionRow expression in item.PolicyExpressions) { if (!String.IsNullOrEmpty(expression.ExpressionXml)) { ValidationResult result = ValidateExpression(expression.ApplicationId.ToString() + "-" + expression.Category + "-" + expression.ExpressionId.ToString(), expression.ExpressionXml, context); if (!result.IsValid) { isValid = false; break; } } } if (!isValid) { // Invalidates all records added during this evaluation sequence context.RejectRecords(); continue; } } } // Commits all records added during this evaluation sequence context.CommitRecords(); // Apply item rowIndexes.Add(item.RowIndex); // Add item to a group if it is applied if (item.DataRow.ExclusivityType.Equals(ExclusionType.GroupLevel)) { context.ExclusiveGroups.Add(item.DataRow.PromotionGroup); } // Finish processing if global level item has been added if (item.DataRow.ExclusivityType.Equals(ExclusionType.GlobalLevel)) { break; } } // Assign curren promotion to null context.CurrentPromotion = null; return(new PromotionItemCollection(promotions, rowIndexes.ToArray())); }