Inventory & Planning

Low-Level Codes: Why Every Item Is Planned Exactly Once

User Solutions TeamUser Solutions Team
|
7 min read

A low-level code is the deepest level at which an item appears anywhere in any bill, and planning strictly in ascending low-level-code order is what guarantees every item is netted exactly once, against all of its demand. In EDGEBIC by User Solutions, that single number decides the order a multi-level run works in, and getting it wrong produces a failure that looks exactly like success: a flat, healthy balance on a part that is about to run out.

This post explains why an order of planning has to exist, what the code is, how it is computed across a shared component, and why a run expands beyond the products you name. It sits under the EDGEBIC planning guide and follows exploding a parent's demand into component demand.

Netting One Item Is Easy. Netting a Hundred Is Only Easy in the Right Order

Netting a single item is arithmetic: demand in, on-hand and incoming supply out, safety buffer protected. Netting a hundred items that demand each other is the same arithmetic, but it is only correct if each item is netted after everything that could demand it.

The reason is that dependent demand does not exist until its parent has been planned. Before a gearbox has an order, the sub-assemblies beneath it have no requirement, so the plate beneath those has no requirement either. Nothing has yet told the plate it is wanted.

Plan the plate at that moment and it nets against whatever demand happens to exist so far, reports a balance it has not earned, and fires no suggestion. The remaining demand appears afterwards, when the levels above it are planned, and by then the plate has already been declared comfortable. Nothing errors. There is no warning. The balance simply lies.

What the Code Is

The low-level code fixes that with one rule: the deepest level at which an item appears anywhere in any bill.

End items are level 0. Their direct components are level 1. A component of a level-1 item is level 2, and so on. When an item appears in several bills at several depths, its code is the deepest of them, not an average and not the first one found.

The word doing the work is anywhere. The code is global and singular, one number per physical part across the whole product structure. That is the property the ordering depends on, and it is why a per-routing depth cannot stand in for it. A routing's own step levels describe depth inside that one routing for that one end product; the same shared part can carry two unrelated numbers in two routings. The low-level code is the maximum over every appearance.

A Worked Example: The Shared Plate

Two end items. A widget takes one plate directly. A gearbox takes a casing, the casing takes two subframes, and each subframe takes four plates.

ItemDepth under widgetDepth under gearboxLow-level code
Widget0-0
Gearbox-00
Casing-11
Subframe-22
Plate133

The plate appears at depth 1 under the widget and depth 3 under the gearbox. Its low-level code is 3, so the planning order runs widget and gearbox, then casing, then subframe, then plate.

Now suppose both end items release orders for 30 widgets and 10 gearboxes on the same day.

OrderItemDemand it holds when plannedIt explodes to
1Widgetindependent onlyplate + 30
2Gearboxindependent onlycasing + 10
3Casing10subframe + 20
4Subframe20plate + 80
5Plate110nothing, it is bought

The plate is netted once, against 110, with both parents pegged to it. Plan it at "depth 1" instead, using its position in the widget's routing, and it would have been netted against 30, reported comfortable, and the 80 from the gearbox branch would have arrived as a surprise several levels and several days later.

Planning One Item Pulls In Its Family

This is the behavior planners notice first and misread as inefficiency.

Name a single product for a run and EDGEBIC expands it to that product's whole family: everything it is made from, and everything made from it. Then it orders that family by low-level code.

The upward half is the one that gets forgotten, and forgetting it reintroduces exactly the blindness the multi-level run removes, one level up. Planning a component requires every parent that could demand it to have been planned first, so asking to plan a plate must pull in the widget and the gearbox tree that consume it. Walk only downwards and the plate is planned against no dependent demand at all and reports a flat, healthy balance.

Products that appear in no bill at all still plan, at level 0, on their own.

The other option is simply to name nothing. Leaving the product list empty runs the plan over every active product, which is the regenerative run and the usual default. There is no net-change mode; every run replans from scratch.

When a Bill Contains Itself

Occasionally a routing leads back to its own product, directly or through several levels. That is a cycle, and a bill that contains itself has no finite plan at all.

EDGEBIC reports these rather than silently dropping them. The affected products are named, and the cyclic-bill message is listed ahead of every other message in the worklist, because an item with no plan cannot be judged by any other message about it. The correction is in the routing that creates the loop.

A step whose product is the same as the end item it belongs to is ignored rather than treated as a level, so a self-reference on one line does not take the whole product out of the plan.

Why This Matters to a Planner

You will rarely type a low-level code or set one, and that is the point: it is derived, not maintained. What it buys you is the guarantee behind every number on the worklist.

When the plan says a shared component needs 110 units, the low-level code is your assurance that 110 is all of the demand rather than the part of it that happened to be computed first. And when a run pulls in products you did not ask for, that is the same guarantee doing its job.

The general failure mode in this part of a planning system is worth stating plainly: no shortage is the outcome that looks like success. A comfortable balance on a shared part is the thing to be suspicious of, and the ordering rule is what makes it trustworthy. Next, read reading MRP action messages for what the plan does with the shortages it finds, or what is MRP for the method's fundamentals.

Expert Q&A: Deep Dive

Q: I want to plan just one purchased component. Why does the run pull in a dozen other products?

A: Because planning a component correctly requires every parent that could demand it to have been planned first. Naming one product expands the run to its whole family, everything it is made from and everything made from it, then orders that family by low-level code. Walking only downwards would plan your component against no dependent demand at all and report a flat, healthy balance, which is the exact blindness the multi-level run exists to remove. The expansion is the correct answer, not an inefficiency.

Q: Our routings already carry a level number on each step. Can that be used instead?

A: No, and it is a tempting mistake because it is already an integer called a level. A routing step's level is depth within that one routing, scoped to a single end product, and it has no opinion about anyone else's bill. A shared plate can carry level 1 in one routing and level 3 in another, two unrelated numbers for one physical part. A low-level code is global and singular, taken as the maximum across every appearance, which is exactly the property the planning order depends on.

Frequently Asked Questions

Ready to Transform Your Production Scheduling?

User Solutions has been helping manufacturers optimize their production schedules for over 35 years. One-time license, 5-day implementation.

User Solutions Team

User Solutions Team

Manufacturing Software Experts

User Solutions has been developing production planning and scheduling software for manufacturers since 1991. Our team combines 35+ years of manufacturing software expertise with deep industry knowledge to help factories optimize their operations.

Let's Solve Your Challenges Together