Traceability is a discipline, not a checkbox on the item screen. Turning on Lot/Serial tracking for an item is one line of setup; being able to answer "which customers received material from this specific vendor lot" in under five minutes during a recall is the actual deliverable. This article covers how Acumatica models lot and serial tracking, where it gets configured, and the reporting and customization patterns that make traceability usable instead of theoretical.
Lot/Serial class setup
Tracking behavior in Acumatica is defined on a Lot/Serial Class, which is then attached to one or more Inventory Items. The class controls the assignment method — Manual, where the warehouse worker types or scans the lot/serial number in, or Automatic, where Acumatica pulls the next value from a numbering sequence — and the tracking method, which determines whether the system tracks by lot (a batch, sharing one identifier across a quantity) or by serial (unique identifier per unit, quantity locked to 1).
The class also sets the tracking direction: None (tracking exists but isn't enforced on transactions), Receipts Only, Issues Only, or Receipts and Issues, which is the setting that actually gives you end-to-end traceability. Get this wrong at go-live and you end up with lot numbers that were captured on receipt but silently dropped on the sales order — a gap that only becomes visible during an audit or a recall, which is the worst possible time to discover it.
Assignment and status through the document flow
Lot and serial numbers get assigned or consumed on the documents that move inventory: Purchase Receipts, Production Orders (for manufactured items), Transfers, Issues, and Sales Order Shipments. Each lot/serial record carries a status — Available, Allocated, In Transit, Sold, Expired, Damaged, and a few others depending on configuration — and Acumatica enforces that status transitions follow the actual movement of goods. You cannot ship a lot that's already marked Sold, and you cannot allocate a lot that's Expired, assuming expiration tracking is turned on for the item.
For lot-controlled items with shelf life, the Expiration Date lives on the Lot/Serial Number Master Record, set at receipt (either entered manually or calculated from a fixed shelf-life period on the item). Sales order and shipment screens can be configured to warn or block on expired or near-expiry lots, which matters a lot more in distribution and food/pharma verticals than it does in, say, spare parts.
The recall workflow: where-used and history
The entire point of lot/serial tracking is answering two questions fast: forward traceability ("this lot is bad, who has it") and backward traceability ("this finished good failed, what raw material lots went into it"). Acumatica supports both through the Lot/Serial Where-Used inquiry and Lot/Serial History, which walk the transaction chain from receipt through production consumption (if applicable) to shipment, and surface the customer, sales order, and shipment number tied to each unit shipped.
In practice, this inquiry is the thing a QA or compliance team actually opens during an incident, so it's worth testing it with real transaction volume before go-live rather than assuming it will perform fine on day one. On implementations with tens of thousands of lot transactions a year, the out-of-the-box inquiry can get slow enough that a generic inquiry or SQL-backed report tuned for the actual query pattern — filter by lot number, return shipment and customer — is a worthwhile add-on.
Every manual adjustment to a lot's quantity or status should go through a Reason Code that explains why. Skipping this on "quick fixes" during data cleanup is how a recall trace ends up with unexplained quantity gaps that nobody can account for six months later.
Customizing lot validation on the sales order
A common ask is enforcing business rules Acumatica doesn't ship out of the box — for example, blocking shipment of a lot within N days of its expiration date, even if it hasn't technically expired yet. That's a graph extension on the Shipment or Sales Order screen, validating against the lot's expiration date before the line can be confirmed.
public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry>
{
[PXOverride]
public void Persist(Action del)
{
foreach (SOShipLine line in Base.Transactions.Select())
{
if (string.IsNullOrEmpty(line.LotSerialNbr)) continue;
INLotSerialStatus lotStatus = SelectFrom<INLotSerialStatus>
.Where<INLotSerialStatus.lotSerialNbr.IsEqual<P.AsString>
.And<INLotSerialStatus.inventoryID.IsEqual<P.AsInt>>>
.View.Select(Base, line.LotSerialNbr, line.InventoryID);
if (lotStatus?.ExpireDate != null &&
lotStatus.ExpireDate < Base.Accessinfo.BusinessDate.Value.AddDays(30))
{
throw new PXSetPropertyException(
"Lot {0} expires within 30 days and requires supervisor override before shipment.",
PXErrorLevel.Warning, line.LotSerialNbr);
}
}
del();
}
}
The same pattern — join INLotSerialStatus against INTran or the shipment/order lines — is the basis for most custom lot-trace generic inquiries. Treat field names as illustrative rather than gospel; verify the exact DAC and field names against the installed version before shipping, since Inventory-module schema has shifted slightly across major releases.
Lot vs. serial: behavior differences
| Behavior | Lot tracking | Serial tracking |
|---|---|---|
| Quantity per identifier | Any quantity (a batch) | Always 1 unit |
| Typical use case | Chemicals, food, raw materials, batch manufacturing | Equipment, electronics, warranty-tracked items |
| Expiration tracking | Common, shelf-life driven | Rare, usually warranty-driven instead |
| Split/merge on transactions | Supported (partial lot quantities) | Not applicable — each unit is discrete |
| Assignment method typically used | Manual (vendor-supplied lot number) or Automatic | Automatic numbering sequence, or manual for vendor serials |
Wrapping up
Lot and serial tracking in Acumatica is cheap to turn on and easy to get wrong in ways that don't show up until the day you need it most. Pick lot or serial per item based on whether you need batch-level or unit-level traceability, get the assignment method and tracking direction right on the Lot/Serial Class before go-live, and treat the where-used inquiry as something to load-test rather than assume. None of that is complicated — it's just easy to skip when the item screen checkbox looks like the whole job. If you are stuck on something specific, reach out or keep reading through the rest of the Acumatica blog.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.