We ordered 25 dozen and received 300
A purchase order for 25 dozen jars was received as 300 dozen. The vendor bill was correct and the PO showed fully billed. Inventory was overstated by thousands of units, and nobody could say where the difference had gone.
Where did the variance go?
An item purchased by the dozen and stocked by the each. The PO said 25 dozen — 300 jars. The item receipt recorded 300 dozen — 3,600 jars. The vendor billed 300 jars at the right price and the PO closed as fully billed. So the bill was right, the receipt was wrong, and the general ledger had to put the difference somewhere.
It went to received not invoiced. The receipt credited that account for 3,600 jars at cost; the bill debited it for 300. The difference sat there, stranded, along with thousands of phantom jars on the shelf in inventory.
The cause
The receipts came from a custom receiving screen. It looked up the quantity left to receive with SuiteQL, which returns line quantities in the item’s stock unit. It then wrote that number into the receipt line, which is entered in the line’s purchase unit:
// remaining comes back in stock units (eaches): 300
const remaining = row.quantity_remaining;
// ...but the receipt line's unit is the PO line's unit (Dozen)
receipt.setSublistValue({ sublistId: 'item', fieldId: 'quantity',
line: i, value: remaining }); // 300 DOZEN
For items bought and stocked in the same unit, the two numbers are identical, which is why it went unnoticed. Only items with a different purchase unit were affected, and the error was exactly the conversion rate — twelve times, in this case.
The fix converts once, explicitly, using the unit conversion rate on the line:
const rate = Number(row.conversion_rate) || 1; // eaches per purchase unit
const inPurchaseUnits = remaining / rate; // 300 / 12 = 25
Finding every receipt it touched
One bad receipt usually means others. This finds receipt lines where the transaction unit differs from the item’s stock unit, which is the population the bug could have affected:
SELECT t.tranid, BUILTIN.DF(tl.item) AS item, tl.quantity,
BUILTIN.DF(tl.units) AS line_unit, u.conversionrate
FROM transactionline tl
JOIN transaction t ON t.id = tl.transaction
JOIN item i ON i.id = tl.item
JOIN unitstypeuom u ON u.internalid = tl.units
WHERE t.type = 'ItemRcpt'
AND tl.units IS NOT NULL AND tl.units <> i.stockunit
Two more receipts turned up. One was in an open period and was corrected directly. The other was in a closed period and needed an inventory adjustment.
The part a journal entry can’t fix
The adjustment relieved the extra units at the item’s current average cost, not the cost they were received at, which left a small residual in received-not-invoiced. The obvious fix is a journal entry to clear it. That clears the GL and leaves the item’s average cost wrong, so every future sale of that item carries the error into cost of goods.
The right tool was the inventory adjustment worksheet, used to revalue the item: same quantity, corrected total value. That recalculates the average cost and posts the offset that clears the variance in one step. One setting matters: run the worksheet against the last transaction of the day, or it counts the earlier adjustment twice.
Preventing the next one
- Any custom screen that reads quantities with SuiteQL and writes them through the record API must convert units explicitly, and its tests must include an item whose purchase unit differs from its stock unit.
- A received quantity that is an exact multiple of the ordered quantity — twelve times, ten times — is a unit bug until proven otherwise. Flag it at receipt.
- Received-not-invoiced deserves a monthly look by item and PO. Stranded variances there are almost always a receiving or billing error with a cause you can find.
Related: receiving a hundred packing lists from one scan, and blanket POs that reconcile.