Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Spare Parts

The maintenance module doesn’t introduce its own stock ledger. Every spare-part issue, return, and write-off is a regular stock movement tagged with a maintenance reference type, so all your existing lot/serial tracking and location accounting continues to apply unchanged. What the module adds on top is the catalog work to make the right parts available at the right time.

Asset-to-part associations

You can declare which parts which asset (or asset class) typically consumes. The association says:

  • The product (and optionally variant) — the spare-part SKU.
  • The typical quantity and unit per intervention.
  • The usage patternEVERY_PM (consumed every preventive service), EVERY_N_PM (every Nth, e.g., gaskets every 4th oil change), ON_FAILURE (only when this part fails), ON_INSPECTION (gathered observationally — air filter checked every time, replaced when dirty).
  • An optional preferred supplier, used to default the supplier on auto-emitted purchase requisitions.

Associations attached to an asset class apply to every asset in that class — useful for parts that are class-uniform (every CNC mill takes the same way-cover); associations attached to a specific asset override (this one press has the unique gasket because it’s a custom retrofit).

Maintenance kits

A kit is a transactional convenience: a named bundle of spare parts that a technician issues to a WO in one click. The forklift 250h kit might bundle engine oil + oil filter + grease + tire gauge. The kit detail page exposes a Components tab where each component has:

  • Product (and optionally variant), quantity, unit.
  • A sequence number for display order.
  • An is_optional flag — the technician decides per-issue whether to consume.

Issuing a kit expands the components, picks lots FEFO/FIFO from the source warehouse, and emits one stock movement per kit line. The kit itself is a definition, not stock — there’s no “kit on hand.”

Preview expansion (dry run)

The kit detail page has a Preview expansion button next to Edit. It opens a side drawer that calls the same expansion engine the real kit issue uses — but writes nothing. For every active component you see:

  • The component’s product, required quantity, and unit.
  • The estimated unit cost (taken from products.standard_cost).
  • The line estimate = required quantity × unit cost.
  • The available quantity at the work order’s source warehouse (only when a work order is selected; otherwise availability is hidden).
  • A Shortage badge when required quantity > available. Mandatory shortages would block a full kit issue; optional shortages flag visually but never block.

A footer line sums every component into the aggregate estimate — what actual_parts_cost will roll up to on the work order once the real kit issue posts (before lot-cost adjustments). The drawer also lets you pick a work order from your active list so the preview is scoped to its warehouse; when no work order is chosen, the unit-cost estimate still renders but availability is suppressed.

Use it before pressing “Issue kit” to spot shortages, decide whether to short-issue or wait for back-order receipts, and confirm the cost the kit will post is the one you expected.

Each planned WO part remembers whether it came from a kit. The issue_method on the part line is either:

  • Manual — the default; the technician issues each unit individually via the per-part issue button.
  • Kit issue — set when the line came from a kit expansion; the entire kit issues in one click via the work order’s “Issue kit” action.

Mixing isn’t allowed on a single line — once a line was created from a kit, all subsequent issues on it run through the kit-issue path. Picking the same part ad-hoc on the same WO creates a separate Manual line.

Critical-spare policies

Some spares matter so much that running out costs more than carrying stock — the unique gasket for that one critical press, the proprietary bearing the OEM takes 6 weeks to ship. A critical-spare policy declares per-product / per-warehouse:

  • A minimum quantity — when on-hand minus reserved drops below, action is needed.
  • A maximum quantity — when topping up, order back to here.
  • An optional preferred supplier and lead time.

A daily background job walks every active policy. When on-hand minus reserved drops below the minimum (parts sitting in a repair pool don’t count toward on-hand), it drafts a purchase requisition for (max − on_hand) units against the preferred supplier. The PR is created with priority HIGH, status DRAFT, requested-delivery = today + the policy’s lead time, and metadata flagging it as MAINTENANCE_CRITICAL_SPARE so procurement knows the trigger source. The job is idempotent — if a DRAFT requisition already exists for the same product, variant, and warehouse, it doesn’t create a duplicate.

Reservation policy

When an MWO is released:

  • Non-optional parts are reserved against the source warehouse stock (parts sitting in a repair pool are excluded — they aren’t available yet).
  • Reserved quantity counts against the on-hand for other reservations (so two parallel WOs can’t both reserve the last unit).
  • Reservation is keyed by (product, variant, warehouse, lot if lot-tracked). Partial reservations are allowed — if only 3 of 5 needed are available, the WO releases with 3 reserved and the planner sees the shortfall.

Reservations release on:

  • Part issuance (reservation decrements, on-hand decrements).
  • Part-issue cancellation (reservation increments back).
  • WO cancellation (all remaining reservations release).
  • WO completion if anything still reserved (it didn’t get used, so it’s freed).

Repair pool

Some parts are repairable rather than disposable: an electronic board, a precision gauge, a motor. The flow:

  • The technician returns the failed part with repair_required = true. The movement is MAINTENANCE_RETURN to a sub-location flagged metadata.is_repair_pool = true.
  • Both reservation (at WO release) and the FEFO issue picker ignore repair-pool stock — these aren’t available for new WOs yet.
  • After repair (either in-house, with a maintenance WO of its own, or sent out as an external service), the repaired part posts back to general stock with is_repaired = true. The new unit cost is the original lot cost plus a per-unit share of the WO’s other cost (actual_other_cost) — that is, the total repair cost divided across the returned units, not the full amount added to each unit.