How to Set Up a Multi-Level BOM for a Product With Sub-Assemblies
A step-by-step build of a multi-level BOM for a product with sub-assemblies, using one worked example the whole way through. Covers which sub-assemblies earn their own BOM, how to number the levels, why quantities are per parent and not per finished unit, and how to check the explosion before you buy anything.
Quick summary: To set up a multi-level BOM, build it from the bottom up — give every sub-assembly you actually stock, build or buy separately its own part number and its own BOM, number the levels from 0 (the finished product) downwards, and enter each component quantity per immediate parent rather than per finished unit. Then explode the structure for a real build quantity and reconcile the totals against a physical unit before you raise a single purchase order.
The difficulty is never conceptual. Everyone knows a finished product contains sub-assemblies and those contain parts. It is procedural: which things get their own BOM, what goes in the quantity column, and what happens when two products share a sub-assembly. Get those wrong and the structure looks tidy on screen while quietly ordering twice the castors you need.
The worked example throughout is a mobile welding fume extractor, MFE-450: a wheeled cabinet with a filter housing, a fan and motor pack, a control panel and an extraction arm. The same manufacturer builds an MFE-900 twin-housing version and a DE-300 bench dust extractor, and two sub-assemblies are shared across them. All figures are illustrative; the point is the structure.
Step 1: map the product the way you build it, not the way it is drawn
Before opening a spreadsheet or a system, walk the build and note each point where a group of parts becomes a thing with a name. Here that is five: someone welds and paints a chassis, someone makes up a wiring loom on a jig, someone stuffs and wires a control panel, someone bolts the motor to its mount plate and fits the impeller, someone fits cartridges into a housing shell. Each is a stopping point where a part-finished item can sit on a shelf overnight.
A multi-level BOM should mirror your production process, not your CAD tree. Engineering groups parts by function; production groups them by the order in which hands touch them. Copy the engineering structure across unchanged and you get levels nobody ever builds, issues or counts.
Write the map as an indented list — paper is fine. One question per group: does anything ever happen to this group on its own?
Step 2: decide which sub-assemblies earn their own BOM
Not every cluster of parts deserves a level. A sub-assembly earns its own BOM if at least one of these is true:
- You stock it. It has a shelf location, a count and a stock figure.
- You build it separately. It has its own works order, or it is made in batches ahead of final assembly.
- You buy it made up. A subcontractor supplies it as one line on a purchase order.
- It is shared. Two or more products consume it, so you want to maintain it once.
- You sell it. It goes out as a spare or a service exchange unit.
If none apply, keep the parts on the parent BOM. A level that exists only for tidiness costs a part number, a stock record, a transaction at build time and one more place for errors to hide. If you still want the grouping visible on the drawing without inventing a stocked item, that is what a phantom is for — the depth question, phantoms and low-level codes included, is worked through separately in BOM levels explained.
That gives four first-level sub-assemblies: chassis (stocked, shared with the DE-300), filter housing (built in batches), fan and motor pack (built separately), control panel (shared with the MFE-900, sold as a spare). The extraction arm is bought complete and never opened, so it stays a purchased component with no BOM beneath it. The wiring loom inside the panel is made in batches on a jig, so it earns a BOM too — pushing the structure to three levels deep.
Step 3: give every BOM one level and one parent
Numbering runs downwards from the finished item: level 0 is the sellable product, level 1 the things consumed directly to make it, level 2 the things consumed to make those, and onwards to raw materials. That much is convention and every system expects it. The part that decides whether your setup works is the mechanic underneath.
Each BOM describes one level only. Microsoft’s Dynamics 365 documentation describes the data model the same way: a single BOM covers a single level identified by a unique ID, and components may carry BOMs of their own that it simply references. Depth is not a longer list. It is BOMs pointing at BOMs.
So the MFE-450 BOM does not contain 80-odd parts. It contains six lines, four of them sub-assemblies with BOMs of their own, and the remaining seventy-odd parts appear only when you explode it. This is the fastest way to check an existing structure: if the level 0 sheet runs to eighty rows, someone has written a flat parts list with indentation in the first column. It will look like a multi-level BOM and behave like a single-level one, and the sub-assemblies inside it are not being shared with anything.
Step 4: build the BOMs bottom-up
Create the lowest-level BOMs first, then use those items as components on the level above. Odoo’s manufacturing documentation gives the same instruction for multilevel BoMs: “If starting from scratch, build the BoMs from the bottom up. Start with the lowest-level product BoMs, then include those products as components in higher-level BoMs.”
The reason is practical. Start at level 0 and every sub-assembly line points at a part number that does not exist yet, so you create stub records you later have to fix, or leave the line blank and forget it. Working upwards, everything you reference already exists with a unit of measure, a cost and a supplier. Here the order is: wiring loom → control panel, fan pack, filter housing, chassis → MFE-450.
Step 5: set quantity per parent, not per finished unit
This is the error that causes the most damage, and it is silent.
The quantity column means: how many of this component go into one of the item this BOM belongs to. Oracle’s JD Edwards documentation defines the Quantity Per field as “a number that indicates how many components you use to manufacture the parent item” — the parent item, not the end product.
The filter housing takes 3 cartridges. The MFE-900 uses 2 housings, so a finished MFE-900 contains 6 cartridges. Somebody edits the housing BOM while thinking about the MFE-900 and types 6 into the cartridge line:
| Product | Cartridges the BOM explodes to | Cartridges actually fitted |
|---|---|---|
| MFE-450 (1 housing) | 6 | 3 |
| MFE-900 (2 housings) | 12 | 6 |
Both products are now wrong by exactly 100%. Nothing errors. Purchasing buys double, stock builds up, and the variance surfaces months later as a stocktake discrepancy nobody can explain.
The discipline that prevents it: edit every BOM with only its own parent in your head. On the filter housing BOM, the only object that exists is one filter housing. Two related habits — state the base quantity (per 1 or per 100) at the top of every BOM and never mix conventions; and accept fractional quantities, because 0.4 kg of powder coat per chassis is a real line and rounding it to 1 inflates cost on every unit.
Step 6: check units of measure, scrap and consumables
A multi-level BOM multiplies. Anything wrong at level 3 is multiplied by the quantity at level 2, then again at level 1. A cable line entered in metres when the stock record is in millimetres does not cause a small error; it causes a thousandfold one. Check three things before going up a level:
- The stocking unit matches the BOM unit. If you buy cable on 100 m drums and issue it by the metre, the conversion belongs in the system, not in someone’s head.
- Scrap and yield sit where the loss happens. Lose 5% of gasket material at cutting and that belongs on the gasket line of the housing BOM, not in the finished-product quantity. At the wrong level it distorts costing on every product sharing that sub-assembly.
- Consumables are on the BOM or explicitly excluded. Pick one rule for solder, sealant, threadlock and gloves and apply it everywhere. Half in, half out makes a cost roll-up untrustworthy.
Step 7: handle sub-assemblies shared across products
Shared sub-assemblies are the main reason to build a multi-level BOM, and the main reason it needs care. The control panel (SA-CTL-04) sits on the MFE-450 and MFE-900; the chassis (SA-CHS-01) sits on the MFE-450 and DE-300. That means:
- One BOM, maintained once. When the contactor is superseded, you change one line and both machines follow. That is the entire payoff.
- Where-used becomes essential. Before changing a shared sub-assembly, answer the reverse question: what does this go into? Oracle’s JD Edwards documentation describes a Where Used Update program for changing multiple bills of material at once, for exactly this reason. If you cannot answer “which products contain part X” in under a minute, you do not have a multi-level BOM — you have several single-level ones that resemble each other.
- Variations need a new part number. If the MFE-900 needs a modified panel and the MFE-450 does not, create SA-CTL-05. Editing a shared sub-assembly to suit one product is the fastest way to break another.
- Demand arrives from several parents. The panel requirement is the sum across every product being built, plus spares sold directly. Anything planning it in isolation will under-order.
Assembled, the whole structure looks like this — note that level 0 is six lines, not eighty:
| Level | Part | Description | Qty per parent |
|---|---|---|---|
| 0 | MFE-450 | Mobile fume extractor | 1 |
| .1 | SA-CHS-01 | Trolley chassis assembly | 1 |
| …2 | WLD-100 | Chassis weldment | 1 |
| …2 | CAS-B100 | Castor, braked 100 mm | 2 |
| …2 | CAS-U100 | Castor, unbraked 100 mm | 2 |
| …2 | PC-RAL7016 | Powder coat, textured | 0.4 kg |
| …2 | BLT-M8 | Bolt, M8 x 25 | 8 |
| .1 | SA-FLT-02 | Filter housing assembly | 1 |
| …2 | HSG-450 | Housing shell | 1 |
| …2 | FLT-F9 | Filter cartridge, F9 | 3 |
| …2 | GSK-F9 | Cartridge gasket | 3 |
| …2 | LAT-TG | Toggle latch | 4 |
| .1 | SA-FAN-03 | Fan and motor pack | 1 |
| …2 | MTR-15 | Motor, 1.5 kW | 1 |
| …2 | IMP-280 | Impeller, 280 mm | 1 |
| …2 | MNT-PLT | Motor mount plate | 1 |
| …2 | AVM-30 | Anti-vibration mount | 4 |
| .1 | SA-CTL-04 | Control panel assembly | 1 |
| …2 | ENC-IP54 | Enclosure, IP54 | 1 |
| …2 | CNT-9A | Contactor, 9 A | 1 |
| …2 | SA-LOOM-01 | Wiring loom | 1 |
| …3 | CBL-3C | Cable, 3-core | 3.2 m |
| …3 | FER-15 | Ferrule | 24 |
| …3 | CON-M12 | Connector, M12 | 6 |
| .1 | ARM-3M | Extraction arm, 3 m | 1 |
| .1 | KIT-FAST | Fastener kit | 1 |
Step 8: explode it and check it before you buy anything
Exploding a BOM means walking down every branch and multiplying as you go: a level 3 requirement equals its own quantity per parent × its parent’s quantity per parent × the build quantity. This is not free in every system — Oracle notes that JD Edwards EnterpriseOne holds BOM data in a single-level format with no defined levels, so the system has to loop through iteratively to explode it into a multi-level structure. Run it for a batch of 40 MFE-450s and check a few lines by hand:
| Component | Chain | Expected total |
|---|---|---|
| Castor, braked | 2 × 1 chassis × 40 | 80 |
| Filter cartridge | 3 × 1 housing × 40 | 120 |
| Anti-vibration mount | 4 × 1 fan pack × 40 | 160 |
| Ferrule | 24 × 1 loom × 1 panel × 40 | 960 |
| Cable, 3-core | 3.2 m × 1 loom × 1 panel × 40 | 128 m |
| Powder coat | 0.4 kg × 1 chassis × 40 | 16 kg |
Four checks before this becomes purchase orders:
- Physical reconciliation. Count the castors, cartridges and latches on one finished machine and compare against the explosion divided by 40. Most quantity-per-parent errors die here.
- Order-of-magnitude scan. Anything 10×, 100× or 1,000× away from a sane number is a unit-of-measure fault, not a quantity fault.
- Loop check. No item may appear anywhere beneath itself. A circular reference makes an explosion run forever or silently truncate.
- Cost roll-up. Total levels 3 and 2 into each sub-assembly, then the sub-assemblies into the finished product. If the rolled-up material cost is £480 and you have been quoting against a £390 figure inherited from an old spreadsheet, that gap has been eating margin on every unit sold.
Spreadsheet or system: what actually breaks
A multi-level BOM is genuinely possible in a spreadsheet: one sheet per assembly, a level column, a parent column, and a lookup pulling sub-assembly totals upwards. Plenty of small manufacturers run this way for years. What breaks is not the arithmetic:
- Where-used. Answering “which products contain the 9 A contactor” means opening every sheet, so people stop asking and change parts blind.
- Version control. The shop floor works from a March printout; purchasing has a copy someone edited in April.
- Shared sub-assemblies. When a second product uses the chassis, someone copies the sheet instead of referencing it, and the two drift apart.
- Demand across parents. Netting the panel requirement across three products plus spares is manual arithmetic, done under pressure, once a week.
A right-sized operations system fixes those four: one record per item, referenced rather than copied, with where-used, revision history and an explosion that runs against live stock. That is a far smaller job than an ERP implementation — the middle ground for a business too messy for spreadsheets and not ready for a full ERP. The ongoing side, including change control and BOM ownership, is covered in bill of materials management.
When a multi-level BOM is the wrong answer
If you build one product, from parts bought loose, in one continuous operation, with nothing stocked part-finished, a single-level BOM is correct and extra levels only add transactions. The full comparison, including the middle cases where a modular single-level structure is better, is in single vs multi-level BOM. If you are still settling what belongs on a parts list at all, start with what a bill of materials is.
The honest test: if you never issue, count or buy a sub-assembly on its own, it does not need to be one.
FAQ
How many levels should a multi-level BOM have?
As many as you have real stopping points in production, and no more — three or four covers most small and mid-size manufacturers. Each extra level adds a part number, a stock record and a transaction at build time, so a level that exists only for neatness is a cost with no return. If you cannot say what happens to a sub-assembly on its own — stocked, built separately, bought made up, shared or sold — collapse it into its parent.
Is the BOM quantity per finished product or per parent assembly?
Per immediate parent, always. Oracle’s JD Edwards documentation defines Quantity Per as how many components you use to manufacture the parent item. If a filter housing takes 3 cartridges and a machine takes 2 housings, the housing BOM says 3 and the machine BOM says 2 — the explosion produces 6. Entering 6 on the housing BOM doubles the requirement on every product using it.
How do I set up a sub-assembly used in more than one product?
Create it once as its own item with its own BOM, then reference that item as a component line on each parent. Never copy the parts into both. Before changing it, run a where-used check to see every product affected, and if one product needs a variation, create a new sub-assembly part number rather than editing the shared one.
In what order should I create the BOMs?
Bottom-up. Create the lowest-level sub-assembly BOMs first, then reference those items on the level above, up to the finished product. Odoo’s manufacturing documentation gives the same guidance. Building top-down means every sub-assembly line points at a part number that does not exist yet.
Sources
- Multilevel BoMs — Odoo 19.0 documentation — building BoMs bottom-up.
- Bills of materials and formulas — Microsoft Learn, Dynamics 365 — a single BOM describes a single level; components reference their own BOMs.
- Work With Bills of Material — Oracle JD Edwards World — Quantity Per; Where Used Update.
- Changing the BOM to a Multi-Level Format for JD Edwards EnterpriseOne — Oracle — iterative explosion.