How slotting decides
This page explains, for warehouse and process engineers, how the install chooses bins: what fits where, how a wave is planned, which order gets a scanned unit, and what happens when the wall is full. The same inputs always give the same answers, so a result can be reproduced and explained.
When does a unit fit a bin#
A unit fits a bin when every one of these holds, counting what the bin already holds:
- Opening. If the item has all three dimensions, it must pass through the bin's opening and fit its depth in some orientation: its sorted dimensions are compared with the bin's sorted width, height and depth. An item 50 cm long fits a 40 x 30 bin that is 60 cm deep (lying down, pushed in lengthways).
- Volume. The volume of all units in the bin may not exceed the bin's volume times the fill factor. Goods never fill
a bin completely, so by default only 85% counts as usable. Set
fillFactoron the layout, or per wave inoptions.fillFactor(the wave wins), from 0.1 to 1. Lower it for irregular or fragile goods, raise it for boxed goods. - Weight. If the bin has a
maxWeight, the weight of all units in it may not exceed it. Units without a weight count 0. - Units. If the bin has a
maxUnits, the number of units in it may not exceed it.
Where the item dimensions come from: the order line's item if it has one, else the wave's item master (items[sku]),
else the item has no dimensions.
Items without dimensions#
An item without all three dimensions skips the opening check and adds no volume, because there is nothing to measure.
In a bin without maxUnits, such units are limited only by weight, so in theory a whole order of them "fits" one bin.
Do one of these:
- Send item dimensions with each wave (the item master in
items, or per line). This gives the best plans. - Give the bins a
maxUnits(in the layout, the CSVmaxUnitscolumn, or the grid import'smaxUnits), for example the number of average items a bin holds. Then units without dimensions are counted against it.
Mixing works: items with dimensions use volume and opening, items without them count against maxUnits, and both count
against maxWeight.
An item that fits no enabled bin of the wave's walls at all (too big for every opening, or heavier than every
maxWeight) is reported as unplaceable on its order. The rest of the order is planned normally, and the order counts
as complete when everything else is put (unplaceable units are not in remaining). Scanning such an item answers
item_too_large, and the operator puts it aside.
Planning a wave: compact clusters#
When a wave is created, every order gets a cluster: the bins it will use, chosen so that they are few and close together. The packer then pulls one order from one spot, not from all over the wall.
- What each order needs: its units, their total volume and weight, and its largest item.
- The order of planning: higher
priorityfirst, then the bigger orders (by volume) before the smaller ones, then the order of the input. Big orders are placed while there is still room for them; small orders fill the gaps. - The cluster: for each free bin as a starting point (the seed), slotting grows a cluster through the nearest free
bins and packs the order's units into it (largest first), until everything fits or the cluster reaches
maxBinsPerOrderbins (default 8, a wave option). Of all the seeds, it keeps the cluster with, in this order:- the fewest bins;
- the smallest spread (bins closest to each other);
- the tightest fit: the least unused space, so big bins stay free for big orders;
- the seed that comes first in reading order (top to bottom, left to right), which keeps the free space together.
- Reservations: the cluster's bins are reserved for the order immediately. Other orders and other waves on the same layout can't take them.
"Close" means the real distance between bin centres on the wall face. Between two walls, it is the distance on the floor
plan (from the walls' position and rotation) plus a penalty for changing walls (wallChangePenalty, default 1 m in
the layout's unit), so a cluster stays on one wall when it can. Walls without a position count as very far apart.
The plan in the POST /api/waves answer lists each order's bins and the expected puts (which SKU goes in which bin).
They are a forecast: at the wall, units are put where the scan answers, and that follows the plan as long as the units come
as expected.
Queued orders#
An order is queued when the wall has no free cluster that can take it at planning time: too many orders for the free
bins, or an order bigger than maxBinsPerOrder bins. Queued orders are not an error and stay part of the wave:
- When a queued order gets its first scan, slotting plans it on the spot, but only if it can reserve bins for the
whole order (free bins, or the bins of an order that hasn't started, see below), and in strict mode only as a
compact group. Otherwise the order keeps waiting,
the unit goes to another order that needs the same item if one can take it, and else the scan answers
no_bin_available: put the unit aside and scan it again after the next release. Starting orders on part of their bins would let a full wall lock up, with every order holding one bin and waiting for another. - An order too big for even the empty walls is the exception: it starts with the scanned units and grows as more come.
- Releasing other orders doesn't plan queued orders by itself; the bins are simply free for the next scan that needs them.
- If no bin is free at all, the scan answers
no_bin_available(see below).
The wave's stats.ordersQueued counts them, so you can see when a wall is overbooked.
Keeping an order together: strict and relaxed#
A cluster of bins that is spread over the wall costs the packer walking and searching at pack-out. The wave option
compactness decides what happens when the free bins are scattered:
compactness |
|
|---|---|
strict (default) |
An order gets bins only as a compact group. If the free bins can't give it one now, it waits (queued) until releases free a compact group |
relaxed |
An order takes the best group the free bins allow, however spread out. Nothing waits for compactness |
Compact means: about as close together as on an empty wall. Slotting knows the best cluster the order would get if the walls were empty; a cluster is compact when its spread (the distances from its bins to its first bin, added up) is at most 1.25 times that ideal spread, plus one bin pitch (the usual distance between neighbouring bins). An order that fits one bin is always compact.
In strict mode the rule applies wherever an order gets its bins:
- Planning: an order whose best free cluster isn't compact is queued instead.
- The first scan of a queued order: if only a scattered cluster is free, the order keeps waiting and the unit goes to another order that needs it, as when there is no room at all (Queued orders).
- Taking an unstarted order's bins for a queued order (Stealing a reservation): only if the result is compact.
It doesn't apply where an order is already being put: when its items need more room than planned, the cluster is extended with the nearest free bin, compact or not, because the units are already on the wall. An order too big for even the empty walls isn't held to it either.
Waiting has a limit. On a busy wall, bins free up one at a time in different places, and an order waiting for a compact
group could wait for a long time. So slotting counts: when an order of the wave is released and the first waiting order
(in planning sequence) could now start, but only on a scattered cluster, that counts as one wait for that order. After
SLOTTING_COMPACT_MAX_WAIT such releases (default 3, set by the operator of the install, see
configuration), the order takes the best cluster it can get. Only the first waiting order
counts at each release, so the guard lets single orders through rather than giving up on compactness for the whole
queue. An order that has no room at all is waiting for room, not for compactness, and isn't counted.
What it achieves: in our test of 150 orders on a full wall, with orders released as they were packed out, every order that needed several bins stayed within 600 mm in strict mode. In relaxed mode, orders spread across the wall as soon as it was busy.
Use relaxed when throughput matters more than walking at pack-out: for example a small wall where every bin is within
reach, or orders that are packed at the wall itself.
Which order gets a scanned unit#
The operator scans a SKU, not an order. When several orders of the wave still need that SKU, the wave's allocation
option decides:
allocation |
The unit goes to |
|---|---|
complete-first (default) |
Orders already in progress first; then the order that will be closest to complete after this unit (fewest units left); then higher priority; then input order. Orders that have bins come before queued orders. This finishes orders early, so bins are released sooner and the packers get a steady flow. |
fifo |
Orders that have bins first, then higher priority, then input order. Use it when orders must be finished in sequence (cut-off times, carrier pickups). |
- To put for one specific order (the operator chose it, or your system knows it), send
orderIdwith the scan. - A scan with
quantitygreater than 1 goes to one order. If that order needs fewer, it gets what it needs and the answer'squantitysays how many were put; scan again for the rest. - If no order needs the SKU any more, the scan answers
sku_fully_slotted; if no order of the wave ever had it,sku_not_in_wave. Both mean: put the unit aside.
Which bin#
For the chosen order, slotting tries in this order and takes the first that works:
- the bin the plan expected for this SKU, if it still has room;
- the order's bin that already holds the most of its units and still has room (keeps the order together);
- extend the cluster with the free bin nearest to the order's bins (up to
maxBinsPerOrderbins); - steal (below);
- otherwise the scan answers
409 no_bin_availableand nothing changes: the operator puts the unit aside, and scans it again when bins are released.
A scan of several units may be split over several bins of the order: puts lists them, and bin is the first.
Stealing a reservation#
When the wall is full, an order can take the bins of an order that hasn't started: a planned order of the same wave with nothing put yet. A queued order does this only when those bins (with the free ones) hold its whole order; an order that is already being put does it to get one more bin when its items needed more room than planned. Among those, the one with the lowest priority and planned last gives way. Its reservation is cancelled (all its bins are freed), the scanning order takes the bin nearest to its own, and the other order goes back to queued; it will be planned again on its first scan. Orders with units in their bins are never touched, and orders of other waves are never touched.
Confirmed puts#
With the wave option confirmPuts: true, a put counts as done only when the operator confirms it: by scanning the bin's
label after putting the unit in, or by pressing the bin's light button (Put-to-light). This catches units put
into the wrong bin before the order is packed out.
- Scan the item. The answer has
"pending": true. The units are already counted for the bin (its capacity) and the order (remaining), so the next scan doesn't send them anywhere else; but the put waits for its confirmation, andorderCompletestaysfalse, even for the order's last unit. - Put the unit in and scan the bin, which sends
POST /api/waves/{waveId}/confirmwith the scannedbinIdand the scan'sscanId. The answer (ConfirmResult) says which order and bin were confirmed; on the order's last pending put,orderCompleteistruewithorderBins, exactly as a last scan without confirmation. - A wrong bin answers
409 wrong_binwithdetails.expected, the bins that scan's units went to. Nothing changes: the operator moves the unit and scans the right bin. A bin with nothing waiting answers409 not_pending.
- A scan split over several bins needs one confirmation per bin; each bin's part is pending on its own.
- Without a
scanId, the confirmation takes the oldest pending put of the wave into that bin. That is what a light button does. - Until the last put is confirmed, the order is
in_progresswith nothingremaining: no more units are sent to it, and releasing it answers409 order_not_complete. - Undo of a pending scan cancels the put (its units go back to
remaining). Completing an order short counts its pending puts as made. - Repeating a
scanIdreturns the first answer (pending: true), also after the put was confirmed. GET /api/waves/{waveId}/pendinglists the puts still waiting, for example for a supervisor's screen.
Without confirmPuts nothing of this applies: every put is done when the scan answers.
Complete, release, close#
- Complete. The scan that puts an order's last unit (with confirmed puts: the confirmation of its last
put) answers
orderComplete: trueandorderBins: every bin that holds units of the order, nearest first. Show them to the operator or the packer, who pulls the order from those bins. Bins that were reserved for the order but stayed empty are freed at that moment. - Short. When an order can't be finished (a unit is missing or damaged),
POST /api/waves/{waveId}/orders/{orderId}/completecompletes it short: it is markedshort, and the reserved bins it never used are freed at once. - Undo.
POST /api/waves/{waveId}/undowith ascanIdtakes that scan's units back out (the operator put them in the wrong bin or scanned twice). The bins stay reserved for the order. A stolen reservation isn't given back. - Release. After pack-out,
POST /api/waves/{waveId}/releasewith{ "orderId" }frees all bins of the order; with{ "binId" }(a packer scanning the bin label) it releases the order that holds that bin. Only complete orders can be released (409 order_not_completeotherwise), so a half-filled order can't be cleared by mistake. - Close.
POST /api/waves/{waveId}/closeends the wave: every bin it still holds is freed, and no more scans are accepted (409 wave_closed). A wave becomescompleteby itself when every order is complete or released, but only closing frees what is left. Closed waves older thanSLOTTING_WAVE_RETENTION_HOURS(default 72) are deleted automatically when the next wave is created on the layout, or at once withDELETE /api/waves/{waveId}.
Several waves on one wall#
Waves on the same layout share its bins: a wave plans only into bins that no other active wave holds, and each wave's
orders keep their bins until they are released or the wave is closed. So you can start the next wave while the previous
one is being packed out; its orders are planned into the free bins and queued for the rest. Limit a wave to some walls with
wallIds when stations work on their own walls.