Acumatica · Reports

Acumatica Inventory Valuation Snapshot Report

How to build and run an Acumatica inventory valuation snapshot — point-in-time inventory value, with filters for warehouse, item class, and costing method.

John Kihiu12 min read

A CFO asked me once why the inventory valuation total on their balance sheet didn't match what the Inventory Valuation report showed for the same date. Both numbers were technically correct. They were answering different questions: one was a point-in-time GL balance, the other was a live recalculation against current item costs that had moved since the period closed. Inventory valuation reporting in Acumatica is one of those areas where understanding what a report is actually computing matters more than knowing which buttons to click.

Live valuation vs snapshot valuation are answering different questions

Acumatica's standard Inventory Valuation report, run without care, recalculates valuation using each item's current cost layers and current status. Run it for "as of" a date three months ago, and depending on costing method and whether cost layers have since been consumed or adjusted, you can get a number that does not match what the GL actually posted at that historical date. This isn't a bug; it's the report doing exactly what it's built to do, which is show current valuation logic applied against historical quantities, not literally replay history.

A true valuation snapshot needs to freeze both quantity and unit cost at a specific point in time and never recompute against later cost changes. That's a materially different query, and it's the one auditors actually want when they ask for "inventory valuation as of period end."

C# · building a frozen snapshot from INTran history
// Reconstruct on-hand qty and cost AS OF a period by summing all
// transactions up to and including that period, per item/site/lot.
PXSelectGroupBy<INTran,
    Where<INTran.finPeriodID, LessEqual<Required<INTran.finPeriodID>>>,
    Aggregate<
        GroupBy<INTran.inventoryID,
        GroupBy<INTran.siteID,
        Sum<INTran.qty,
        Sum<INTran.tranCost>>>>>>
    .Select(Base, asOfPeriodID);

The key discipline: sum TranCost, the actual recorded transaction cost at the time each movement posted, never the item's current standard or average cost. Joining historical quantity to today's cost is exactly the bug that produces a valuation report that doesn't reconcile to the GL.

Costing method changes what "unit cost" even means at a point in time

FIFO tracks discrete cost layers consumed in order, so a snapshot needs to know which layers were still open at the snapshot date, not just a blended average. Average costing recomputes a moving average with every receipt, so the "unit cost" at a historical date is whatever the running average was after the last receipt before that date, which the item's cost history table tracks, not the item master's current value. Standard costing is the simplest to snapshot because the standard cost is a deliberately set, relatively static value, but standard costing introduces its own variance accounts that a valuation snapshot needs to account for separately if you want the snapshot to tie to GL inventory asset accounts exactly.

INItemCost and the cost history tables are where the real historical data lives

Don't try to reconstruct historical average cost from current INItemCost values alone. Acumatica retains cost layer and cost history detail (particularly under FIFO and for landed cost adjustments) that lets you reconstruct what a specific lot's cost actually was at a point in time. Building a snapshot report against only the item's current cost fields instead of the transaction and layer history is the single most common mistake I've seen in custom valuation reports, and it's the direct cause of the CFO's mismatch story above.

Tying the snapshot back to the GL inventory account

A valuation snapshot that doesn't reconcile to the GL's inventory asset account balance for the same date isn't useful for audit purposes, it's just a number. The reconciliation check that actually catches problems: sum the snapshot's extended value (quantity times historical unit cost) per site, and compare it against the GL account balance for the corresponding inventory account and branch as of that period, pulled straight from GLTran.

C# · reconciliation check against the GL
decimal glInventoryBalance = PXSelectGroupBy<GLTran,
    Where<GLTran.accountID, Equal<Required<GLTran.accountID>>,
    And<GLTran.finPeriodID, LessEqual<Required<GLTran.finPeriodID>>>>,
    Aggregate<Sum<GLTran.debitAmt>>>
    .Select(Base, inventoryAcctID, asOfPeriodID)
    .RowCast<GLTran>().Sum(r => (r.DebitAmt ?? 0m) - (r.CreditAmt ?? 0m));

decimal snapshotValue = /* sum of snapshot extended values for same account/branch */;
decimal variance = glInventoryBalance - snapshotValue;
// A nonzero variance here is worth investigating BEFORE handing the
// report to an auditor, not after they find it themselves.

A small persistent variance is often explainable, in-transit inventory, landed cost accruals not yet allocated, a timing difference between physical receipt and GL posting. A large or growing variance usually means a costing method edge case (a negative-quantity sale that later got a cost adjustment, for instance) that the snapshot query isn't accounting for correctly.

Wrapping up

The standard Inventory Valuation report and a true point-in-time valuation snapshot answer different questions, and conflating them is how you end up explaining a mismatch to a CFO after the fact instead of before. Build snapshots from transaction-level cost history, never from an item's current cost fields, respect that FIFO and average costing carry genuinely different historical cost semantics, and always reconcile the snapshot against the GL inventory account before treating it as audit-ready.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.