Inventory Routing App
The Inventory Routing app family automatically assigns order deliveries to warehouses based on stock availability, country routing rules, and inventory date. It turns "we have stock in three warehouses but orders always go to the wrong one" into a configuration problem instead of a coding problem.
The family ships in two variants. They share configuration and stock-reservation behaviour but differ in where the inventoryKey lives — that single design choice determines whether a single delivery can mix warehouses or whether each delivery is tied to one warehouse.
Variants
| App ID | inventoryKey is set on | Resulting delivery shape | Status |
|---|---|---|---|
inventory-routing.per-delivery | Each delivery | One warehouse per delivery. Multi-warehouse lines are split into additional deliveries, one per inventory. | Available |
inventory-routing.per-orderline | Each order line | One delivery can list lines from different warehouses; the source warehouse is recorded per line. | Not yet available |
Both variants are interchangeable from a caller's point of view — the trigger is the same (inventoryKey: "auto_assign" on the new resource) and the same channel-country configuration drives the warehouse priorities.
Picking a variant
The constraint is rarely Hantera's — it's almost always set by the surrounding software landscape. Both the downstream side (WMS, picking station, couriers) and the upstream side (ERP invoicing, finance) can dictate whether a single fulfilment is allowed to mix warehouses.
Rule of thumb
Can the systems that consume your fulfilment data — your WMS, your ERP's invoicing, your label and courier flows — handle a single fulfilment that lists items from multiple warehouses?
- No, they need exactly one fulfilment per warehouse →
per-delivery - Yes, they can mix →
per-orderline
If you're not sure, pick per-delivery. It's the safer default and works for any downstream system because each delivery is internally consistent.
Typical separations
| Situation | Typical variant |
|---|---|
| Legacy ERP still owns invoicing — each invoice is per fulfilment, so each invoice must come from one warehouse | per-delivery |
| A WMS or 3PL portal consumes Hantera deliveries one at a time and expects every line to be picked at the same location | per-delivery |
| Couriers / shipping integrations assign one label per delivery, and warehouses ship independently | per-delivery |
| A modern WMS or 3PL with a per-line picking-order model that can mix source warehouses inside one outbound shipment | per-orderline |
| You want one fulfilment as the source of truth for "what's been shipped" and you track source warehouse per item for reporting | per-orderline |
In this model, when an order has 10 items where 7 are at warehouse A and 3 are at warehouse B:
- Under
per-delivery, you end up with two deliveries, picked and shipped independently. - Under
per-orderline, you end up with one delivery carrying both lines, each labelled with its source warehouse.
Variant is install-time, not runtime
You install one variant per Hantera instance. Switching variants is a re-install — existing orders keep the metadata they were created with, but new orders use the new model.
Where it fits
The app fires on OnOrderValidate after every order mutation, so the routing decision is automatically reapplied whenever the order changes — adding lines, changing quantities, cancelling a delivery, or even just clearing inventoryKey back to auto_assign on a delivery to "re-route" it.
Shared behaviour across variants
All variants share these characteristics:
- Channel-keyed, country-aware priorities. Each channel can have a different ordered list of warehouses per country. A Swedish channel and a German channel can route Swedish customers through completely different priority chains.
- The
auto_assigntrigger key. Anything that creates or edits an order — an HTTP ingress, an ERP integration, a portal agent, a CSV importer — can setinventoryKey: "auto_assign"to ask the app to resolve a real warehouse. - Single-fulfiller preference. When the highest-priority warehouse cannot cover a whole line but a lower-priority one can, the lower-priority warehouse wins. Picking from one place is operationally cheaper than splitting.
- Best-effort allocation. Partial coverage produces partial reservations; unfulfilable units stay on the country's primary warehouse as back-order pressure.
- Automatic stock reservations across the order lifecycle — reserve on open/processing, unreserve on cancel or inventory clear, unreserve + setPhysicalStock on completion.
- Inventory-date aware. Each delivery's
inventoryDatedrives the stock lookup horizon, so pre-orders that include incoming shipments can coexist with urgent orders that only consider physical stock.
What you do, what the app does
| Activity | Who does it |
|---|---|
| Configure channel-country inventory priorities | You (in the portal's channel editor, contributed by this app) |
Tag new deliveries with inventoryKey: "auto_assign" | Whatever creates the order (ingress, ERP integration, portal, import, etc.) |
Resolve auto_assign to a real warehouse based on stock and priorities | The app |
| Split or move order lines when multiple warehouses are needed (per-delivery variant only) | The app |
| Place / release stock reservations | The app |
| Trigger a re-routing (e.g. after stock arrival) | Anyone — set inventoryKey back to auto_assign on the affected delivery and save. The app re-runs. |
Available documentation
- Per-Delivery Variant — the currently shipping variant. Includes configuration, the auto-assignment algorithm in operator terms, back-order behaviour, and reservation lifecycle.
- Per-Orderline Variant — pending implementation.
See also
asset.product— the source of SKU stock that the routing algorithm queries.- Activity log and the standard Hantera Order graph — the routing decisions surface as ordinary delivery / order-line mutations, visible alongside everything else on the order.