Table of Contents

Picking Class Shipment Matching Scripts

Colin Updated by Colin

When ShipStream creates a Shipment, the final step is to assign the Shipment to a Picking Class. Each Shipment is evaluated against each Picking Class in order of the Sort Order to determine which one will be assigned. By using a script you can apply complex logic to this process so that your shipments are classified according to your needs for an efficient picking and packing operation.

See Scripting Basics to become more familiar with scripting in ShipStream in general.

Picking Class Matching

A Soft Match counts as a match but will allow remaining Picking Classes to be evaluated, and if there is another Picking Class that matches the last one wins. A Hard Match will match and short-circuit the remaining Picking Classes so that no other Picking Class will be evaluated. Essentially the Soft Match allows a match to "fall through" so that another Picking Class can be matched and a Hard Match does not.

The scripts in this case are not able to mutate any of the shipment data, they can only determine if there is a match or not. This is done by calling SoftMatch() and HardMatch(). If neither of these methods are called in the script execution, the Picking Class will not match the Shipment being evaluated and the next Picking Class will be evaluated until all are evaluated or there is a Hard Match.

Example Script

The following example script would result in a Hard Match for shipments that have a total weight greater than or equal to 200 lbs or a total quantity of pickable items greater than or equal to 100. If neither of these criteria are true there would be no match.

// Huge shipments
if (shipment.total_weight >= 200 || shipment.total_qty >= 100) {
HardMatch();
}

Script Data

The script is executed in a scope with three variables:

  • shipment - The shipment being matched
  • order - The order of the shipment being matched
  • Order - An object exposing methods for the order of the shipment being matched

Here is an example of the data contained within these variables:

const shipment = {
"shipment_id": "1100000091",
"order_unique_id": "1100000044",
"order_ref": null,
"carrier_code": "external",
"shipping_method": "external_ltl",
"tpb_group_id": null,
"warehouse_id": "2",
"total_weight": "5.0000",
"total_qty": "5.0000",
"items": [
{
"sku": "AIR-1",
"name": "O'hare Air - Single",
"order_item_id": "172",
"qty": "1.0000",
"qty_picked": "0.0000",
"qty_shipped": "0.0000",
"qty_cancel_requested": "0.0000",
"qty_canceled": "0.0000",
"weight": "1.000",
"product": {
"sku": "AIR-1",
"name": "O'hare Air - Single",
"barcode": "AIR-1",
"external_id": null,
"vendor_sku": "BoM_Tests",
"goods_type": "NORMAL",
"regulation_id": null,
"status": "1",
"availability": "1",
"visibility": "2",
"weight": "1.0000",
"length": "9.1000",
"width": "4.1000",
"height": "4.1000",
"export_description": null,
"country_of_manufacture": null,
"customs_value_usd": null,
"hts_base_code": null,
"hts_country_code": null,
"requires_packaging": 1,
"requires_infill": null,
"require_weight_check": 1,
"confirmation_per_item": 0,
"valid_containers": [],
"special_supplies": [],
"special_other": [],
"unit_qty": 1,
"bulk_qty": null,
"max_per_package": null,
"is_ship_separate": 0,
"ship_separate_tag": null,
"can_tip": 1,
"can_contain_other_items": 0
}
},
{
"sku": "AIR-1",
"name": "O'hare Air - Single",
"order_item_id": "173",
"qty": "4.0000",
"qty_picked": "0.0000",
"qty_shipped": "0.0000",
"qty_cancel_requested": "0.0000",
"qty_canceled": "0.0000",
"weight": "1.000",
"product": {
"sku": "AIR-1",
"name": "O'hare Air - Single",
"barcode": "AIR-1",
"external_id": null,
"vendor_sku": "BoM_Tests",
"goods_type": "NORMAL",
"regulation_id": null,
"status": "1",
"availability": "1",
"visibility": "2",
"weight": "1.0000",
"length": "9.1000",
"width": "4.1000",
"height": "4.1000",
"export_description": null,
"country_of_manufacture": null,
"customs_value_usd": null,
"hts_base_code": null,
"hts_country_code": null,
"requires_packaging": 1,
"requires_infill": null,
"require_weight_check": 1,
"confirmation_per_item": 0,
"valid_containers": [],
"special_supplies": [],
"special_other": [],
"unit_qty": 1,
"bulk_qty": null,
"max_per_package": null,
"is_ship_separate": 0,
"ship_separate_tag": null,
"can_tip": 1,
"can_contain_other_items": 0
}
}
],
"solution": {
"source_type": "algorithm",
"source_id": "box_packer",
"num_containers": "1",
"containers": [
{
"qty": "1",
"product": {
"sku": "PB16824",
"name": "Plain Box 16x8x24",
"barcode": "B3",
"external_id": null,
"vendor_sku": null,
"status": "1",
"availability": "1",
"visibility": "2",
"weight": "1.3000",
"length": "16.0000",
"width": "8.0000",
"height": "24.0000"
},
"volume": "3072.0000",
"weight": 6.2999999999999998,
"length": "16.0000",
"width": "8.0000",
"height": "24.0000"
}
]
}
}
const order = {
"order_id": "62",
"unique_id": "1100000044",
"order_ref": null,
"store_code": "acme_inc",
"state": "new",
"status": "new",
"carrier_code": "external",
"shipping_method": "external_ltl",
"shipping_description": "LTL",
"weight": "5.0000",
"total_item_count": "2",
"signature_required": "none",
"saturday_delivery": "0",
"overbox": "0",
"custom_greeting": null,
"requested_ship_date": null,
"submitted_by_id": "1",
"submitted_by_type": "admin",
"other_shipping_options": "",
"declared_value": "0.000",
"backorder_policy": "default",
"priority": "50",
"tpb_group_id": null,
"desired_delivery_date": null,
"reason_for_export": null,
"customs_value": null,
"shipping_address": {
"region": "Missouri",
"postcode": "65807",
"lastname": "Goalley",
"street": "15491 West Whiteside Street",
"city": "Springfield",
"email": "celina.goalley@thompson-torp.com",
"telephone": "+444175193773",
"firstname": "Celina",
"company": "Thompson-Torp",
"classification": null,
"is_valid": null,
"shipping_name": "Celina Goalley",
"country": "US"
},
"items": [
{
"sku": "AIR-1",
"name": "O'hare Air - Single",
"weight": "1.000",
"row_weight": "1.000",
"qty_ordered": "1.0000",
"qty_backordered": "0.0000",
"qty_canceled": "0.0000",
"qty_processing": "0.0000",
"qty_shipped": "0.0000",
"allocation_data": [
{
"warehouse_id": "2",
"qty_allocated": "1.0000"
}
],
"order_item_id": "172",
"order_item_ref": null,
"product": {
"sku": "AIR-1",
"name": "O'hare Air - Single",
"barcode": "AIR-1",
"external_id": null,
"vendor_sku": "BoM_Tests",
"goods_type": "NORMAL",
"regulation_id": null,
"status": "1",
"availability": "1",
"visibility": "2",
"weight": "1.0000",
"length": "9.1000",
"width": "4.1000",
"height": "4.1000",
"export_description": null,
"country_of_manufacture": null,
"customs_value_usd": null,
"hts_base_code": null,
"hts_country_code": null,
"requires_packaging": 1,
"requires_infill": null,
"require_weight_check": 1,
"confirmation_per_item": 0,
"valid_containers": [],
"special_supplies": [],
"special_other": [],
"unit_qty": 1,
"bulk_qty": null,
"max_per_package": null,
"is_ship_separate": 0,
"ship_separate_tag": null,
"can_tip": 1,
"can_contain_other_items": 0
}
},
{
"sku": "AIR-4",
"name": "O'hare Air - 4 Pack",
"weight": "4.000",
"row_weight": "4.000",
"qty_ordered": "1.0000",
"qty_backordered": "0.0000",
"qty_canceled": "0.0000",
"qty_processing": "0.0000",
"qty_shipped": "0.0000",
"allocation_data": [
{
"warehouse_id": "2",
"qty_allocated": "1.0000"
}
],
"order_item_id": "173",
"order_item_ref": null,
"product": {
"sku": "AIR-4",
"name": "O'hare Air - 4 Pack",
"barcode": null,
"external_id": null,
"vendor_sku": "BoM_Tests",
"goods_type": "NORMAL",
"regulation_id": null,
"status": "1",
"availability": "1",
"visibility": "2",
"weight": "4.0000",
"length": "12.1000",
"width": "4.1000",
"height": "9.1000",
"export_description": null,
"country_of_manufacture": null,
"customs_value_usd": null,
"hts_base_code": null,
"hts_country_code": null,
"requires_packaging": 1,
"requires_infill": null,
"require_weight_check": 1,
"confirmation_per_item": 0,
"valid_containers": [],
"special_supplies": [],
"special_other": [],
"unit_qty": 1,
"bulk_qty": null,
"max_per_package": null,
"is_ship_separate": 0,
"ship_separate_tag": null,
"can_tip": 1,
"can_contain_other_items": 0
}
}
]
}
const Order = {
getCustomField: function(code) (),
getCustomFieldValue: function(code) (),
getCustomFieldId: function(code) (),
getCustomFieldLabel: function(code) (),
}

Custom Fields

Order Custom Fields are accessed and updated using a number of methods on the Order object rather than properties of the order object.

The custom field methods are invoked on an object with an upper-case "O" whereas the other fields above are accessed as properties of an object with a lower-case "o".
Order.getCustomField(code)

This method returns either an object or an array depending on the type of the custom field.

Field Type

Empty Return Value

Non-Empty Return Value

Example

Text

null

Object{value: string}

{"value":"Greetings!"}

Multiline Text

null

Object{value: string}

{"value":"Hello\nworld!"}

Number

null

Object{value: number}

{"value":42}

Currency

null

Object{amount: number}

{"amount":1.29}

Select

null

Object{id: number, label: string}

{"id":13,"label":"Damaged in shipping"}

Multiselect

[]

Array{Object{id: number, label: string}}

[{"id":13,"label":"Label 1"},{"id":15,"label":"Label 2"}]

Yes/No

null

boolean

{"value":true}

Date

null

string

{"value":"2023-05-09"}

Admin User

null

Object{id: number, label: string}

{"id":51,"label":"Bernard Greensmith"}

Client User

null

Object{id: number, label: string}

{"id":51,"label":"Bernard Greensmith"}

Email

null

Object{value: string}

{"value":"user@example.com"}

URL

null

Object{value: string}

{"value":"https://example.com"}

Get the custom field value for a custom field with code "my_custom_field":

let myValue = Order.getCustomField('my_custom_field') // null or {"value":"x"}
Order.getCustomFieldValue(code)

Like Order.getCustomField() above, but returns the "value" or "amount" property instead of an object. This can still return null so make sure you account for that to avoid errors from calling methods on null. This method cannot be used for Select, Multiselect, Admin User or Client User types.

if ((Order.getCustomFieldValue('district')||'').match(/^pattern/)) {
// do something...
}

if (Order.getCustomFieldValue('customer_since') > "2020-01-01") {
// do something...
}
Order.getCustomFieldId(code)

Like above, but returns just the "id" property for single-select fields and an array of "id" for multi-select fields.

print(order.getCustomFieldId('claim_reason')) // 13
print(order.getCustomFieldId('claim_reasons')) // [15,16]
Order.getCustomFieldLabel(code)

Like above, but returns just the "label" property for single-select fields and an array of "label" for multi-select fields.

print(order.getCustomFieldLabel('claim_reason')) // "Damaged in shipping"
print(order.getCustomFieldLabel('claim_reasons')) // ["Damaged in shipping","Did not fit"]

Cookbook

The following examples demonstrate some of the scripting capabilities you have with matching scripts. These can be combined and modified to fit your needs.

Match by specific item​ properties

// Match shipment by specific item properties
if (shipment.items.find(item => item.product.requires_packaging === 1)) {
HardMatch();
}

Match by shipping carrier

// Match all "External Shipping Methods"
if (shipment.carrier_code === "external") {
HardMatch();
}

Match by shipping methods

// Match all FedEx Overnight methods
const methodRegex = /^fedex_.+OVERNIGHT$/
if (shipment.shipping_method.match(methodRegex)) {
HardMatch();
}

Match by product longest dimension

// Match longest dimension greater than 24 inches
const itemMatch = shipment.items.some(function(item){
const length = parseFloat((item.product||{length:0}).length)
const width = parseFloat((item.product||{width:0}).width)
const height = parseFloat((item.product||{height:0}).height)
return Math.max(length, width, height) >= 24
})
if (itemMatch) {
HardMatch()
}

Match by container properties

// Match all shipments NOT using "Plain Box" containers
const boxRegex = /^Plain Box/
if (
! shipment.solution ||
! shipment.solution.containers.some(container => container.product.name.match(boxRegex)
) {
HardMatch()
}

Match by Other Shipping Options

The Other Shipping Options field can contain any valid JSON object. For example:

{"gift_wrap":true}

// Match all orders with "gift_wrap" flag
if (order.other_shipping_options && order.other_shipping_options.gift_wrap) {
HardMatch()
}

How did we do?

Ready to Ship Time Scripts

Contact