Blog posts of '2011' 'December'

Shipping Director does Packing!- Friday, December 30, 2011

The packing method built in to Shipping Director is FirstFitSingleBox - Packing is based on "First Fit" using a Single Box Size.  Products fit into first avail box that will take the volume and weight of products.  If no existing box will fit the product, then a new box is started.  It does check that the product will fit in the box's dimensions, but otherwise fit is based on volume of product vs. volume remaining in box, or weight of product vs weight remaining in the box.  (If the product item's dimensions don't fit the box's dimensions, then a new box is created with the product's dimensions, and is considered "full" - no other items will go in that box.)

Here is a sample setup for Shipping Director to do packing.





Rate Expression





























































All should be marked Active, and be sure to spell exactly as above including case, and quote or leading $ if any.  The items with 0 in Expression can be left out if you like - their defaults are 0 anyway, but shown above so you know what all the special variable names (packing parameters) are.   When adding the Packing-type record the Add Form will say "Packing Method" rather than Rate.  (It always says Rate in the grid).

I think most special $ prefix variable names should be obvious, but here's a brief description of each:




Turns on debugging.  Debugging messages appears in the System Log.   Because log messages are not HTML formatted, they can be hard to read in the browser.  So, on a System Log record, click View to see the log detail page.  Then,  Right click the page and "View Source".  Scroll down (a bit more than half way) until you see the plain text messages.


Maximum Weight that the package will hold.  If a product item does not fit in an existing box, then a new box is started.


Height dimension of the box.


Width dimension of the box.


Length dimension of the box.


The weight of the box itself (empty).  This is added to weight of contents for the total weight sent to FedEx.


The weight of any packing material, per item.


The dimension of packing material.  This is added to each of the product item's dimension (H,W,L).


After packing, "Shrinking" adjusts the dimensions of the package if the package is not at least n% full by volume.   The cubed root of the used volume is used as the new dimensions (HxWxL).   This allows for a "smaller" package when package is not full.  $PackageShrinkPercent should be a number from 0 to 100 (it's a %).  If 0 (not present), then no shrinking takes place.


This tells the Shipping Director how to call other shipping plugins when retrieving rate options:
If not specified, then "OneRequestPerSender" is the default if there is a SenderExpression, and "OneRequestForAllPackages" is the default otherwise.

If box dimensions are not specified by above variables, then all items are packed in one box.


The $PackageBox variable is a shorthand for setting many package attributes in one line.
 e.g. $PackageBox   "MaxWeight:40,Height:15,Width:15,Length:15"
 Here's how each shorthand attribute corresponds to the built in variable:
    MaxWeight    => $PackageBoxMaxWeight
    Height       => $PackageBoxHeight
    Width        => $PackageBoxWidth
    Length       => $PackageBoxLength
    Weight       => $PackageBoxWeight
    AddWeight    => $PackageItemAddWeight
    AddDimension => $PackageItemAddDimension
    ShrinkPercent=> $PackageShrinkPercent

The /APPENDPACKAGES Switch (Update 10/6/2018)

If a Packing rule is called multiple times, then each time it is called the set of packages are cleared and new packages are generated.  To override that behavior and instead append addiitonal packages to the current set of packages, then use the /AppendPackages option following the packing method name:

   Packing.FirstFitSingleBox /APPENDPACKAGES

Typically, you you append packages, you would also use the Packing method "Packing.ClearPackages" and/or use the Exclude Expression.  Otherwise, you would double-pack the same items and that would increase the shipping rates that are caclulated by weight/dimensions.  An example scenario for the AppendPackages would be to use a different $PackageBoxWeight for different types of items; be sure to use the Exclude Expression on each packing rule.

Tags :  Packing
Comments (1)
Sorry, we can't ship to PO Boxes- Sunday, December 11, 2011

Do customers miss your "We can't ship to PO Boxes" message?  You can now prevent them from placing the order...

You'll also need to prefix the above expression with a check for null, because during a Shipping Estimate (as opposed to checkout), there is no Address1.  So, the final expression looks like this:

  ShippingAddress.Address1 != null and Regex.IsMatch(ShippingAddress.Address1, "(?i)\b(?:Post\ (?:Office\ )?|P[.\ ]?O\.?\ )?Box\b")

Tags :  PO-Boxes
Comments (6)
Customer can add Optional Insurance- Sunday, December 11, 2011

You can allow your customer to add insurance to the shipping.   In the example below, we add 10% (of subtotal $) using the Surcharge Expression.  Also, by using the Name Expression, it will be clear to the customer what the shipping option is, and you will be able to see that when you goto the order's Shipping Info tab.

Tags :  Insurance
Comments (1)
Shipping By Weight Brackets- Friday, December 9, 2011

nopCommerce's "Shipping By Weight" is a bit confusing (see my post).  And additionally, it can't enforce a minimum charge if using "Use percentage:".   Brackets are easy to set up in Shipping Director:

You can even show the actual weight in the description if you like

"Weight = " + [$TotalWeight].ToString() + " lbs."  

Also, if you want to add a fixed cost to the per unit rate, then additionally at the bottom of the configuration page, in section Shipping Director Settings, put your fixed cost in the: field.  E.g. To have a base rate of $5.00 the enter 5 in Surcharge field, and click Save button

Shipping Director Settings

Tags :  Brackets
Comments (1)
Using other Shipping Rate Methods- Thursday, December 8, 2011

When you configure  Shipping > Shipping Rate Computation Methods, be sure that Shipping.Director is the only "Is Active".
You can still configure the other methods you need.  When you want to 'call' another rate method, just put the name in the Rate Expression field  (no quotes)  E.g.

Option    Fed Ex    true    Shipping.Fedex


Comments (1)
The Shipping Director is an "evaluation engine"- Wednesday, December 7, 2011

The Shipping Director is an "evaluation engine".  Each row is evaluated based on "Order".  (Some old school VB developers may notice the numbering scheme in the example screen below. :)  The "Type" of each row is either a variable (String, Boolean, etc.), an Error, or a shipping Option.  For Variables, the "Expression" field should evaluate to the type of the declaration.  For Error and Option, the "Expression" field is a 'condition' that should evaluate to a boolean - if true, the additional expressions are evaluated (rate, surcharge, etc.), and if false, the next row is examined.  You can specify whether the rows continue to evaluate, or "Exit" when matched - ErrorExit, OptionExit.  Additionally, there is (not shown below) a global setting: "Evaluate All" vs. "EvaluateFirstMatchOnly", whereby a plain Exit or Option will exit if EvaluateFirstMatchOnly is set.

Below are some sample expressions in context of the Configure screen.   (Note that NameExpression and DescriptionExpression must evaluate to strings - if you just have text, be sure to enclose it in double quotes.)

Sample Expressions

Tags :  GettingStarted
Comments (2)
The Shopping Cart Object and Query Operators- Saturday, December 3, 2011

(Update: 12/20/2021 - This is a very old blog.  Some of the properties have changed.  Contact us at for up-to-date information.)

The previous blog discussed expressions, and that the underlying attributes of the Shopping Cart can be referenced.  Below is a partial shopping cart hierarchy.  You use a dot (".") between attributes in the hierachy to reference children.  Some attributes are collections (lists), that can contain 0 or more other objects.  All expressions must yield a scalar value, so collections must have some Query Operator applied like All() [a boolean], or Sum() [a decimal].

Some query operators, like All(), will return a boolean.  For example, Any() will return true if any items in the collection meet the criteria.  For example - The customer has the Administrator role:

Customer.CustomerRoles.Any(Name = "Administrators")

Some query operators, like Where(), will return a subset which is still a collection, so a First() operator must then be applied and then probably followed with an attribute name.  This Where().First() is a common scenario.  For example,  check if customer has the role with Any() above, and then check if that  role is Active:

and Customer.CustomerRoles.Where(Name = "Administrators").First().Active  

 Customer                Customer
     Id                      1
     AdminComment            NULL
     LanguageId              NULL
     CurrencyId              NULL
     TaxDisplayTypeId        0
     IsTaxExempt             False
     VatNumber               NULL
     VatNumberStatusId       0
     UseRewardPointsDuringCheckout    False
     TimeZoneId              NULL
     AffiliateId             NULL
     Active                  True
     IsSystemAccount         False
     SystemName              NULL
     CreatedOnUtc            9/3/2011 2:08:02 AM
     Affiliate               NULL
     Language                NULL
     Currency                NULL
     CustomerRoles           Collection[CustomerRole]
         Id                      1
         Name                    Administrators
         FreeShipping            False
         TaxExempt               False
         Active                  True
         IsSystemRole            True
         SystemName              Administrators

     CustomerAttributes      Collection[CustomerAttribute]
         Key                     FirstName
         Value                   John

         Key                     LastName
         Value                   Smith

         Key                     LastVisitedPage
         Value                   http://localhost:7872/

         Key                     LastShippingOption

         Key                     LastContinueShoppingPage
         Value                   http://localhost:7872/m/261/test           

         Key                     Gender

         Key                     DateOfBirth

         Key                     Company

 Items                   List[ShoppingCartItem]
         Id                      16
         ProductVariantId        59
         CustomerEnteredPrice    0.0000
         Quantity                1
         CreatedOnUtc            10/5/2011 3:12:37 AM
         UpdatedOnUtc            10/15/2011 1:52:19 AM
             Id                      59
             ProductId               58
             Name                    Box Cutter
             Sku                     123456789
             Description             NULL
             AdminComment            NULL
             ManufacturerPartNumber    099999
             IsGiftCard              False
             GiftCardTypeId          0
             IsDownload              False
             IsFreeShipping          False
             AdditionalShippingCharge    0.0000
             IsTaxExempt             False
             TaxCategoryId           0
             CallForPrice            False
             Price                   52.9100
             Weight                  1.0000
             Length                  0.0000
             Width                   0.0000
             Height                  0.0000
             Product                 System.Data.Entity.DynamicProxies.Product
                 Id                      58
                 Name                    Box Cutter
                 ShortDescription        NULL
                 ProductCategories       Collection[ProductCategory]
                     Id                      14
                     ProductId               58
                     CategoryId              72
                     IsFeaturedProduct       False
                     DisplayOrder            1
                     Category                Category
                         Id                      72
                         Name                    Box Cutter Knife, Blades
                         Description             NULL

                 ProductManufacturers    Collection[ProductManufacturer]
                     Id                      14
                     ProductId               58
                     ManufacturerId          5
                     IsFeaturedProduct       False
                     DisplayOrder            1
                     Manufacturer            Manufacturer
                         Id                      5
                         Name                    ABC Industries
                         Description             NULL

 ShippingAddress         Address
     FirstName               NULL
     LastName                NULL
     Email                   NULL
     Company                 NULL
     CountryId               1
     StateProvinceId         40
     City                    NULL
     Address1                NULL
     Address2                NULL
     ZipPostalCode           10021
     PhoneNumber             NULL
     FaxNumber               NULL
     CreatedOnUtc            1/1/0001 12:00:00 AM
     Country                 Country
        Country : 1
     StateProvince           StateProvince
        StateProvince : 40
     Id                      0

 CountryFrom             NULL
 StateProvinceFrom       NULL

Tags :  GettingStarted
Comments (3)
Shipping Director - Sample Expressions- Saturday, December 3, 2011

Expressions are created by referencing variables that you define, or the underlying attributes of the Shopping Cart.  Expressions are built using variables and properties of the shipping request (e.g. Customer, Items collection, etc.).   Simple expressions just use typical operators like "+", "-", "and", "or", etc.  Queries use a variant of Linq syntax (no lambda symbol "=>" required).  Queries are applied to collections to "extract" the items in the collection that meet the query criteria.

When variable names are used in expressions, they must be enclosed in square brackets - e.g. [ZipCode3].  Variables can be boolean, string, decimal, integer, etc.  Query expressions and Attributes are referenced without enclosing brackets.  Most attributes are "objects" that themselves contain other attributes.  Some attributes are collections (lists), that can contain 0 or more other objects.  Developers having a familiarity with the nopCommerce shopping cart object and linq syntax certainly have an advantage when creating expressions, but the syntax is not that hard to grasp given some examples, and future blogs will discuss the cart,, and provide more examples.  Here are some examples that may commonly be used:

Only 2 free items allowed

Items.Where(ProductVariant.Price = 0).Sum(Quantity) > 2

Has Role with Free Shipping

Customer.CustomerRoles.Any(Name = "FreeShipping")  (* see below update)

Affiliated to XYZ

Customer.AffiliateId = 1

Placed 2 or more orders in past 30 days

Customer.Orders.Where((DateTime.Now - CreatedOnUtc).TotalDays <= 30).Count() >= 2


[$TotalWeight] > 150


EXECUTE ShippingZone_LookupRate @p1, @p2; [ZipCode3], [$TotalWeight]

(Update: 12/12/2012 - see this for more about Variable and Expression Data Types )

(Update: 12/20/2021 - Customer.CustomerRoles won't work in 4.x and above.   Use Customer.GetCustomerRoles() to get the full collection, or to check a specific role, use helper property  Customer.IsInRole("role system name") )

Comments (3)