Skip to main content

Production orders

Route: /org/inventory/production · Module: org_inv_production — 6 permissions Permission to view: View Production and Manufacturing Trends


1. What production is​

Turning raw materials into finished goods. A production order says make 20 of this variation, pulls its bill of materials, and — on completion — posts the whole movement to the ledger in one go.

The screen's own subtitle states the contract: "Manufacture finished goods — auto-consumes raw materials per BOM on completion."

Figure 1 — The order list. 1 status filter · 2 New Production Order.

2. How an order moves​

StatusEditableCan completeCan cancel
DRAFT✅ quantity and ingredients✅✅
COMPLETED❌❌ already done❌ ledger already posted
CANCELLED❌❌idempotent — cancelling again is a no-op
A completed order can never be cancelled

The exact refusal is completed orders cannot be cancelled — ledger already posted. Completion writes real ledger rows; reversing them would mean deleting audit history.

To correct a completed run, post a compensating adjustment. Both entries stay visible.


3. Creating an order​

Figure 2 — Two fields, and it always creates a DRAFT.

Two inputs only.

Finished Good to Produce — a variation, not a product. The recipe belongs to the variation.

Planned Quantity — defaults to 1, must be greater than 0.

The button says CREATE AS DRAFT, and that is not a choice: CreateProductionOrder always sets status DRAFT.

What happens on create​

For every BOM line on that variation, the app stores an ingredient row:

planned ingredient quantity = BOM quantity_required × planned_quantity
The order takes a COPY of the BOM

From this moment the order carries its own ingredient list. Editing the BOM afterwards does not change orders already created — which is what makes a historic order auditable.

A variation with no BOM produces an order with no ingredients

Nothing warns you. The order is created, it completes happily, and it posts a PRODUCTION_IN row with no corresponding consumption — finished goods appearing from nowhere.


4. Reading the list​

ColumnNotes
OrderThe first 8 characters of the order UUID, e.g. #fb75ec9f
Finished goodProduct name, variation and SKU
Planned / ProducedProduced stays 0 until completion
StatusThe pill
CreatedDo not use — see below
👁Opens the detail drawer
Figure 3 — All four statuses, and the broken Created column on every row.
The Created column is wrong on every row

It reads 01 Jan 0001, 00:53 for every order — visible on all five rows in Figure 3. The list query never selects created_at, so the zero value is serialised and rendered.

The same query orders by o.id DESC — by random UUID, not by date — so the list is not in chronological order either. Use the detail drawer's Completed timestamp, which is correct.


5. Permissions — and what the UI does not check​

ActionPermission
Viewproduction.view
Menuproduction.menu
Createproduction.create
Edit a DRAFTproduction.edit
Completeproduction.complete
Cancelproduction.cancel
This screen performs no permission checks in the UI

New Production Order, Complete and Cancel all render for anyone holding production.view. The API enforces the real permission, so the user meets a failure instead of a hidden control. See Permissions.


6. The admin contract​

Must be trueOr else
A project is selectedThe list is empty
The variation has a BOMThe order consumes nothing on completion
Raw materials exist with unitsThe BOM cannot exist in the first place

7. Troubleshooting​

SymptomCause
List is emptyNo project selected
All Created dates read 01 Jan 0001Known defect — see §4
The list is in a strange orderIt is ordered by UUID, not date
Cannot cancel an orderIt is COMPLETED — the ledger is posted
Completing produced no consumption rowsThe variation had no BOM
Edit is refusedOnly DRAFT orders can be edited: only DRAFT orders can be edited (current: …)