+1-888-365-2779
Try Now
More in this section

Forums / Ecommerce / Calculating Different Shipping cost tiers based on Cart Total

Calculating Different Shipping cost tiers based on Cart Total

5 posts, 0 answered
  1. Tim
    Tim  avatar
    34 posts
    Registered:
    16 Oct 2012
    11 Jun 2013
    Link to this post
    I see that I can create different shipping methods e.g.  $1-to-$100 = 10% of total,
    and another $101-to-$200 = %8 of total.

    But this makes the customer to pick from the right option (which seems very wrong).

    I'd like to keep the range totals and percents in the configurable backend area of sitefinity so my endCustomer can change them with calling a developer to change code.

    I'm thinking my approach is to Hide the options (make them inactive?)   get my hooks in "somewhere" to see which option applies to the current cart and apply the correct shipping amount to the cart.
     
    This feels like something someone must have done before.  HeadStart or pointers to accomplish what I am trying to do ? 

    Thanks,
    Tim
  2. Peter
    Peter avatar
    36 posts
    Registered:
    03 Oct 2016
    12 Jun 2013
    Link to this post
    Hi Tim,

    Let me try to make sure I have understand you correctly. If I have understood you correctly, you want the user to be charged with the right option automatically.

    An important thing to say here is that by default we display only the shipping methods that are applicable for the current cart, so we don't display all available, but only those that are applicable in the context of the currently processed cart.

    If in your case, you will always have one applicable method based on the weight of the amount to be shipped, this will be the only one displayed by the system and displayed by it.

    Just in case, I haven't understood you correctly, I will send you some code on how you can easily get all the applicable methods manually as well. There is a service called EcommerceShippingMethodService, located in the Telerik.Sitefinity.Modules.Ecommerce.BusinessServices.Shipping.Implementations namespace.

    There is a public virtual method called GetApplicableShippingMethods, which you can use to get all shipping methods applicable for the current cart:

    public virtual IQueryable<IShippingResponse> GetApplicableShippingMethods(CheckoutState checkoutStateCartOrder cartOrder) 

    Please let me know if I am getting your requirement correctly and if you need additional assistance or questions here.

    Regards,
    Peter
    Telerik
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. Tim
    Tim  avatar
    34 posts
    Registered:
    16 Oct 2012
    12 Jun 2013 in reply to Peter
    Link to this post
    Thanks for the explanation.  I now understand more about the shipping options, but the options aren't quite what I need.

    Based on Total Price, I need to apply a different Percentage (the option only allow for a fixed price (not a percent).

    I thought I could hook into the OnEcommerceCheckoutPageChanging and calculate shipping, but it looks like the shipping option gets there first.  

    Can I update the shipping methods on the fly ?  e.g. Hook int the page change event 0, see what Price range I am in; calculate the correct shipping amount and apply it to the shipping option ?    

    Write my own shipping Carrier?  I've read the documentation, but have seen an example of hooking one up.

    Thanks for you insight!
    Tim
  4. Peter
    Peter avatar
    36 posts
    Registered:
    03 Oct 2016
    14 Jun 2013
    Link to this post
    Hi Tim,

    Like most of the shipping carriers (UPS and FedEx), our shipping logic is based on the physical properties of the shopping cart like dimensions and weight and not on the monetary properties of the products.

    So to achieve you shipping price you will have to extend the system's default behavior. Here is a general overview of the process.

    1) You have to create a ShippingMethod with a custom field to store the shipping percentage rate for the method. You can name the custom field - ShippingPriceProcentage. Here is more info on that (link here)

    2) That field won't be accessible through the UI, so to allow the editors to enter the ShippingPricePercentage, you will have to add a custom backend control, configuration or other interface to allow the back-end users to enter the ShippingPricePercentage for every shipping method they will manage.

    3) The next thing you will need to solve is to create a class that inherits from ShippingCalculatorBase class located in the Telerik.Sitefinity.Modules.Ecommerce.Shipping.Business.Calculators namespace. You would need to add a new metod public GenericShippingResponse Calculate(ShippingMethod shippingMethod, CartOrder cartOrder, string[] parms) - this is the same method we use in ShippingcalculatorByWeight and you will need to implemetn somethign similar, but calcualting percentage of the price. Here is the code we use, so you can use it as an example:

    using System;
    using System.Globalization;
    using System.Linq;
    using Telerik.Sitefinity.Ecommerce.Orders.Model;
    using Telerik.Sitefinity.Ecommerce.Shipping.Model;
    using Telerik.Sitefinity.Modules.Ecommerce.Shipping.Interfaces;
     
    namespace Telerik.Sitefinity.Modules.Ecommerce.Shipping.Business.Calculators
    {
        internal class ShippingCalculatorByWeight : ShippingCalculatorBase, IOfflineShippingCalculator
        {
            public GenericShippingResponse Calculate(ShippingMethod shippingMethod, CartOrder cartOrder, string[] parms)
            {
                if (parms.Length != 4)
                {
                    return null;
                }
     
                if (IsShippingDestinationWithinShippingArea(shippingMethod, cartOrder) == false)
                {
                    return null;
                }
     
                double minimumWeight = String.IsNullOrWhiteSpace(parms[1]) ? double.MinValue : Double.Parse(parms[1], CultureInfo.InvariantCulture);
                double maximumWeight = String.IsNullOrWhiteSpace(parms[2]) ? double.MaxValue : Double.Parse(parms[2], CultureInfo.InvariantCulture);
     
                if (minimumWeight > maximumWeight)
                {
                    Swap(ref minimumWeight, ref maximumWeight);
                }
     
                if (cartOrder.Weight >= minimumWeight && cartOrder.Weight <= maximumWeight)
                {
                    decimal price = GetPriceParameterValue(parms[3]);
                    return this.CreateGenericShippingResponse(shippingMethod, price);
                }
     
                return null;
            }
        }
    }


    Using this calculator, Sitefinity will take the applicable shipping methods based on the weight and using the custom  field (ShippingPricePercentage) created in step 1, you will get the applied percentage rate per the price of the cart.

    4) You will also have to create an implementation of the IShippingMethodRetriever itnerface, which returns the applicable shipping methods used during the checkout process.

    You will need to apply logic in the GetApplicableShippingMethods(CheckoutState checkoutState, CartOrder cartOrder) method, which will  have to use your custom calculator from step 3 to calculate the shipping price used in the checkout. It will use the method from your custom shipping calculator to ShippingXXXXMethodCalculator().Calculate(shippingMethod, cartOrder, parms) to actually apply your custom shipping rate in the checkout.

    5) And to make the checkout use your Retriever from step 4, you will have to override the IEcommerceShippingMethodService implementation, i.e. the EcommerceShippingMethodService class.

    There is one method, you need to override and that is the  public virtual IQueryable<IShippingResponse> GetApplicableShippingMethods(CheckoutState checkoutState, CartOrder cartOrder), which has to use your shipping retriever from step 4, instead of the built-in one. 

    Here is the code of the built-in service, you will have to override:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Telerik.Sitefinity.Ecommerce.Orders.Model;
    using Telerik.Sitefinity.Ecommerce.Shipping.Model;
    using Telerik.Sitefinity.Modules.Ecommerce.BusinessServices.Shipping.Interfaces;
    using Telerik.Sitefinity.Modules.Ecommerce.Orders.Web.UI.CheckoutViews;
    using Telerik.Sitefinity.Modules.Ecommerce.Shipping;
    using Telerik.Sitefinity.Modules.Ecommerce.Shipping.Business;
     
    namespace Telerik.Sitefinity.Modules.Ecommerce.BusinessServices.Shipping.Implementations
    {
        /// <summary>
        /// Concrete implementation of IEcommerceShippingMethodService
        /// </summary>
        public class EcommerceShippingMethodService : IEcommerceShippingMethodService
        {
            public EcommerceShippingMethodService()
            {
     
            }
     
            #region IEcommerceShippingMethodService Methods
             
            /// <inheritdoc />
            public virtual IQueryable<IShippingResponse> GetApplicableShippingMethods(CheckoutState checkoutState, CartOrder cartOrder)
            {
                var shippingManager = ShippingManager.GetManager();
                List<IShippingResponse> availableShippingMethods = new List<IShippingResponse>();
     
                var onlineShippingMethodRetriever = new OnlineShippingMethodRetriever(shippingManager);
     
                availableShippingMethods.AddRange(onlineShippingMethodRetriever.GetApplicableShippingMethods(checkoutState, cartOrder));
                Dictionary<string, IShippingResponse> uniqueShippingMethods = new Dictionary<string, IShippingResponse>();
                foreach (var shippingOption in availableShippingMethods)
                {
                    if (!uniqueShippingMethods.ContainsKey(shippingOption.ServiceCode))
                    {
                        uniqueShippingMethods.Add(shippingOption.ServiceCode, shippingOption);
                    }
                }
                availableShippingMethods = uniqueShippingMethods.Values.ToList();
     
                var offlineShippingMethodRetriever = new OfflineShippingMethodRetriever(shippingManager);
                availableShippingMethods.AddRange(offlineShippingMethodRetriever.GetApplicableShippingMethods(checkoutState, cartOrder));
     
                availableShippingMethods = availableShippingMethods.OrderBy(x => x.SortOrder).ToList();
     
                return availableShippingMethods.AsQueryable();
            }
            #endregion
     
        }
    }

    So instead of the var offlineShippingMethodRetriever = new OfflineShippingMethodRetriever(shippingManager);
    availableShippingMethods.AddRange(offlineShippingMethodRetriever.GetApplicableShippingMethods(checkoutState, cartOrder));

    you will have to use you shipping retriever.

    6) Last but not least, you have to register your custom service from step 5 instead of the built in one. This can be done via ObjectFactory.Container.RegisterType<IEcommerceShippingMethodService, YourNewEcommerceShippingMethodService>(new ContainerControlledLifetimeManager());

    I hope this helps and give you good estimation on the amount of effort needed to do so.

    Regards,
    Peter
    Telerik
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  5. Tim
    Tim  avatar
    34 posts
    Registered:
    16 Oct 2012
    14 Jun 2013 in reply to Peter
    Link to this post
    Thanks Peter.

    Wow, that's way more involved than I thought it would be!

    I might try going down the Create a Customer Carrier Class route instead. It might be easier/simpler to maintain.

    Thanks for the detailed reply.  It's always helpful to see specific code examples.
    -Tim 
5 posts, 0 answered