Multiple Delivery Calculations – Sitecore Commerce

While working with one of the clients recently, we had to implement a product-specific delivery calculation. Certain products sold online, are delivered by the company itself and they have fix delivery charges for each region. While certain products(depending on the size/nature) are delivered through other courier services. Since the delivery charges can differ depending on the courier service, we have to calculate/fetch delivery charges for particular products.

Let’s say a customer adds two products to the cart

  1. Bluetooth Speaker
  2. Baby Cart

Since speakers are delivered by the company itself, we use the internal delivery fee using a delivery fee book. For baby-cart, we integrate to the external courier delivery fee service. For the sake of this article, I am calling Speaker as Internal product while baby-cart as external product.

DeliveryFlow

In commerce engine solution we have a feature called fulfilment, this feature has CalculateCartDeliveryBlock which calculates the delivery fee for internal products. This block is configured inside ICalculateCartPipeline of Sitecore. ConfigureSitecore.cs below

                .ConfigurePipeline<ICalculateCartPipeline>(configure => configure
                      .Add<CalculateCartDeliveryBlock>().After<CalculateCartSubTotalsBlock>(), order: 1001)

 

We also extended this CalculateCartDeliveryBlock in a way that it calls either internal calculation for a product or calls the external API to get the delivery fee depending on the nature of the product.

This is how the block code looks like. The actual code is little different, I made it simpler to demonstrate how we can achieve this.

    [PipelineDisplayName(DeliveryConstants.Pipelines.Blocks.CalculateCartLinesDeliveryBlock)]
    public class CalculateCartDeliveryBlock : PipelineBlock<Cart, Cart, CommercePipelineExecutionContext>
    {
        public CalculateCartDeliveryBlock()
          : base(null)
        {
            GetDeliveryFeeForDeliveryTypeCommand = getDeliveryFeeForDeliveryTypeCommand;
        }

        /// <summary>
        /// Runs the specified argument.
        /// </summary>
        /// <param name="cart">The argument.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public override async Task<Cart> Run(Cart cart, CommercePipelineExecutionContext context)
        {
            Condition.Requires(cart).IsNotNull($"{Name}: The cart cannot be null.");
            Condition.Requires(cart.Lines).IsNotNull($"{Name}: The cart lines cannot be null.");
            
            if (!cart.HasComponent<PhysicalFulfillmentComponent>())
            {
                context.Logger.LogDebug($"{Name} - No cart fulfillment component");
                return cart;
            }

            var cartDeliveryFeeComponent = cart.GetComponent<CartDeliveryFeeComponent>();

            foreach (var cartLine in cart.Lines)
            {
                var fulfillmentComponent = cart.GetComponent<PhysicalFulfillmentComponent>();
                Money deliveryFee;
                //Extension method which returns true false
                //based on certain properties of a product
                if (cartLine.IsInternal()) 
                {
                    //internalDeliveryFeeCommand injected as dependency
                    deliveryFee = await internalDeliveryFeeCommand().Process(context.CommerceContext, cart);
                }
                else
                {
                    deliveryFee = await new externalDeliveryFeeCommand().Process(context.CommerceContext, cart);
                }

                // +Operator overloaded
                cartDeliveryFeeComponent.DeliveryCharge = cartDeliveryFeeComponent.DeliveryCharge + deliveryFee; 
            }
            
            return cart;
        }
    }

Few facts about the code which are not obvious here

  1. We add up all the delivery fee for all the products and show it to the customer
  2. GetExternalDeliveryFeeCommand calls the external API to get the delivery fee

 

Putting together all the pieces

DeliverCalculatinoFlow

Leave a Reply