Blog

First,
I recommend checking if a Country/State/Zip has been provided, because the
“Estimate Shipping” will work even if they are not selected, and depending on
rate calculation method (shipping plugin), you could get funny results, or an
error. (Only US and Canada have states.) For this, we use the ErrorExit
record Type. This will Exit if the Expression (condition) evaluates to
true, and the customer will see the message calculated in the Description
Expression. Note, that this is a String Expression, so be sure to include
quotes for a literal value.

Order

10

Type

ErrorExit

Name

Missing Country State Zip

Expression

Country
= "" or Zip = "" or ("US,CA".Contains(Country)
and State = "")

Description Expression

"Please
Enter Country, State, and Postal Code"

Then,
let’s say we want to prevent shipping if the State is Alaska or Hawaii.
We would use the ErrorExit type here too:

Order

20

Type

ErrorExit

Name

No Shipping to Alaska and Hawaii

Expression

"AK,HI".Contains(State)

Description Expression

"Sorry,
we can’t ship to Alaska or Hawaii"

The
condition Expression could have also been written as

Expression

State = "HI" or State =
"AK"

But
when using an “or”, be sure to use parenthesis if you have a more complex
expression that includes “and”s too.

Alternately,
you may just want to exclude just Ground shipping to Alaska and Hawaii.
For example, you want to use the Shipping.FixedOrByWeight rate calculation
method, but don’t want to offer Ground to Alaska or Hawaii. Then the
above would instead be entered with an Option type:

Order

20

Type

Option

Name

Ship By Weight but no Ground for AK and HI

Expression

true

Rate Expression

Shipping.FixedOrByWeight

Name Expression

"AK,HI".Contains(State) and [$Name].Contains("Ground") ? "" :
[$Name]

For
the Option type, the Expression field is a condition. If it evaluates to
true, then the option record is processed, otherwise it's skipped. The
Rate Expression can either be a decimal expression calculating the actual rate
you want to charge, or the name of a shipping plugin. The Name Expression
calculates the shipping option Name shown to the customer. However, if
the Name Expression evaluates to blank (""), then Shipping Director
will exclude the Option. The [$Name] is a built-in variable that contains
the Name of the shipping option as returned by the other rate calculation
plugin. So, here we are saying "if the state is Alaska or Hawaii,
then exclude the named option, else show the named option". The If-Then-Else is achieved using the " ?
: " ternary operator - condition ? if-true : if-false.

Let's say you've assigned Products their own "Additional shipping charge" and you want that charge to be the only charge for those products, and for any other prodcucts in the cart you want to calculate shipping using some 'standard' provider (like FedEx, or By Weight, etc.). Shipping Director's Packing with Exclude Expression can handle it. Here's the general idea:

EvalType

Name

Expression

Rate Expression

Description Expression(Exclude)

Packing

Exclude Addl Charge items

Items.Any(Product.AdditionalShippingCharge
> 0)

Packing.FirstFitSingleBox

Product.AdditionalShippingCharge > 0

Option

Shipping

true

Shipping.ByTotal

Using Packing's Exclude Expression removes those items from "the cart", so that the Shipping.ByWeight provider does not see them.

Calculation Per item shipping charges can be a bit tricky. Consider that the complexity is that the cart can contain multiple items in different categories, and thus you need to have some kind of "per item" shipping calculation that group items by category. There are two ways to do this with Shipping Director.

1) "Configure" in Shipping Director all the zone/rate calculations. See this basic example about per item shipping

The above example does not take into account any consideration for different rates for the first item vs. additional items. For example, if the first item ships for $5.00 and each additional item ships for $2.00. First, you need to consider if the calculation is specific for Product quantity or Category quantity (as per above example "counts").

2) If you have so many Zones and Categories and you frequently need to change rates, then you may want to set up some tables in SQL Server, and a custom Stored Procedure can be written to do the calculation. Here's a blog with an example using Zone/Weight, but note it's 'total cart weight' and doing individual categories would need different coding. Note that Shipping Director does not have a GUI to maintain the lookup tables. You (or your IT person) would need some time of tool (like SSMS) to maintain (insert or update) rates. (In the future, we plan on adding a feature to SD to allow uploading such data into SQL tables.)

(Also, note: if your products have Product Attributes that need special shipping rate calculations / additional $, then it becomes more complex. And, you may want to 'validate' the postal code, because it is just a free form text field.)

nopCommerce always adds the Additional Shipping Charges after getting rates from the Shipping Providers. I've blogged about how to use the Shipping Director to conditionally negate the Additional Shipping Charges. It's easily done by using the Surcharge Expression as described here:

In this example, we’ll show how to have the Product Additional Shipping Charge apply only once to the cart item regardless of the Quantity entered by customer.

The ‘magic’ is to calculate the Product Additional Shipping Charges that would be added by nopCommerce and use the Surcharge Expression to negate them. But in this case, to also calculate, and add back, those charges as if only one charge per item rather than one charge per Quantity.

In the Rate Expression of an Option (or OptionExit) type record, put in a SQL statement (or call a stored procedure). It must return a table of Shipping Options - columns: Name VARCHAR, Description VARCHAR, Rate Decimal.

For example, if you can set up Warehouses as locations for local Pickup:

You can use the day of week in your expressions. For example, if you need to have Saturday Delivery, but only want to show that option on Friday, here's an example using Shipping By Weight. You can create another Shipping Method (e.g. "Saturday Delivery"), and Shipping Director can exclude it conditionally (when not Fri) by using Name Expression.

The Name Expression would look like this (assuming your method name has the word "Saturday" in it - e.g. "Saturday Delivery") :

Note, though, that you may also want to check the Time too (because if they place the order Fri at 11pm, you may not be able to get it there Sat ;)

Another example would be to show an additional set of shipping options with a surcharge. For example, if you use Shipping By Weight, you can call it twice with the Option type. The 2nd call would check if the country is Belgium and the day of the week is Thu or Fri; it would have a Surcharge Expression, in this case just a fixed 2.50:

Here's one way to charge a fee to "rentals made after 1pm of a rental starting today"

Note that RentalStartDateUtc has Utc suffix, but since current nopC only supports Date and not time for rentals, I don't know if it has any impact - my test shows that when I entered item in cart with today's date, that is what was stored in the database, even though I'm UTC - 5 which would have been UTC next day since I entered it at 9pm. (There is no DateTime.UtcToday, but DateTime.UtcNow.Date should work in its place if you prefer to use compare.) Also, below I use DateTime.Now.Hour and not DateTime.UtcNow.Hour, because I'm comparing the current hour to see if it's later than 1pm my time (13:00) - but this time will also depend on the time of your server.

PayPal Express is a "button" payment method, which means it appears as a button on the shopping cart page. That said, your Payment Director expression won't be able to make use of ShippingAddress attributes, because a shipping address does not get selected by the customer until later in the checkout flow.

So, for example, if you wanted to only allow PayPal Express for US customers, you can't use ShippingAddress.Country.TwoLetterIsoCode . Instead, one workaround is to require a Country be entered during customer registration. "CountryId" is an attribute stored with the Customer.

Here's what it should look like in Payment Director grid:

Option

Payments.PayPalExpressCheckout

Customer.GetAttribute("CountryId") = "1"

Note the "1". That's the CountryId. You'll need to verify (or change) the "1" for country of your choice. "US" is typically "1", but it could vary depending on your nopCommerce configuration. To verify/get the Id, Edit your country in Admin > Configuration > Countries, and check the browser's address bar. Check the # on the end of the url - e.g. /Admin/Country/Edit/1

You really only need to replace the file Nop.Plugin.Shipping.USPS.dll but I've included everything - source code, and no source versions. Copy .dll from the zip file's \USPS Shipping\nopCommerce 3.xx\Shipping.USPS folder to your \Plugins\Shipping.USPS folder. After you copy it to your plugin folder, be sure to "Reload list of plugins", or restart your web app.