2.4 KiB
2.4 KiB
Contract: BOM Decomposition Mapping
Version: 1.0
Purpose
Defines the canonical way to represent a BOM row that decomposes one external/vendor item into multiple internal component or LOT rows.
This is not an alternate-choice mapping. All mappings in the row apply simultaneously.
Use this contract when:
- one vendor part number expands into multiple LOTs
- one bundle SKU expands into multiple internal components
- one external line item contributes quantities to multiple downstream rows
See README.md for full JSON and Go examples.
Canonical Shape
- A BOM row contains one quantity plus zero or more mapping entries in one array field.
component_mappings[]is the only canonical persisted decomposition format.- Each mapping entry has:
component_refquantity_per_item
- Project-specific field names are allowed only if the semantics stay identical.
Quantity and Persistence Rules
- Downstream quantity is always
row.quantity * mapping.quantity_per_item. - The persisted row payload is the source of truth.
- The same mapping shape must be used for persistence, API read/write payloads, and downstream expansion logic.
- If the mapping array is empty, the row contributes nothing downstream.
- Row order is defined by
sort_order. - Mapping entry order may be preserved for UX, but business logic must not depend on it.
UI and Validation Rules
- The first mapping row is not special. Every mapping row is equally editable and removable.
quantity_per_itemis edited per mapping row, not once for the whole BOM row.- Blank mapping rows may exist temporarily in draft UI state, but they must not be persisted.
- New UI rows should default
quantity_per_itemto1. - Before persistence:
- trim
component_ref - drop empty
component_refrows - reject
quantity_per_item <= 0 - merge duplicate
component_refvalues by summing quantities - preserve first-seen order when merging duplicates
- trim
Forbidden Patterns
- Do not introduce alternate persisted shapes such as
primary_lot,secondary_lots,main_component, orbundle_lots. - Do not split the component and its quantity across unrelated fields outside the mapping array.
- Do not treat the first mapping row as a special primary component.
- Do not compute downstream decomposition from temporary UI-only fields instead of the persisted mapping array.
- Do not store the same decomposition in multiple competing formats.