That's a good question. How can I tell?
The promotion getting executed seems to be EPiServer.Commerce.Marketing.Promotions.SpendAmountGetGiftItemsProcessor
The SpendAmountGetGiftItems Class is part of the new promotions system because it's under the EPiServer.Commerce.Marketing.Promotions namespace.
If you're using the built in discounts for getting free gift items, they use a GiftItemFactory. If you want to have custom metafields added to those gift items, the only thing you need to do is inject your own GiftItemFactory that inherits from the epi one. Like such:
public class CustomGiftItemFactory : GiftItemFactory { public CustomGiftItemFactory(IContentLoader contentLoader, IPriceService priceService, IOrderGroupFactory orderGroupFactory) : base(contentLoader, priceService, orderGroupFactory) { } protected override ILineItem CreateGiftLineItem(EntryContentBase entryContent, PromotionProcessorContext processorContext) { var lineItem = base.CreateGiftLineItem(entryContent, processorContext); // Here you have your lineitem where you can populate it with your metafields before returning it to the promotion engine to add it to your cart return lineItem; } }
And don't forget to setup the injection in your container config :)
Thank you Joel, that does indeed work for me when a gift item i added.
I I'm looking a bit ahead, I'm thinking what happens if we decide that we need an extra field on lineitems in the future. In that case, we would need to enrich exisiting line items for all baskets.
Can I hook into the "cart load" somehow, and add some data to lineitems that way? Of course this could hurt performance, but I could check if the lineitem already has the data, and if not, then fetch it and enrich the item.
But where would that hook be?
I'd rather say that you want your own service handling cart adds, so you put a layer on top of epis add to cart. So all your cart operations use your service as a single point of entry and you can add custom fields there. You could use the same service in the CustomGiftItemFactory to populate the metafields needed for your solution.
But yeah, when you're in the future adding a new field you need to do a migration that does the actual column adding, and one that populates all existing lineitems with acceptable values for that field. And that migration should be deployed the same time as the code changes that sets/uses this field, of course :)
One possible solution is to try and load all existing orders/carts, update those lineitem's metafields and save them back.
We do have a CartService which is the single point for our own code. And I can use that for my custom gift item factory as well.
I'm just wondering if there could be other ways in which EPiServer would add items to a cart? Are there more factories I need to override?
Some commerce platforms have the concept of a "pipeline", so whenever f.ex. a line item is fetched, it will pass through this pipeline to ensure that the data is current and valid. I was thinking that the ILineItemValidator or the Workflows would work in a similar fashion? This would eliminate the need for factories, since I could enrich the line item whenever someone requests it.
As far as I know epi doesn't have pipelines such as that, you'll need to build your pipeline/flow manually. However, epi does have the workflows, which basically are a standard implementation of a flow/pipeline. But as soon as you want to derive from them I recommend you build your own flow. The only thing we've experienced is the PromotionEngine creating lineitems outside of our pipeline. Maybe there is something in Commerce Manager that can manually create LineItems, but you should advice the administrators not to touch that :)
As a side note, you'd have the same issue using Workflows with the metafield creation on the GiftItemFactory, so I'd say keep doing your custom implementation.
Using EPiServer Commerce 10.2.3.0
When adding a line item to the cart from our site, we add a few custom properties to the line item.
However, if I set up a discount that gives the user at free gift, then that line item is added without those custom fields, since our own code is not adding the item.
Is there a way for me to always enrich new lines with my custom information?
I have stumbled on the concept of an ILineItemValidator, which seems to be executed for a cart, and I wonder if I should add my data from a custom validator? Even though the name suggests that is not the purpose of the feature.
I've also found some information about "Workflows and activities", but I can't quite figure out if I can simple add my own step to a workflow, and add data to my lineitems there.
Any suggestions are very much appreciated :)