Files
bible/rules/patterns/bom-decomposition/contract.md
2026-04-02 13:48:36 +03:00

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_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.