DEV Community

Tom
Tom

Posted on

Reject a Partial Order Import Before It Creates Warehouse Work

A file import can contain one valid row followed by a row that cannot be processed. If the importer creates work as it reads, the first row may already be accepted when the second one fails. The operator then has to discover which part of the file took effect before deciding what to retry.

This runnable teaching example from YX Fulfillment uses an explicit policy: validate every row in a small batch before accepting any of its rows. It models one account and already parsed JavaScript values, not the company's production integration.

Validate into a plan before applying it

The input contract requires nonempty, unpadded string identifiers, known SKUs and positive integer quantities. A line is identified by its order and line reference together. The importer rejects duplicate line keys within the batch instead of silently merging them.

Save this as order-import-demo.cjs and run node order-import-demo.cjs. It uses the Node.js strict assertion API.

const assert = require('node:assert/strict');
const knownSkus = new Set(['MUG-WHITE', 'POUCH-NATURAL']);
const acceptedRows = [];

function validateBatch(rows) {
  assert.ok(Array.isArray(rows) && rows.length > 0);
  const seen = new Set();
  return rows.map(row => {
    assert.ok(row && typeof row === 'object' && !Array.isArray(row));
    const { orderId, lineId, sku, quantity } = row;
    for (const value of [orderId, lineId, sku]) {
      assert.ok(typeof value === 'string' && value.length > 0);
      assert.equal(value, value.trim(), 'Padded identifier');
    }
    assert.ok(knownSkus.has(sku), 'Unknown SKU');
    assert.ok(Number.isSafeInteger(quantity) && quantity > 0);
    const key = JSON.stringify([orderId, lineId]);
    assert.ok(!seen.has(key), 'Duplicate order line');
    seen.add(key);
    return Object.freeze({ orderId, lineId, sku, quantity });
  });
}

function acceptBatch(rows) {
  const plan = validateBatch(rows);
  acceptedRows.push(...plan);
  return plan.length;
}

const first = { orderId: 'order-1', lineId: '1', sku: 'MUG-WHITE', quantity: 1 };
const second = { ...first, lineId: '2', sku: 'POUCH-NATURAL' };
assert.throws(() => acceptBatch([first, { ...second, sku: 'UNKNOWN' }]));
assert.equal(acceptedRows.length, 0);
assert.throws(() => acceptBatch([first, { ...second, quantity: '2' }]));
assert.throws(() => acceptBatch([first, { ...first }]));
assert.throws(() => acceptBatch([{ ...first, orderId: ' order-1' }]));
assert.throws(() => acceptBatch([{ ...first, quantity: 0 }]));
assert.equal(acceptedRows.length, 0);
assert.equal(acceptBatch([first, second]), 2);
assert.equal(acceptedRows.length, 2);
assert.equal(acceptedRows[1].sku, 'POUCH-NATURAL');
console.log('Rejected batches accepted no rows; the valid batch accepted both lines.');
Enter fullscreen mode Exit fullscreen mode

The first test is the important failure path: a valid first row followed by an unknown SKU leaves no accepted rows. The quantity test also rejects a numeric string; converting text fields belongs in a defined parsing step, rather than an accidental coercion inside warehouse acceptance.

Keep validation free of side effects

The validation function constructs values in memory. It does not reserve stock, write acceptance records or call a warehouse API. That separation makes the rejection test possible.

The array used here is a demonstration, not a durable transaction. A production importer needs a defined persistence boundary, restart behavior and duplicate-import handling. If downstream work is asynchronous, decide how the accepted batch and the work awaiting delivery remain consistent across a failure. Validating the file does not prove that every later warehouse request succeeded.

A provider may deliberately accept valid orders while rejecting others. That is a different contract and needs an explicit result per accepted and rejected unit, plus a retry rule. The point is to choose and test the contract before operators encounter a partially processed file.

For an integration acceptance test, include a valid first row and an invalid later row, then inspect the resulting accepted records and warehouse work. A helpful error message is only part of the result; the operator also needs to know exactly what changed.

Reviewing a complete import batch before releasing work

Reviewing the complete batch before acceptance. Illustrative scene.

Top comments (0)