Inbound receiving is where fulfillment software is quietly bad. The core task is boring: compare what arrived against what you expected, and surface the diff. Model it as two lists and a join.
function reconcile(expected, received) {
const bySku = new Map();
for (const line of expected) bySku.set(line.sku, { expected: line.qty, received: 0 });
for (const line of received) {
const row = bySku.get(line.sku) || { expected: 0, received: 0 };
row.received += line.qty;
bySku.set(line.sku, row);
}
const diffs = [];
for (const [sku, r] of bySku) {
if (r.received !== r.expected) {
diffs.push({ sku, expected: r.expected, received: r.received, delta: r.received - r.expected });
}
}
return diffs; // empty means a clean receipt
}
A non-empty diffs array is the whole point: it is your exception queue.
-
delta < 0= short shipment. -
delta > 0= over-ship or mislabeled carton. - A SKU in
receivedbut notexpected= mixed carton.
The discipline that makes this work is upstream: every inbound must be created from a SKU list, not free text. If receiving staff can type an arbitrary item, reconciliation is meaningless because the expected side is a guess.
Do this well and quality problems get caught at the dock, where they cost a phone call. Do it badly and they reach a customer, where they cost a refund and a bad review.
Top comments (0)