The first time a client asked me why MRP was telling them to buy 4,000 units of a part they already had on the shelf, I learned more about Acumatica's planning engine in a week than the documentation had taught me in a year. Planned orders are the output of MRP, but understanding why a specific planned order exists means understanding the inputs the regeneration run consumed — and most "MRP is wrong" tickets turn out to be "the inputs were wrong."
This post walks through how the MRP regeneration in the Acumatica Manufacturing Edition builds planned orders, where the data lives, and the diagnostic path I follow when the output looks insane.
What a planned order actually is
MRP in Acumatica is a full regeneration, not a net-change engine. When you run Regenerate MRP (AM505000), the engine wipes the previous plan and rebuilds it from scratch: it nets gross requirements (sales orders, production demand from higher-level orders, forecasts) against supply (on-hand quantity, open purchase orders, open production orders), explodes BOMs level by level, offsets by lead time, and writes the shortfall as planned orders into the AMRPPlan and related tables.
A planned order is a suggestion, nothing more. It has no document number in PO or Production terms, it reserves nothing, and it disappears on the next regeneration if the conditions that created it change. It only becomes real when someone fires it from MRP Display (AM400000) — at which point Acumatica creates an actual purchase order line or production order, and the next MRP run sees that as supply instead of re-suggesting it.
The inputs that actually drive the numbers
When a planned order quantity or date looks wrong, the cause is almost always one of these, roughly in order of how often I've seen it:
- Item replenishment settings. The Manufacturing tab and replenishment settings on the stock item — source (Purchase vs Manufacture), lot size, minimum/maximum order quantity, and safety stock. A minimum order quantity of 5,000 will happily turn a demand for 12 units into a planned order for 5,000.
- Lead times. Purchase lead time on the vendor or item, plus the MRP grace period. If lead time is zero, everything looks feasible; if it's wrong, action dates drift into the past and you get "past due" planned orders on day one.
- Warehouse participation. Each warehouse has an MRP flag. Demand in a warehouse excluded from MRP simply doesn't exist to the engine — a classic source of "MRP missed this sales order."
- Forecast and sales order consumption. If you load forecasts and also have real sales orders, the consumption settings decide whether they stack or the orders consume the forecast. Getting this wrong doubles demand.
- BOM effectivity. The engine explodes the BOM that is effective on the planned date, not today's date. A future-dated BOM revision changes component requirements for orders planned past its start date.
Before staring at planned orders, open MRP Exceptions. Move-in, move-out, expedite and cancel recommendations against existing supply are usually more actionable than the raw plan, and they tell you what MRP thinks about the orders you already have.
Tracing a single planned order
MRP Display gives you pegging: select a planned order and drill into the requirements that generated it. I still sometimes go to the database when the pegging looks off, because seeing the raw plan rows makes the netting logic obvious:
SELECT InventoryID, SiteID, PlanDate, ActionDate,
BaseQty, Type, RefNoteID
FROM AMRPPlan
WHERE CompanyID = 2
AND InventoryID = (SELECT InventoryID FROM InventoryItem
WHERE InventoryCD LIKE 'BRKT-100%')
ORDER BY PlanDate;
Reading supply and demand rows in date order for one item is the fastest way I know to answer "why did it suggest this quantity on this date." You can see the running balance dip below safety stock and the planned order appear exactly where the engine decided it had to.
Firing planned orders programmatically
On one project the planners wanted approved planned orders converted automatically overnight rather than clicked through MRP Display. The supported way is the same as any mass action: instantiate the graph, set the filter, mark rows selected, and invoke the action. Roughly:
var graph = PXGraph.CreateInstance<MRPEngine>(); // MRP display graph
foreach (AMRPDetail row in graph.Detailrecs.Select())
{
if (row.Type != MRPPlanningType.PlannedOrder) continue;
if (ShouldFire(row)) // your approval rule
{
row.Selected = true;
graph.Detailrecs.Update(row);
}
}
graph.Actions["CreateOrders"].Press(); // fires selected rows
Two gotchas from doing this in production. First, run it on a processing schedule after the nightly MRP regeneration completes, never overlapping — firing against a half-built plan creates duplicates. Second, log every fired order with its pegged demand; when a planner asks "why did the system buy this," you want an answer that doesn't involve reconstructing last Tuesday's plan.
Performance and scheduling the run
Regeneration is heavy — it locks planning tables and chews CPU roughly in proportion to BOM depth times active items times open orders. Practical rules I follow: run it once nightly via an automation schedule during the quietest window; keep BOMs shallow where the engineering allows it (phantoms are cheaper than real subassembly levels); and archive or close stale sales orders and production orders, because MRP dutifully plans for demand from 2023 if you leave it open.
If the run takes more than an hour on a mid-size dataset, look at SQL before looking at Acumatica settings — missing index maintenance on the MRP tables shows up here first.
Wrapping up
Planned orders are deterministic: same inputs, same plan. Every "MRP is broken" investigation I've done ended in a data problem — a lot size, a lead time, a warehouse flag, an open order someone forgot to close. Learn to read the plan rows for a single item in date order, fix the input, regenerate, and the suggestion fixes itself. Treat the planned order as the messenger, not the problem.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.