I think we have 2 ways to do that:
1. Update line item price: By this way, we need to do some below steps when validating cart:
2. Update discount amount: By this way, we won't change placed price in every line item. We will only re-update line item discount amount if discount amount > Max discount amount (Regular Price - Sale Price). Here is steps that we need to do when validating cart:
That is my ideas, the option 2 is more simple I think.
@Binh Nguyen: Thank you so much for the idea, I ended up creating a cart extension method to do the check and update the placed price. But it only works fine if I have a single SKU in the cart. Upon having more than 1 SKU it double discounts all line items other than the last one which is very strange.
if (cart.GetFirstForm().Promotions.Any())
{
var currentMarket = ServiceLocator.Current.GetInstance<ICurrentMarket>().GetCurrentMarket();
//Look for a line item promo
PromotionInformation promo = cart.GetFirstForm().Promotions.Where(x => x.DiscountType == DiscountType.LineItem).FirstOrDefault();
if (promo != null)
{
//Create an in memory order group and see the discount
var inMemoryOrderGroup = new InMemoryOrderGroup(currentMarket, ServiceLocator.Current.GetInstance<CurrencyService>().GetCurrentCurrency().CurrencyCode);
foreach (ILineItem lineItem in cart.GetFirstForm().GetAllLineItems())
{
EntryContentBase entry = lineItem.GetEntryContent(ServiceLocator.Current.GetInstance<ReferenceConverter>(), ServiceLocator.Current.GetInstance<IContentLoader>());
decimal currentPlacedPrice = placedPriceUpdater.GetPlacedPrice(entry, lineItem.Quantity, ServiceLocator.Current.GetInstance<CurrentCustomerProfile>().GetCurrentCustomer(), currentMarket.MarketId, ServiceLocator.Current.GetInstance<CurrencyService>().GetCurrentCurrency()).Value.Amount;
//Passing regular price into the promotion engine
lineItem.PlacedPrice = Convert.ToDecimal(lineItem.Properties[Constants.Metadata.LineItem.ListPrice]);
inMemoryOrderGroup.AddLineItem(lineItem);
if (!string.IsNullOrEmpty(promo.CouponCode))
{
inMemoryOrderGroup.GetFirstForm().CouponCodes.Add(promo.CouponCode);
}
var rewards = ServiceLocator.Current.GetInstance<IPromotionEngine>().Run(inMemoryOrderGroup);
if (rewards.Any())
{
RewardDescription reward = rewards.OrderByDescending(x => x.SavedAmount).FirstOrDefault();
decimal promoFinalPrice = reward.Redemptions.FirstOrDefault().AffectedEntries.PriceEntries.Where(x => x.OriginalTotal == Convert.ToDecimal(lineItem.Properties[Constants.Metadata.LineItem.ListPrice])).FirstOrDefault().Price;
if (promoFinalPrice < currentPlacedPrice)
{
lineItem.PlacedPrice = Convert.ToDecimal(lineItem.Properties[Constants.Metadata.LineItem.ListPrice]);
}
else
{
lineItem.PlacedPrice = currentPlacedPrice;
lineItem.TrySetDiscountValue(x => x.EntryAmount, 0.0M);
var entryPromo = promo.Entries.Where(x => x.EntryCode == lineItem.Code).FirstOrDefault();
entryPromo.SavedAmount = 0.0M;
}
}
else
{
lineItem.PlacedPrice = currentPlacedPrice;
}
}
}
}
Here is an sample: https://www.screencast.com/t/ZMaw4YOJSj
The customer disocunt was 20% and the Epi coupon was 15%. In the image, you can see that all line items are being double discounted other than the last line item. I also had a look at the LineItem table and I see that LineItemDiscountAmount is populated with $6.66 for Item 1 and $4.32 for Item 2.
The problem here is you ran promotion in the loop. For every iterator, you added more 1 line item and get all discounts for all items in the memory order. So the discounts retrieved may be not proper if you don't have all line items in the order.
Hi,
I am using Commerce 12.15, I have a requirment where I need to compare between the sale price and the promotion price (All lineitem promotions only). The logic is as follows:
An item 001 has a Regular price $10.00, the sale price is $6.00. Now they want me to apply the discount on the regular price and see if it is even lower than the current sale price.
I am able to check if the line item has an applicable promotion lower than the sale price, but I am not sure where I need to add the logic to find the lowest price should be inserted.
My implementation so far is as follows:
I am overriding UpdatePlacedPrice(ILineItem lineItem, CustomerContact customerContact, MarketId market, Currency currency, Action<ILineItem, ValidationIssue> onValidationError) from DefaultPlacedPriceProcessor class.
There I get the current shopping cart and use the lineitems in the cart to create a InMemomryOrderGroup and apply the coupon. This gives me the collection of rewards, which I can use to compare against the sale price. I have created 3 metafields on the line item level as well, Original Price ex: $10.00, SalePrice: $6.00 and $PromoPrice $xx.xx. Now I want to check the lowest price between SalePrice and PromoPrice. But the promotions engine is always discounting on the placed price, so this leads to a double discount $6.00 being further discounted. I know this is the default behaviour of EPi, but I am looking for ideas or suggestions to overcome this.
Below is my sample code :