Manufacturing
The BOM editor holds a multi-level bill of materials: what a product is made of, assembly by assembly, down to the last bolt. Edit the structure as an indented tree; each part is listed once, so changing a sub-assembly changes it everywhere it is used. Lines carry quantities in their own unit, scrap, find numbers, reference designators, dates they apply from and to, and alternate parts.
Cost, weight and cumulative lead time roll up as you type, for the number you are building, with the longest chain of lead time marked. The parts list sums every part the build needs; where-used finds every assembly a part goes into, and replaces it in all of them at once; and a second revision can be compared line by line. Missing parts, loops and units that do not convert are found and marked on their rows. BOMs come in from ERP and PLM exports as CSV or JSON, and go out as CSV, JSON, a change list or a printable PDF.
Try it with your own BOM files in confidence: they are opened by your browser, on your device. Nothing is uploaded, no copy reaches us or anyone else, and nothing is kept once you close this tab.
An e-bike's bill of materials, rolled up
A made-up maker's e-bike, five levels deep: the frame, a drive unit, a battery pack with its cells, two wheels and a fastener kit that is never stocked (a phantom), so its bolts are used straight in the frame and the drive unit. Every part, price and supplier is invented. Roll up a batch of 50, list the parts to buy, find where a bolt is used, and replace a connector the supplier has stopped making.
// Node 18 or later, from the Pro or Gold package: cost tonight's e-bike BOM from the ERP export and keep its parts list.
import { readFileSync, writeFileSync } from 'node:fs';
import { readBomFile, checkBom, rollUpBom, flattenBom, writeBomCsv } from './dist/node/bmx-bom-editor.mjs';
const { bom } = readBomFile(readFileSync('exports/eb-500-indented.csv', 'utf8'), 'eb-500-indented.csv');
const errors = checkBom(bom).filter(p => p.severity === 'error');
if (errors.length) {
for (const p of errors) console.error(p.message);
process.exit(1);
}
const bike = rollUpBom(bom).get('EB-500');
const { totalCost, costComplete, leadTime, items } = flattenBom(bom, { quantity: 50 });
console.log(`EB-500: £${bike.unitCost.toFixed(2)} a bike, £${totalCost.toFixed(2)} for 50${costComplete ? '' : ' (some parts have no cost)'}`);
console.log(`${items.length} parts to buy; ${leadTime} days from the first order to the first bike`);
writeFileSync(`costing/eb-500-${new Date().toISOString().slice(0, 10)}.csv`, writeBomCsv(bom, 'parts-list', { quantity: 50 }));
Two revisions, compared
The same made-up battery pack, revision B against revision C: a fourth cell in each group, a new management board and case, a thermistor added and the foam pads gone. Two mistakes have crept into revision C on purpose - a quantity in the wrong kind of unit, and a line pasted into the wrong assembly. Compare the two, take the change list, then check revision C and put it right.