Functional Weave
Code in TypeScript

manufacturing.bom-explode@1.0.0

README.md

2,318 bytes · view raw

# manufacturing.bom-explode

Explodes a multi-level bill of materials (BOM): given the parent-component
lines, a product and how many to build, it returns the total quantity of every
sub-assembly and part needed, summed over every place each one is used.

    need(component) += need(parent) x quantity x (1 + scrap)

**Exact quantities.** A line's quantity is a `Rational` (from `math.rational`),
so 1.5 m of tube is `3/2` and a tenth of a sheet is `1/10`, and totals are
exact fractions. Nothing is rounded on the way down: three cases that each take
a tenth of a sheet, with ten coatings per sheet, need exactly 3 coatings, where
floating point says 3.0000000000000004 and a ceiling makes it 4. `wholeUnits`
is the exact total rounded up, once, for items counted in whole units; use
`quantity` for anything measured (metres, kilograms).

**Scrap.** `scrapBasisPoints` is component scrap as most ERP systems define it:
an allowance added to the line's quantity (500 = 5% more), applied to that line
only. Scrap on a sub-assembly line compounds into everything below it, because
the extra sub-assemblies need their own parts.

**Levels.** Each item's `level` is its low-level code: the deepest level at
which it appears (a direct component of the product is level 1). A part used
both directly and inside a sub-assembly gets the deeper level, which is the
order MRP must plan in so all of a part's demand is known before it is
planned. Results are ordered by level, then by where the item first appears
in a depth-first walk of the lines in the order given.

**Cycles are errors.** A BOM in which an item contains itself, directly or
through other items, has no finite explosion; the error names the loop
(`bill of materials has a cycle: A -> B -> C -> A`). Only the part of the BOM
under `item` is walked, so a loop elsewhere in the lines is not reported.

**Other rules.** Several lines for the same parent and component are added
together. `leaf` is true for items with no lines of their own (bought in). The
product itself is not in the result. A product with no lines, a quantity that
is not positive, negative scrap or a negative build quantity is an error.
Build quantity 0 gives every item with a zero quantity. Totals are exact
fractions and must stay within 2^53 - 1 when reduced (`math.rational`'s range).