BOM PRE → PEA: inheritance and synchronization

An operation’s Bill of Material is defined first on the PRE (Recommended Maintenance Program — constructor reference). When a PEA derives from this PRE, it inherits the materials at instantiation, and can override locally. When the PRE evolves (constructor publishes a revision, a quantity is fixed), the PEA can be synchronized by the user on explicit decision.

This is the architecture put in place in wave L5-A’ (May 2026).

Why this hierarchy

Initially the BOM was placed on the PEA (wave L5-A). Framing mistake: the BOM is constructor information — it’s the constructor who says “to calibrate this torque wrench you need this sealant, this seal”. The PEA is the customer instance that can adapt to its constraints (this workshop, this interchangeable reference).

Therefore: PRE = canonical source, PEA = instance with override capability.

The inheritance model

On a material line on the PEA side, there is a hidden field sourceMaterialId:

Value Meaning Behavior on sync
non-null Line inherited from the PRE — its sourceMaterialId points to the PRE source line Overwritten by PRE values
null Line local to the PEA — manual addition OR detached by user Preserved intact

Visually in the PEA Materials panel, inherited lines have a discreet “PRE” badge next to the PN. Local ones don’t.

Defining the BOM on the PRE

Define materials of a PRE operation

  1. 1. Open the PRE task

    ReferencePRE → click the PRE → click a task.

  2. 2. Expand an operation

    In the Operations section, chevron > to the left of each operation line. On click, a “Materials required for operation XXX” panel opens with an “+ Add” button.

  3. 3. Add a line

    Select the role (Spare / Consumable / Tooling), choose the part via the filtered picker, enter the quantity, check “mandatory”. The picker automatically filters on PartType.isTool according to the role.

Initial copy PRE → PEA

When a MaintenancePlanTask is created from a PRE MaintenanceTask (existing mechanism that copies task + triggers + operations), the system also copies the materials:

  • Each active MaintenanceOperationMaterial is copied to MaintenancePlanOperationMaterial with sourceMaterialId = ULID of the PRE source
  • Values (quantity, mandatory, notes) are identical at time T of the copy
  • At this stage, the PEA is perfectly aligned with the PRE

Synchronizing after a PRE evolution

If you modify the PRE (add an operation, a trigger or a material, change an operation field — title, description, order, standard duration, code —, change a quantity, delete), derived PEAs don’t update automatically. An explicit user action is required — deliberate decision so that no PRE change silently breaks a production PEA.

Although the historical name is “BOM”, task-level synchronization now covers all inherited content: operations, triggers and materials. An operation added to the PRE after attachment is therefore carried over by this same action.

Where the “Sync available” badge appears

The orange “Synchronization available” badge is computed on-the-fly and surfaces on three screens, so you never have to open each task to know whether a sync is pending:

  • Maintenance plans list (/maintenance-plans): next to the PEA name, if at least one of its tasks has diverged from its PRE, or if an attached PRE has a brand-new task not yet copied to the PEA.
  • PEA sheet (“PEA tasks” section): on each affected task row.
  • PEA task sheet: next to the title, with the “Synchronize from PRE” button enabled.

A brand-new task added to the PRE has no copy in the PEA yet, so it cannot carry a per-task badge. It is flagged at the PEA level (plans list and PEA sheet) and listed in the tooltip under “New PRE tasks”.

See the exact divergences without opening the task

On hover (or keyboard focus) of the badge, a tooltip shows the precise detail of the PRE → PEA divergences — the same diff as the synchronization dialog, but read-only: added operations, modified operations (scalar fields “before → after”), added triggers, added / modified / removed materials, with their part numbers and quantities.

  • On the PEA sheet and the task sheet, the tooltip details the hovered task.
  • On the maintenance plans list, the badge covers the whole PEA: the tooltip groups by task (code + title) every diverging task of the plan, and lists brand-new PRE tasks separately (with their operation and trigger counts).

The diff is loaded on demand (only on hover), so it never slows down list rendering.

Synchronize a PEA from its source PRE

  1. 1. Spot the badge

    The “Synchronization available” badge signals that some PRE content (brand-new task, operation, trigger or material) hasn’t been carried over yet. From the list or the PEA sheet, open the flagged task — or, for a brand-new task, use “Synchronize” on the attached PRE (“Attached PREs” section of the PEA sheet).

  2. 2. Click 'Synchronize from PRE'

    A dialog opens with a diff preview, additive and non-destructive:

    • Operations added (N): PRE operations absent from the PEA — created with their materials.
    • Operations modified (M): inherited operations whose scalar field (title, description, order, standard duration, code) changed in the PRE — rewritten with the PRE value, “before → after”.
    • Triggers added (N): PRE triggers absent from the PEA — created.
    • Materials added (N): new PRE materials — created on the PEA as inherited.
    • Materials modified (M): inherited materials whose PRE value changed — “before → after”.
    • Removed (R): materials whose PRE source disappeared — kept with “obsolete” annotation (Part-145 retention).
  3. 3. Apply

    “Apply synchronization” button. The operation is transactional: all succeed or all fail. A message summarizes what was carried over (“Sync OK — 1 operation, 2 materials added”). An audit maintenance_plan_task.material_sync_applied is recorded with details (Part-145 §145.A.30).

Detaching a line to customize

Want to change the quantity of an inherited line without suffering overwriting on the next sync? Detach the line:

  • On the inherited line of the PEA panel, click the broken chain icon (“Detach”)
  • The sourceMaterialId becomes null, the “PRE” badge disappears
  • The line becomes local, never overwritten by sync
  • You can now modify its quantity as a local addition

It’s explicit: if you go outside the constructor contract, you assume it. To reintegrate the constructor value later, delete the local line and trigger a sync — the PRE line will be re-created as inherited.

Possible statuses

Status on PEA When
up_to_date All inherited content (operations, triggers, materials) matches the current PRE
pre_evolved A PRE operation or trigger isn’t copied yet, OR a scalar field of an inherited operation (title, description, order, duration, code) differs from PRE, OR an inherited material differs from PRE, OR a new PRE material isn’t copied yet
no_source The plan-task has no PRE-source (task created manually on the PEA) — sync unavailable

V1 limitations

  • No 3-way merge: if you modify an inherited (material) without detaching it, the sync overwrites your modification. To preserve, detach before modifying. Likewise, the scalar fields of an inherited operation (title, description, order, duration, code) are rewritten from the PRE on sync — any local edit of an inherited operation is overwritten (the PRE remains the source of truth).
  • PRE deletion: currently the PEA keeps obsolete inherited with annotation, no automatic deletion. To clear manually.
  • No arbitrary re-attachment: the PATCH only accepts sourceMaterialId: null (detach). To reconnect a line to the PRE, go through the official sync.

See also