Once you run more than one warehouse, "which site fulfills this?" becomes an algorithm. A clean start is a scoring function: each candidate gets a score, highest wins.
function pickWarehouse(order, warehouses) {
let best = null, bestScore = -Infinity;
for (const w of warehouses) {
if (!w.canHandle(order)) continue; // oversized, battery SOP, etc.
const score =
0.5 * stockCoverage(w, order) + // does it have every SKU?
0.3 * proximityScore(w, order.destination) +
0.2 * (1 - w.utilization); // prefer a less loaded site
if (score > bestScore) { bestScore = score; best = w; }
}
return best;
}
The weights are a starting point, not truth. Tune them to what actually hurts: split shipments, slow lanes, or overloaded sites.
Two gotchas:
Capability gates before scoring. A battery or oversized item must be filtered out of warehouses that cannot legally or physically handle it before you score. Scoring an ineligible site just gives a wrong answer faster.
Partial stock. If no single warehouse covers the whole order, decide explicitly whether to split-ship or hold. Silent splitting doubles freight and confuses customers.
We run three sites in China (Shenzhen for oversized and sea-air, Suzhou for consolidation, Dongguan for ecommerce one-piece), and the routing logic is mostly about matching the order to the site actually built for it.
Top comments (0)