Skip to content

Nesting & execution

When a BOM containing a sub-assemblySub-AssemblyA reusable assembly block that composes into bigger BOMs. Define it once, include it in any BOM. At execution time, Assemblified expands the sub-assembly into its own components recursively. Read more → fires, the sub-assembly is recursively expanded into its own components. Quantities multiply through each layer; pre-assembled stockPre-Assembled InventoryStock of finished sub-assemblies and BOM items that have already been built and are sitting on the shelf. When a work order needs a sub-assembly, it draws from pre-assembled inventory first and only builds fresh ones if the shelf comes up short. Read more → at each layer is consumed first.

This page walks through the expansion mechanics with worked examples.

  • Quantity multiplication through layers
  • Pre-assembled drawdown at each layer
  • A worked end-to-end example
  • Waste percentage handling
  • Cycles — what NOT to do

A BOM containing a sub-assembly carries a quantity multiplier on the reference. The sub-assembly’s own components are then multiplied by (parent_quantity × reference_quantity).

Example. Order 4 units of BOM B, where:

  • B contains 2 × Sub-assembly S (the reference quantity is 2).

The expansion produces 4 × 2 = 8 of whatever’s inside S, before any pre-assembled drawdown.

This compounds across layers. If S contains 3 × Sub-assembly T, and T contains 5 × Raw R, then:

  • 4 units of B → 8 of S → 24 of T → 120 of R.

At each layer of the recursion, the sub-assembly’s pre-assembled shelf is consumed before falling through to its components.

Example. Same setup as above. S has 3 in pre-assembled stock.

Order 4 of B.
Frame { B, multiplier=4 }:
No B-level pre-assembled.
Recurse into S edge with multiplier 4 × 2 = 8.
Frame { S, multiplier=8 }:
Consume from S's shelf: min(3, 8) = 3. Shelf → 0. Remainder = 5.
Recurse into T edge with multiplier 5 × 3 = 15.
Frame { T, multiplier=15 }:
No T-level pre-assembled.
Emit Raw R × (15 × 5) = 75.

Net effect: 75 of Raw R consumed, plus 3 of S’s pre-assembled shelf. Without S’s pre-assembled, you’d have consumed 24 of T (which would have consumed 120 of R). The shelf cut consumption by 60%.

Waste percentage is applied per-edge, not compounded across layers. If a raw material has 10% waste on its sub_assembly_raw_material_references row, the multiplier is 1.10 at that single emission. Sub-assembly references themselves don’t carry waste percentages.

So a chain like:

  • BOM B has 1 × Sub-assembly S (no waste at the BOM→SA edge).
  • S has 5 × Raw R with 10% waste.

For an order of 4 units of B: emit Raw R × (4 × 1 × 5 × 1.10) = 22.

If you want waste at multiple layers (e.g., the SA itself has assembly loss), model it as additional raw materials on the parent BOM, not as cumulative percentages.

A “Vanilla Candle 8oz” BOM contains:

  • 1 × Glass jar
  • 1 × Sub-assembly “Wick assembly” (qty 1)
  • 1 × Vanilla scent oil (raw material)

The “Wick assembly” sub-assembly contains:

  • 1 × Raw wick (8% waste)
  • 0.5 × Wick clip
  • 1 × Sub-assembly “Wax block” (qty 1)

The “Wax block” sub-assembly contains:

  • 0.25 × Wax (1kg block, 5% waste)

Setup:

  • “Wick assembly” pre-assembled stock: 5
  • “Wax block” pre-assembled stock: 0
  • BOM pre-assembled: 0

Customer orders 4 units of “Vanilla Candle 8oz”.

Expansion:

  1. BOM level. No BOM pre-assembled. Order qty 4.
  2. Direct components. Emit:
    • 4 × Glass jar (qty 1) = 4 jars.
    • 4 × Vanilla scent oil (qty 1) = 4 oils.
  3. Recurse into “Wick assembly” with multiplier 4.
  4. “Wick assembly” pre-assembled. Consume min(5, 4) = 4. Shelf → 1. Remainder = 0.
  5. Recursion into “Wick assembly“‘s children stops because remainder is 0. No raw wick, wick clip, or wax block needed!

Final result: 4 jars, 4 oils, and a -4 to “Wick assembly” pre-assembled shelf.

If the order had been for 7 units instead:

  • “Wick assembly” pre-assembled covers 5; remainder = 2.
  • Recurse into “Wick assembly“‘s children with multiplier 2.
  • Emit Raw wick × (2 × 1 × 1.08) = 2.16.
  • Emit Wick clip × (2 × 0.5) = 1.
  • Recurse into “Wax block” with multiplier 2 × 1 = 2.
  • “Wax block” has no pre-assembled. Emit Wax × (2 × 0.25 × 1.05) = 0.525.

The expansion has no cycle detection. A sub-assembly that references itself transitively (S → T → S, or any longer cycle) will infinite-loop the traversal until processing aborts and the order fails to process.

Don’t create cycles. If you accidentally make one, the symptom is webhook timeouts — execution log rows stuck in “processing” status.