Menu
BOM and Routing Data Model: Fields, Keys and Effectivity

BOM and Routing Data Model: Fields, Keys and Effectivity

Field tables for the item master, BOM header, BOM line and routing operations, plus quantity_basis, setup versus run time, effectivity and a worked example.
BOM and Routing Data Model: Fields, Keys and Effectivity

Key takeaways

  • Four objects carry a manufactured part: the item master, the BOM header, the BOM lines and the routing with its operations. The BOM says what goes in, the routing says how and where.
  • Two fields cause most of the damage: quantity_basis on the BOM header, and setup_time kept apart from run_time_per_unit on the operation.
  • Every BOM line should name the operation that consumes it. Defaulting everything to the first operation breaks backflush, work in progress value and the shortage list.
  • Effectivity is date based or unit based, and a released order must copy both structures. Editing a released line in place rewrites jobs that are half finished.
  • In the worked example below, leaving one operation's yield_percent out finishes the order 10 units short and understates planned time by 46.2 minutes.

The four objects, and the fifth they point at

A manufactured part is defined by two structures, maintained separately and used together. The bill of materials answers what goes in, and the routing answers how and where it is made.

For that difference in plain language, read our guide to BOM vs routing. This page is the tables, the fields and the keys.

ObjectWhat it answersOne row per
Item masterWhat is this thingPart number
BOM headerWhich recipe versionParent part and revision
BOM lineWhat goes in, how muchCom­po­nent on that BOM
RoutingWhich method versionPart and revision
OperationHow, where, how longStep in the routing
Work centreThe capacity it runs onMachine, cell or bench

The fifth object, the work centre, deserves a real table with its own key, because the routing points at it and so does every machine record on the floor.

A BOM line and a routing operation never reference each other by name. They meet through one number, the operation sequence.

The item master

One row per part number, whatever the part is. A purchased washer, a made sub-assembly and a phantom kit share one table, which lets a BOM line point at anything without special cases.

FieldWhat it holds
part_noThe key. Never reused, never edited
descrip­tionShort noun phrase, not a sentence
item_typeMake, Buy or Phantom
uomBase unit: pcs, kg, m, L
unit_weightNet weight in the stated unit
revisionDrawing or engi­neer­ing level
lifecycle_statusDesign, Active, Phase out, Obsolete
lot_con­trolledYes forces a lot number on every move
serial_con­trolledYes forces a serial per unit
shelf_life_daysSets expiry at receipt or production
default_supplierPreferred source for Buy items

item_type decides which other structures may exist. A Make item is allowed a BOM and a routing, a Buy item neither, and a Phantom a BOM but no routing.

Enforce that in the database, because a Buy item with a routing is how a purchased part starts consuming capacity in your plan.

Which fields are mandatory for which type

The two types need different minimums, and blurring that fills the master with placeholders.

FieldPur­chasedManu­fac­tured
part_no, descrip­tion, uomYesYes
item_typeBuyMake
default_supplierYesNo
revisionOnly if drawnYes
BOM and routingMust be emptyYes, one active each
unit_weightIf shipped by weightDerive from the BOM
shelf_life_daysIf perish­ableIf perish­able
lot_con­trolledPer material riskPer customer or law

Lot control is a decision about recall exposure, modelled in our lot traceability data model. Derive a made part's weight from its BOM rather than typing it.

The BOM header

One row per parent part, per revision, per site, holding no components. It says which version of the recipe applies, and when.

FieldWhat it holds
bom_idThe key, for example B-4471-C
parent_part_noThe item this BOM builds
revisionBOM level, tracked apart from the drawing
effective_fromFirst date it may be used
effective_toLast date, or open
quantity_basis1, 100 or 1,000. Read the next section
bom_statusDraft, Released, Superseded
alter­na­tiveWhich of several valid recipes
sitePlant, when recipes differ by plant

Keep the BOM revision separate from the drawing revision, because a supplier swap changes the BOM without touching the drawing.

The natural key is parent_part_no plus revision plus site, and it must be unique, or two people build two BOMs for the same part and both look correct.

quantity_basis against qty_per: the silent multiplier

A BOM line's qty_per is meaningless on its own. It is a quantity per quantity_basis parent units, and the basis lives on the header.

A basis above 1 exists so that adhesive is written as 3.5 litres per 1,000 units, a number people do not mistype.

Basisqty_perPer one parent
122
10020.02
1002002
1,0003.50.0035

A line written as 200 per 100 parents means 2 each, and read as 200 each it is a hundredfold error. No alarm fires, because the number is still a valid quantity.

Store the basis on the header and let no line override it, show the derived per-unit figure next to qty_per, and make a tenfold jump in that figure ask for confirmation.

The BOM line

One row per component, with its own sequence number so two lines can carry the same part.

FieldWhat it holds
bom_id + line_noThe key, 10, 20, 30 with gaps
com­po­nent_part_noWhat goes in
qty_perQuantity per quantity_basis parents
uomCom­po­nent unit, may differ from parent
scrap_factorExtra to issue, as a share
oper­a­tion_seqWhich operation consumes it
is_phantomBlow through instead of stocking
sub­sti­tute_groupLines that may replace each other
refer­ence_desig­natorWhere it sits: R12, R13, bolt hole 4
effective_from / toLine dates, inside the header window
issue_methodManual issue or backflush

Reference designator is the field electronics plants cannot live without and mechanical plants usually skip. If a BOM says four capacitors and the board has positions C4, C7, C11 and C19, the designators are what lets an operator and a placement program agree, so keep their count equal to qty_per.

The uom on the line is the component's unit, not the parent's.

The routing and its operations

The routing header mirrors the BOM header almost field for field. Both are versioned definitions of the same part, and both need the same effectivity rules.

FieldWhat it holds
routing_idThe key, for example R-4471-C
part_noThe item this method makes
revisionProcess level, tracked apart from the BOM
effective_from / toWindow in which it may be used
routing_statusDraft, Released, Superseded
alter­na­tiveSecond method, for example a manual cell
lot_size_basisLot the times were measured on

Times measured on a lot of 500 do not describe a lot of 20, which is what lot_size_basis records. Where those times come from is our time study data model.

Operation fieldWhat it holds
oper­a­tion_seq010, 020, 030 with gaps for inserts
work_centre_idWhere it runs
descrip­tionVerb first: Weld frame, Deburr bore
setup_timeMinutes per order, not per part
run_time_per_unitTime for one unit at rated speed
run_time_uommin/pc, pc/h or h/100. State it
queue_timeExpected wait before the step
move_timeTransport to the next step
overlap_ruleSend ahead quantity or percentage
tool_noDie, fixture or program needed
yield_per­centShare that survives this step
is_qa_gateNothing passes without a result
crew_sizePeople for setup and for run

Setup time is per order, run time is per unit

Setup is paid once per order and does not move with quantity. Run time is paid once per unit, and this is the field pair most often collapsed into one number.

The routing below carries 155 minutes of setup across four operations. On an order of 500 units the planned total is 3,351.2 minutes, so setup is 4.6% of it, while on 50 units the total is 478.4 minutes and the same setup is 32.4%.

Fold setup into run time by dividing 155 by 500, and the 500 unit order is still right while the 50 unit order is planned at 338.9 against a real 478.4.

That routing overruns by roughly 40% on every small order, and the report calls it a performance problem at the work centre. It is a data model problem.

Queue, move and overlap

queue_time and move_time are lead time, not work, so they belong in the schedule and never in the cost of the operation. overlap_rule lets the next operation start on a send ahead quantity, and without it the schedule moves the whole lot at once and quotes far longer than the floor needs.

The work centre

The routing points at a work centre and the work centre points at the physical assets. That chain is what lets machine data be scored against a routing.

Work centre fieldWhat it holds
work_centre_idThe key, for example WC-WELD-02
descrip­tionWeld cell 2
asset_idsThe machines inside it
capacityMachines and people available
calendarShifts, breaks, planned shutdowns
cost_rateMachine rate and labour rate
efficiency_factorPlanning derate, kept visible

One work centre holds several assets, and an asset belongs to one work centre, as in our asset hierarchy data model.

Keep the efficiency_factor as its own field rather than baking it into run times, because a visible derate can be corrected while a padded run time reads as a slow process.

Where the BOM and the routing meet

The two structures are joined by operation_seq on the BOM line. That number decides when material is needed, where it is issued, what the work in progress is worth, and how much of a component the order needs.

Backflush against manual issue

MethodWhat it costs you
Manual issueOne transaction per pick. Accurate, and it catches a wrong part at the bench
BackflushNo picking transaction. Stock is only as right as the reported quantity and the qty_per

Backflush deducts qty_per multiplied by the quantity reported at the consuming operation, and it is the default in most plants for fasteners, adhesives and paint.

It goes wrong in one way: a part scrapped after the material was already in it still consumed that material, so backflush against the operation's input quantity, not its good output. High value and lot controlled components should stay on manual issue whatever the transaction cost.

The everything at operation 10 default

Many systems default operation_seq to the first operation when the field is left empty. It is the most expensive default in the model, and four things break at once.

Material requirements are dated to the start of the job, so parts arrive early and sit. Work in progress value jumps to its full amount at the first step, so a job that is 10% done looks 100% funded.

Backflush deducts paint when the first part is cut, so stock is wrong all run, and the shortage list is useless because everything is short on day one.

Set the field on every line. A component is consumed at the first operation that physically needs it in the hand.

Effectivity and revisions

Effectivity answers which version applies to a given order.

Ap­proachKey fieldUse when
Dateeffective_from / toChange applies from a date
Unitfrom_serial / to_serialChange applies from a build number
Lotfrom_lotProcess change tied to a batch

Date effectivity is the common case and the easier one. It fits a supplier change or a material substitution that applies to whatever is built from Monday.

Unit effectivity is what regulated and long-lived products need, and it costs more to run. When a customer asks what was in serial 00412, a date is not an answer, because the build spanned a revision change.

Why you never edit a released BOM line in place

An edit in place has no time dimension. It changes what the part was made of last March as well as what it will be made of tomorrow.

Costs then recalculate against a recipe never used, a trace returns today's design rather than the components actually fitted, and a job on the floor changes under the operator's hands.

The correct move is always the same. Close the old line with an effective_to date, open a new line with an effective_from date, and raise the BOM revision.

Treat Released as immutable, accepting only the effectivity dates that retire it.

What the work order copies at release

At release the order takes a snapshot. What it copies and what it merely references is the difference between defensible history and guesswork.

Copied into the orderKept as a reference
bom_id and revisionpart_no
Each line: com­po­nent, qty_per, scrap_factor, oper­a­tion_seqItem master descrip­tion and uom
routing_id and revisionwork_centre_id
Each operation: setup, run, yield, tool_noWork centre calendar and rates
Computed required quan­titiesSupplier and stock records

Anything that defines what this order was told to do is copied, and anything that only names an object is referenced. A shift calendar can change without rewriting history, but a qty_per cannot.

The full field set on the order itself is our production work order data model.

Phantoms, substitutes and scrap factors

Each of these three solves a real problem, and each has a failure mode that is easy to reach.

DeviceWhat it is forFailure mode
PhantomGroup parts without stocking themA real stocked part flagged phantom vanishes from stock
Sub­sti­tuteAllow an approved alter­na­tiveSilent swap, so the unit's real content is unknown
Scrap factorIssue extra for known lossSet at the wrong level, or stacked on a yield

Phantoms

A phantom exists in the structure but never in stock, and the explosion blows straight through it to its children. Use it for a kit of fasteners, or a sub-assembly built and consumed in the same operation without being put away.

Flag a genuinely stocked part as phantom and its on hand quantity is ignored, so the children are ordered again and the shelf fills up.

Substitutes

A substitute_group marks lines that may stand in for each other, usually with a priority and a date window. The failure mode is allowing the swap without recording it.

If the order does not store which approved part was fitted, that unit's genealogy is a guess. Book the substitution on the order line with part, quantity and approval.

Scrap factors

A scrap_factor issues extra material for loss that is known and accepted, such as offcuts or a purge at the start of a run.

Two conventions exist and systems disagree. Additive multiplies qty_per by one plus the factor, while yield style divides qty_per by one minus the factor.

At 5% on 1,000 pieces the first gives 1,050 and the second 1,053, so write down which your system uses. Set at the wrong level it buys extra of the wrong part, and stacked on an operation yield it orders the same loss twice.

A scrap factor is an allowance, not a measurement. Track real losses through scrap records with reasons, as in our scrap reason code taxonomy, and review the factors against them.

Worked example: 500 units, two BOM levels, four operations

Order MO‑4471‑08 asks for 500 good units of PART‑4471 revision C. Every number below, including both error cases, comes from the two tables that follow.

BOM B-4471-C (basis 1)qty_perAt op
SUB-2210 sub-assembly2 pcs, scrap 3%010
HW-0801 bolt8 pcs, scrap 1%030
PNT-100 paint0.12 L, scrap 6%040
Routing R-4471-CSetup + runYield
010 Fit subs, WC-ASSY-0130 min + 1.80 min/pc100%
020 Weld, WC-WELD-0245 min + 2.40 min/pc98%
030 Bolt and torque, WC-ASSY-0220 min + 1.20 min/pc100%
040 Paint and cure, WC-PAINT-0160 min + 0.90 min/pc100%

1. Work backwards to the release quantity

Yield runs from the last operation back to the first, because the 500 is a requirement for good output, not for input.

Operations 040 and 030 pass everything, so both need 500 in. Operation 020 passes 98%, so it needs 500 divided by 0.98, that is 510.20, rounded up to 511.

Operation 010 has no loss, so the order releases 511 units, 11 of them expected to be lost at welding.

2. Gross component requirements

Each component is sized on the input quantity of the operation that consumes it, then increased by its scrap factor, rounding discrete parts up.

Com­po­nentCalcu­lationRe­quired
SUB-2210 at op 010511 x 2 x 1.03 = 1,052.661,053 pcs
HW-0801 at op 030500 x 8 x 1.01 = 4,0404,040 pcs
PNT-100 at op 040500 x 0.12 x 1.06 = 63.663.6 L

The sub-assembly is sized on 511 because it is fitted before the weld loss, the bolts on 500 because they go on after it. Get that wrong on the bolt line and you order 4,088.

3. The second BOM level

SUB‑2210 has its own BOM, B‑2210‑A, on a quantity_basis of 100. The 1,053 sub-assemblies are its parent quantity.

B-2210-A (basis 100)CalculationRequired
RAW-5590, qty_per 1001,053 x 100 / 1001,053 blanks
CLIP-77, qty_per 200, scrap 2%1,053 x 2 x 1.02 = 2,148.122,149 pcs

Read qty_per 100 as a per-unit figure and the steel requirement becomes 105,300 blanks instead of 1,053. The only thing between that and a purchase order is somebody noticing the number is large.

4. Total planned time

Planned minutes are setup plus run time multiplied by the quantity that passes through the operation, and that quantity changes at operation 020.

OperationCalculationMinutes
01030 + 511 x 1.80949.8
02045 + 511 x 2.401,271.4
03020 + 500 x 1.20620.0
04060 + 500 x 0.90510.0
Total155 setup + 3,196.2 run3,351.2

That is 55.9 hours of planned work, 155 minutes of it setup, and welding is the constraint. Check it two ways: the four lines add to 3,351.2, and 155 setup plus 3,196.2 run give the same.

5. Error one: the yield is left out

Now recompute with operation 020 at 100% yield, which is the default. The release quantity becomes 500, and every operation is planned on 500 units.

FigureCorrectYield omitted
Released at op 010511500
Good units out500490
Planned minutes3,351.23,305.0
SUB-2210 required1,0531,030

The order finishes 10 units short, because 500 released at 98% yield returns 490 good. Planned time is understated by 46.2 minutes, and the sub-assembly requirement drops to 1,030.

Both halves reconcile. The 11 missing units explain 11 times 1.80 plus 11 times 2.40, which is 46.2 minutes, and 11 times 2 times 1.03 rounds to the 23 missing sub-assemblies.

6. Error two: the scrap factor sits at the wrong level

The 3% belongs on the SUB‑2210 line of the parent BOM, because subs are damaged during fitting at operation 010. Suppose it goes on the RAW‑5590 line one level down instead.

FigureCorrectFactor moved down
SUB-2210 planned1,0531,022
RAW-5590 blanks1,0531,053
Usable subs after fitting1,022991
Good units out500485

The steel requirement is identical at 1,053 blanks, which is exactly why this error survives review. The number everyone checks does not move.

What moves is the sub-assembly build quantity: 1,022 instead of 1,053. At 0.70 minutes per sub on the press, those 31 missing subs are 21.7 minutes cut from the sub-assembly order.

The fitting loss then hits the smaller pool, and 3% of 1,022 is 30.66, so 31 are damaged and 991 usable subs remain.

At two per unit those fit 495 units, and 495 through a 98% weld yield gives 485 good. The order finishes 15 units short, with 31 blanks stranded as work in progress.

Both errors share a signature: consistent arithmetic, no validation, and a shortage that appears at the end of the job.

How this feeds the shop floor

The order leaves the office with a frozen copy of both structures, and comes back with what actually happened, operation by operation.

The reporting loop needs four values per operation: the input quantity, the good quantity, the scrap quantity with a reason code, and the actual setup and run minutes.

Good divided by input is the operation's measured yield, and against the stored yield_percent it says whether the model or the process has drifted.

Actual minutes against setup_time plus run_time_per_unit is the same test for the times. If welding takes 1,400 minutes rather than 1,271.4, either the standard is optimistic or the work centre is losing time to stops.

Separating those two explanations is what OEE is for: availability for time lost to stops, performance for speed against the routing's rate, quality for what survived.

That makes run_time_per_unit the ideal cycle time performance is scored against, and our guide to cycle time covers how to set it. The part number must travel with the machine record, or the two systems disagree about which part was running.

The ERP owns the item master, the BOMs, the routings and the order header, while the floor systems own the events. Our pages on the manufacturing execution system and the CMMS data model cover that boundary.

One rule keeps it coherent: every field has exactly one owning system, and the others read it.

Five questions to ask a vendor about BOM and routing structures

  1. How do you handle effectivity? Ask whether unit or serial effectivity works alongside dates, and what happens to an open order when a new revision goes effective.
  2. What does a work order copy at release, and what stays a live reference? Ask them to name the fields, because a vague answer means history is not defensible.
  3. Can a BOM line be tied to a routing operation, and does backflush respect it? Then ask what the default is when the field is left empty.
  4. Is setup_time stored separately from run_time_per_unit? Ask to see planned time for an order of 20 and one of 2,000, because the small one exposes setup folded into run time.
  5. How are scrap_factor and yield_percent combined? Ask for the formula in writing, including the rounding rule and whether the two can double count the same loss.

Ask each one against your own part, in a live system. Sample data only proves the sample data was built to work.

How Fabrico helps

Fabrico does not maintain BOMs or routings, and it does not do MRP, production planning or scheduling. Those structures live in your ERP or MES, and Fabrico reads them rather than owning them.

What Fabrico owns is the machine side. It measures OEE, downtime, short stops and cycle times through PLC connections, IoT sensors and AI cameras.

The link to this model is deliberately narrow. The part number travels with the machine data, so a stop or a slow run is attributed to the part that was running, and run_time_per_unit can be compared with what the machine actually achieved.

Whether the operation and the work centre come across as well depends on what your ERP or MES sends over the integration. Ask for that mapping in writing before you assume a downtime report can be split by operation.

On the maintenance side, Fabrico is a full CMMS: your team creates maintenance work orders, runs preventive plans and tracks spare parts consumed per work order, from web or mobile apps. That inventory covers maintenance spares, not production components.

The AI assistant answers questions about a machine's losses and history in plain language.

Want to see whether your routing times match what your machines really do? Book a 30 minute demo with a Fabrico consultant, no commitment, or contact us with your questions.

Frequently asked questions

What fields does a BOM need?

The header needs bom_id, parent_part_no, revision, effective_from and effective_to, quantity_basis and status. Each line needs component_part_no, qty_per, uom, scrap_factor and operation_seq, plus is_phantom, substitute_group and reference_designator where they apply.

What is the difference between a BOM and a routing in the data model?

The BOM is a parent item with component lines and quantities, so it answers what goes in. The routing is a parent item with operation lines, work centres and times, so it answers how and where it is made.

What does quantity_basis mean on a BOM?

It is the number of parent units that qty_per refers to, usually 1, 100 or 1,000. A line of 200 on a basis of 100 means 2 per unit, and reading it as 200 per unit multiplies the requirement by a hundred.

Should setup time and run time be stored in one field?

No, because setup is paid once per order and run time is paid per unit. Combining them plans every order size wrongly except the one the standard was built on.

Why should a work order copy the BOM and routing instead of pointing at them?

Because a later revision would otherwise rewrite orders already running or already closed. A copy keeps costs, traceability and the pick list consistent with what was built.

Dernières nouvelles de notre blog

Définissez votre feuille de route en matière de fiabilité
Validez votre retour sur investissement potentiel : réservez une démonstration en direct
Définissez votre feuille de route en matière de fiabilité
En cliquant sur le bouton Accepter, vous donnez votre consentement à l'utilisation de cookies lors de l'accès à ce site Web et de l'utilisation de nos services. Pour en savoir plus pour en savoir plus sur la manière dont les cookies sont utilisés et gérés, veuillez consulter notre Politique de confidentialité et Déclaration relative aux cookies