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
Write down, once, which parts each machine normally takes: how many per job, on which kind of job, and who you usually buy them from. It is the planner’s reference sheet — what the person preparing a job on that press, or ordering its spares, would otherwise piece together from memory and old work orders. Manage these on the Asset Spare Parts tab of Maintenance → Assets: 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 itself.
- The typical quantity and unit per intervention — how many a job on this machine usually takes.
- The usage pattern — Every preventive maintenance (used at every preventive service), Every Nth preventive maintenance (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 — who you normally buy this part from, for whoever places the order.
An association is information for the people reading it; Beelocity does not act on it by itself. It does not add the part to a work order, it does not set stock aside, and it does not raise a purchase requisition or choose the supplier on one. When a part has to be there, put it where Beelocity does act:
- A part every service of a plan uses goes on the plan’s Parts tab (Maintenance Plans) — those rows are copied onto every work order the plan raises.
- A part for one job goes on that work order’s Parts tab, as a line you add.
- A part you must never run out of gets a critical-spare policy (below). The supplier named on the association plays no part in it.
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). Attach a part to one specific asset when only that machine takes it (this one press has the unique gasket because it’s a custom retrofit). A machine’s own association adds to its class’s list rather than replacing it: both appear on the machine’s Parts tab. Only the class the machine is filed under counts — parts attached to a parent class above it do not carry down, so attach them to the machine’s own class. Where one machine takes a different part from the rest of its class, say so in the association’s Notes.
Every asset’s detail page carries that Parts tab, and it is where the associations are meant to be read — open the machine before planning a job on it or ordering for 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_optionalflag — the technician decides per-issue whether to consume.
Issuing a kit expands the components and issues each one from the work order’s warehouse exactly as a single part issue would: soonest expiry first, each lot at what it cost, with one stock movement per component. A component drawn from two lots, or from two bins, shows as two rows on the job’s Part issues tab, one for each. 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 the kit is expected to add to the work order’s parts cost. The real kit issue adds what the lots it draws actually cost, so the two differ wherever a lot was bought above or below the product’s standard cost. 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.
What a policy counts is the same everywhere: the stock on hand less what is reserved, in the policy’s own warehouse, with parts sitting in a repair pool left out. A policy on a variant counts that variant’s stock; a policy on a product counts the product’s own stock and all of its variants’. The coverage card, the daily requisition and the Spares not covered list on the Maintenance dashboard all read that one count, so they never disagree about a part.
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. A requisition names no supplier, so the policy’s preferred supplier only prices it: the line’s Estimated Price is taken 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. When the requisition is approved, the purchase order it raises takes its supplier from the part’s own supplier catalogue, not from the policy, by the same rules as any other requisition: the supplier marked Preferred there is taken first, unless another supplier has a row for the exact variant where the preferred one’s covers only the whole product, quotes a price where the preferred one quotes none, or prices in the requisition’s own currency where the preferred one does not. Where no supplier is marked, the cheapest you can order from is used. The PR is created with priority HIGH, status DRAFT, requested-delivery = today + the policy’s lead time. Its line is named after the part, and its Source reads Critical spare — a link back to the policy — so procurement knows what raised it (Purchase requisitions). 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 in the work order’s warehouse (parts sitting in a repair pool are excluded — they aren’t available yet). Optional parts are never reserved, and neither are the lines a kit issue adds to the job: those are taken from free stock when the kit is issued.
- A reservation only takes stock that is free. What another order has already reserved stays with that order, so two parallel WOs can’t both reserve the last unit, and a job can’t claim a bearing a sales order has promised to a customer.
- Parts are reserved per part and per warehouse, from the free stock that expires soonest — the stock an issue takes first. Partial reservations are allowed — if only 3 of 5 needed are free, the WO releases with 3 reserved, the part line’s Reserved quantity reads 3, and the planner sees the shortfall.
Putting the work order on hold keeps its reservations. Releasing it again gives them back and reserves afresh from what is free that day, so a job never holds the same units twice.
Reservations release on:
- Part issuance (the job’s reservation goes down by what the issue used of it, and on-hand by the whole quantity issued).
- A return of an issued part, unused or under warranty. It gives back whatever that part line still has reserved, so the line reads 0 reserved afterwards and any later issue for it comes from free stock.
- Work-order cancellation (all remaining reservations release).
- Work-order completion or closing, if anything is still reserved (it didn’t get used, so it’s freed).
Whose stock an issue takes
An issue from the work order’s own warehouse first uses what the job has reserved for that part, up to the quantity issued, and takes anything beyond that from free stock only. An issue from another warehouse takes the whole quantity from that warehouse’s free stock, and the job’s reservation in its own warehouse is given back all the same, up to the quantity issued. An issue never takes stock another order has already set aside — a spare promised to a customer, or reserved for another job, stays where it is. If what the issue may take falls short, the issue is refused and nothing moves; the message says how much was available against how much you tried to issue.
Repair pool
Some parts are repairable rather than disposable: an electronic board, a precision gauge, a motor. The flow:
- The technician records the failed part on the work order’s issue form as an Unused return or a Warranty return, turns on Repair pool, and picks the Repair-pool location the part waits in. Only the source warehouse’s locations set aside for repairs are offered; where the warehouse has none, the form reads None in this warehouse instead, and the return goes back to the shelf. A consumed or scrapped part cannot be sent to the repair pool: those take stock out, and repair-pool stock is never taken.
- Neither the reservation made at WO release nor a part issue ever takes 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.