Calculating Different Shipping cost tiers based on Cart Tota

Posted by Community Admin on 05-Aug-2018 17:45

Calculating Different Shipping cost tiers based on Cart Total

All Replies

Posted by Community Admin on 11-Jun-2013 00:00

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

Posted by Community Admin on 12-Jun-2013 00:00

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

Posted by Community Admin on 12-Jun-2013 00:00

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

Posted by Community Admin on 14-Jun-2013 00:00

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

Posted by Community Admin on 14-Jun-2013 00:00

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 

This thread is closed