# Bills of materials > Multi-level BOMs, line effectivity, effective BOM as of a date, compare. A bill of materials (BOM) lists what goes into one revision of an assembly. Each line names a child part and how many of it you need. You edit it on the **BOM** tab in **Parts & BOMs**. ## Lines A line has three things: - The child part. - A quantity. Quantities are decimal strings, such as `"2"` or `"0.25"`, so metres and grams work without rounding errors. A quantity must be greater than zero. - A way to choose the child revision. A BOM holds at most one line per child part. To use more of a part, change the quantity of its line. You list a revision's own lines with `listBOMLines`. You add, change and remove lines with `addBOMLine`, `updateBOMLine` and `deleteBOMLine`. You can only edit the lines of a `DRAFT` revision. See [Parts and revisions](https://buildtrace.eu/docs/concepts/parts-and-revisions.md). ## Which child revision a line uses Each line has a reference mode. The UI calls this **Revision**: - `PINNED` (**Pinned to revision**): the line always uses the revision you choose. A pinned child must be a revision of the line's part. - `LATEST_RELEASED` (**Latest released**): the line uses whichever released revision of the child is newest when you look. Pinning gives you a fixed design. Following the latest release keeps a sub-assembly current without editing the parent. ## Multi-level BOMs A child can be an assembly with its own BOM. This nests as deep as you need, and the result is a `multi-level` BOM. The **BOM** tab has three views: - **Lines**: only this revision's own lines. - **Multi-level**: the full tree. You can collapse and expand each sub-assembly. - **Flattened**: every line at every level in one list, with no nesting. The BOM is `flattened` so you can scan or count it. Each quantity is the line's own quantity, per one of its parent. ## Cycles are rejected A BOM can't contain itself. A line can't point at its own revision, and a pinned line that would make a loop is refused. Lines that follow `LATEST_RELEASED` can still form a `cycle` through other parts, such as A uses B and B uses A. BuildTrace can't see that when you add the line. It reports the `cycle` when it builds the BOM, and `getEffectiveBOM` answers with a conflict. Remove one of the lines to fix it. ## The effective BOM The base BOM is the lines you edited. The `effective BOM` is the base BOM plus the change orders that are effective at a date you choose. It shows what production will use. Use the **Effective as of** date on the **BOM** tab to look at any date. Leave it empty to see today. Lines that a change order added or replaced show the change order's number, title and date. `getEffectiveBOM` returns this tree. Its `effectiveAsOf` parameter is the date. See [Change orders](https://buildtrace.eu/docs/concepts/change-orders.md). ## Compare two revisions On the **Revisions** tab, choose revision A and revision B and select **Compare**. The result compares the direct lines of the two effective BOMs, part by part. It marks each part as added, removed or changed, and shows the quantity in A and in B. Parts that are the same in both are listed without a mark. It does not compare sub-assemblies level by level. ## Where a part is used The **Where-Used** tab shows every BOM that uses the selected part, and whether each line is pinned or follows the latest release. The operation is `getPartWhereUsed`.