Skip to content

Powered by Grav CMS + Helios Theme

Boxes and packing

This page covers the box catalogue, how an order becomes parcels, and how to check that decision before a customer pays for it.

Packing is the part of carrier shipping a merchant otherwise cannot see. Rates arrive and labels print, and how many boxes the software decided on stays invisible until a customer is charged for three parcels where two would have done. So it is visible, it is repeatable, and this page explains it.

Before you begin

  • kahunacart.shipping.manage to edit boxes, and kahunacart.orders.view to run the packer test.
  • Weights and sizes on your variants. A catalogue with neither still quotes, on estimates.

The box catalogue

A box is a code, a name, its outside measurements in whole millimetres, and a maximum weight in whole grams. You can also record the inside measurements, the weight of the empty box, and a courier's own predefined package where the box is one — a flat-rate envelope is a box like any other.

Add a box

  1. In the admin sidebar, click KahunaCart, then Shipping carriers, then the Boxes tab.
  2. Click Add a box.
  3. Enter a Code, a Name, the Length, Width and Height in millimetres, and a Maximum weight in grams.
  4. Click Save.

The box is now one the packer may choose.

Field Meaning
Code Your own short identifier. packing.default_box names one of these.
Length, Width, Height The outside of the box, in whole millimetres, which is what the label on the pack says.
Maximum weight In whole grams, and the empty box counts towards it, because the box goes on the scale too.
Inside length/width/height Optional. Left blank, the packer works with the outside less the packing-material allowance.
Empty weight Optional. The weight of the box itself.
Carrier package Optional. The courier's own code where this box is one of theirs.

Note

A maximum weight of 0 means not weighed, not "nothing fits". A merchant who has not weighed a box gets a working catalogue rather than a box the packer refuses to put anything in.

Packing material

Packing material is millimetres kept free on each side of every box for bubble wrap and paper. Ten by default (packing.padding_mm). The packer will not put something in a box unless it fits with that much room to spare, so a 190 mm thing does not go into a 200 mm box.

Set it to 0 if your boxes are already measured to their usable inside.

A store with no boxes

It still quotes, on one built-in box of 300 × 200 × 150 mm and twenty kilos, with every parcel flagged as an estimate and a line on the Boxes tab saying the prices will be approximate.

Refusing to price an order because nobody typed a box in would be a worse answer than an approximate one. It is still an approximate one.

How the packer decides

  1. Every line becomes units. Three of a mug is three items, not one item of quantity three, because a box takes three mugs or it does not.
  2. Anything with no recorded size joins a pile of unknowns, and the answer says which lines those were.
  3. The rest is sorted largest first, and each unit goes into the first open parcel that will take it, or opens the smallest box it fits in. That is first-fit-decreasing.
  4. The pile of unknowns joins the last parcel if its weight allows, or opens the default box. Either way the parcel is flagged as an estimate and says why.
  5. Each parcel's billable weight is the greater of its actual weight and its dimensional weight.

Two things the packer will not do:

  • Overfill a box. Nothing goes in that would take the box over its maximum weight.
  • Refuse an oversized item. Something that fits no box travels on its own, at its own dimensions, flagged. "This goes on its own" is right far more often than "this cannot be sent".

It is not a true three-dimensional solver. A real one would tell you six mugs fit a box that five and a book do not, and would occasionally be wrong the other way — and a parcel that will not close is a parcel somebody has to repack at four o'clock with the courier waiting.

Packing is repeatable

The same order packs the same way every time. Every tie is broken on facts about the order — the line's id, the unit's place in its line, the box's code — and never on anything about the request, so two page loads cannot disagree. There is a test that packs one order a hundred times with its lines reshuffled and compares the bytes.

Sizes on your products

The packer reads each line's size from the variant frozen onto the order. A variant records length_mm, width_mm and height_mm beside weight_grams, in whole millimetres.

Blank means not recorded, never zero. A box with a zero side is not a box, and a courier asked to quote for one answers nonsense.

Record a variant's size

  1. In the admin sidebar, click KahunaCart, then Products, and open a product.
  2. Open the Variants tab and expand a variant.
  3. Under Size, fill in Length, Width and Height in millimetres.
  4. Click Save.

The fields are also on the products API and in the CSV importer.

Important

There is no centimetre column in the importer, and its absence is on purpose. Reading a Length (cm) from another platform into a millimetre field quotes a parcel at a tenth of its real size, which is invisible until the courier bills you.

Note

A variant's weight has no field in the admin yet, only in the API and the importer. Everything here prices on billable weight, which is the greater of the actual and the dimensional, so a catalogue filled in entirely through the admin is priced on size alone. That is the wrong number for anything dense.

Dimensional weight

Every courier bills on the greater of a parcel's actual weight and its dimensional weight, which is its volume converted into a weight. A pillow costs what a pillow-sized brick costs, because what the courier is really selling is space on a van.

The arithmetic is length × width × height in centimetres divided by a divisor, giving kilograms, rounded up. 5000 is the usual divisor and the default (packing.dim_divisor).

It is not universal — divisors differ by courier and by whatever you have negotiated — so there is a per-carrier override map beside it (packing.dim_divisors), keyed by the courier's own token:

YAML
packing:
  dim_divisor: 5000
  dim_divisors:
    ups: 4000

A fractional kilogram is rounded up, because that is what every courier does. A parcel quoted a gram less than it is charged loses you money on every order.

Check the packing

Test the packer draws the parcels a real order would make: the box each one is in, what went in it, both weights, and which of the two the courier would bill.

Run it against a real order

  1. Open KahunaCart → Shipping carriers and the Boxes tab.
  2. Under Test the packer, choose A real order.
  3. Enter the order number and click Pack it.

Run it against a made-up basket

  1. Under Test the packer, choose A made-up basket.
  2. Click Add a line and fill in how many, the length, width and height in millimetres, and the weight in grams.
  3. Click Pack it.

This answers "what would five mugs do" without placing an order to find out.

The test writes nothing, so it works on a read-only store as well.