Skip to content

Spare Parts

The maintenance module doesn't introduce its own stock ledger.

Updated View as Markdown

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. Manage these under Maintenance → Asset Spare Parts: the list shows every association with its scope, part, typical quantity, usage pattern, and preferred supplier; the New button opens a dedicated page where each association says:

  • The scope — one specific asset, or a whole asset class. Exactly one of the two.
  • The product (and optionally variant) — the spare-part SKU.
  • The typical quantity and unit per intervention. This is a planning hint — it feeds part suggestions and demand forecasts, and never reserves stock by itself.
  • The usage patternEvery PM (consumed every preventive service), Every Nth PM (every Nth, e.g., gaskets every 4th oil change — the N must be at least 2), 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).

Every asset’s detail page also carries a Parts tab showing the parts that cover it: the Scope column names the machine itself for a row attached to it directly, and reads Class: followed by the class name for a row it inherits from its class. Click any row to open and edit the association.

The Asset spare parts list narrows on its filter button by Asset, Asset Class, Product, Usage pattern, Preferred supplier, Active or a typical-quantity range (Working with lists).

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.

The Maintenance kits list filters by Asset Class and Active.

On a kit, the Components tab narrows by Part, Unit, Optional, Active or a quantity range.

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 line is priced from that supplier’s own catalogue row — the last price actually paid, or the agreed price where nothing has been bought yet — and where the supplier has a row for the specific variant rather than the whole product, that row is the one used. Where that supplier has no price on file — nothing listed for the part, or a listed zero, which is not a price — the requisition is still raised and the line simply arrives with Estimated Price blank. That is not a failure: the line waits on a price exactly as an approved requisition line does, and the buyer fills the figure in when placing the order. 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.

The Critical spare policies list filters by Product, Warehouse, Preferred supplier, Active, or a minimum, maximum or lead-time range — Lead time (days) above 14 is the list to review before a long holiday.

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 reversal (reservation increments back).
  • Work-order cancellation (all remaining reservations release).
  • Work-order 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.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close