Add to cart when there is no price on sellable item- Item is not purchasable

There might be a situation when you don’t have any price defined on a sellable item and you still want the ability to Add To Cart. If you are not well across how pricing works in Sitecore Experience Commerce(SXC), please have a look at this article from Andrew Sutherland.

In a nutshell, the pricing calculation works from Price Book to List Price. If there are price cards defined on a sellable item, that price is used but if there is no price card, ListPrice defined on a sellable item is used.

If your eCommerce website has the option of Contact To Purchase, you might end up having no prices defined(nor price cards neither list price).  In such scenarios, you will get this error  while trying to add to cart

Item ‘item name’ is not purchasable.

At this stage, you have two options either ask your Content Author to add List Price as $0.00 which doesn’t reflect the actual state of the system or extend Sitecore Commerce with the ability to AddToCart without any price.

If you trace down the origin of the above error you will find ValidateCartLinePrice inside a pipeline in catalog plugin

Pipeline

 

If you see the logic inside this block, it will look for money policy that gets added to a sellable item if there is a price card or list price present on the item.

Block

 

So to enable AddToCart with no price, I started looking into the pipeline which deals with List price. I found ICalculateSellableItemListPricePipeline which calls a block CalculateSellableItemListPriceBlock.

CalcPriceBlock

 

This block would leave the list price as null if it is not defined on a sellable item. And I ended up adding a custom block after this block to be able to set List Price to 0.00 inside the cart.

ConfigureSitecore.cs to configure the block

           .ConfigurePipeline<ICalculateSellableItemListPricePipeline>(configure => configure
               .Add<CalculateMissingListPriceBlock>().After<CalculateSellableItemListPriceBlock>())

CalculateMissingListPriceBlock.cs looks like

    public class CalculateMissingListPriceBlock : PipelineBlock<SellableItem, SellableItem, CommercePipelineExecutionContext>
    {
        public override Task<SellableItem> Run(SellableItem arg, CommercePipelineExecutionContext context)
        {
            return Task.Run(() =>
            {
                CalculateMissingPrice(arg, context);
                return arg;
            });
        }
        
        private void CalculateMissingPrice(SellableItem item, CommercePipelineExecutionContext context)
        {
            if (item.ListPrice == null)
            {
                context.Logger.LogInformation($"{nameof(CalculateMissingListPriceBlock)} {item.FriendlyId} list price is null, zero price will be used");

                item.ListPrice = new Money(context.CommerceContext.CurrentCurrency(), 0);
            }
        }
    }

 

 

Leave a Reply