The ICart object inside the context that is passed as argument to the promotion processor switches back and fourth between SerializableCart and InMemoryOrderGroup.
The SerializableCart has got all the pertinent information needed for me to process the promotions and discounts correctly.
The InMemoryOrderGroup has not got the needed informaiton as it seems to be a cached object containing only a bare minimum of the cart properties.
When is the SerializableCart passed as an argument and when is, instead, the InMemoryOrderGroup object passed? Can somehow force the SerializableCart object to be used or do I have to write a custom PromotionEngine, IOrderGroupExtension etc to get only the SerializableCart type of object?
Also I believe EPiServers promotion/discount system isn't adapted to having multiple LineItems with the same Code/SKU. For instance a drinking cup with a SKU/code but with a extended property that holds the text to be printed on the side.
I.e.
Code: mug-with-print, Quantity: 10, TextToBePrintedOnCup: "EPiServer"
Code: mug-with-print, Quantity: 5, TextToBePrintedOnCup: "Commerce"
In the promotion system there is a lot of examples of just the first item being updated. E.g. EPiServer.Commerce.Order.IOrderGroupExtensions.UpdateManualDiscounts() where there is code that get the LineItem to apply the discount to that use orderForm.GetAllLineItems().FirstOrDefault(li => li.Code == .....).
I want the promotion system to be able to handle order rows with a sku code that is not unique. Does this mean that I need to calculate the discounts not using the default engine and methods or do I need to create custom code for it to work?
Since there is an infinite number of variations, I can't create SKUs for all of them to get unique SKU codes.
Episerver uses InMemoryOrderGroup to evaluate promotions when no real cart is available.
This is the case for several functions in IPromotionEngineExtensions, any function who returns a discounted price or evaluate which promotions affect a Content, they all create an temporary InMemoryOrderGroup and passes it into the IPromotionEngine.
You can of course create a SerializableCart and send it into the IPromotionEngine yourself without using the extension methods and then handle the response manually.
However if your business logic allows it you can in your custom promotion processor check to see if it is an InMemoryOrderGroup and in that case exit early. If you don't have to take Organization or CustomerId into account for those extension methods you call.
Of course I am a bit suspicious to why you should need the Organization or CustomerId to calculate the discount.
The general solution is to have different promotions and use visitor groups to control which promotions are applied for which Organization/Customer.
Thanks Erik for the information on why InMemoryOrderGroup is used and also the solution with supplying the SerializableCart myself.
The business case forces me to access some data that is stored in the Organization object. It's not a pleasing option to copy this to each and every ILineItem.
Besides, with the InMemoryOrderGroup missing all the extended properties and many of the built in system properties, it will not suffice anyway.
With your suggested solution supplying SerializableCart myself, I won't need to put any redundant information into the ILineItem or otherwise.
I have created a custom promotion processor that inherits from the EntryPromotionProcessorBase<> base class.>
In the method Evaluate(IfCompanyPromotionData promotionData, PromotionProcessorContext context) the received cart in context.OrderGroup is of type InMemoryOrderGroup.
The data type is no problem. What is a problem is that it is missing most of the property values (system as well as extended) that is present in the cart (of type SerializableCart).
I need to know the carts Organization or CustomerId fields to be able to correctly calculate the discounts in my business case. This simply isn't possible with a cart missing a lot of the values that are set in the cart.
How can I handle this?
Do I need to calculate this entirely outside of EPiServers promotion engine?