Calculating Different Shipping cost tiers based on Cart Total
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
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 checkoutState, CartOrder cartOrder)Please let me know if I am getting your requirement correctly and if you need additional assistance or questions here.
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
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
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
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