Files
2026-04-02 13:48:36 +03:00

58 lines
2.4 KiB
Markdown

# 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_ref`
- `quantity_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_item` is 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_item` to `1`.
- Before persistence:
- trim `component_ref`
- drop empty `component_ref` rows
- reject `quantity_per_item <= 0`
- merge duplicate `component_ref` values by summing quantities
- preserve first-seen order when merging duplicates
## Forbidden Patterns
- Do not introduce alternate persisted shapes such as `primary_lot`, `secondary_lots`, `main_component`, or `bundle_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.