Material Requisitions & Issues
Formally request the raw materials a Work Order needs, get the request approved, then record each physical hand-out of material against that order — all in one place, under a single controller.
production/MaterialRequisitions
controller: (1) Requisitions — a request document (header + line items) with an approval
step; and (2) Material Issues — a consumption log recording materials actually handed out
against a Work Order.
item_inventories), it does not increment the requisition line's
Qty Issued, and it does not advance the requisition's status. Any real stock movement
must be done separately in the Inventory module. See
How issuing affects inventory below.
The flow at a glance
A requisition is a header document with one or more item lines. It is created as a Draft, Approved in one click, and then materials are physically Issued against the linked Work Order. In the current build only the Draft → Approved step is automated — everything after that is a manual/local procedure.
in_progress work orders appear in the Work Order
dropdowns. The Units of Measure you need must also exist and be active in Manufacturing UoM.
The screens
production/MaterialRequisitions — the list. Columns: Requisition #, Work Order, Required Date, Status, Requested By, and a per-row gear menu (View, Items, Edit, Delete). Includes a Status filter.
Modal to create or edit a header: Requisition # (prefilled), Work Order, Required Date, Notes.
/view/{id} — details, approval info, the item lines, and the material issues. Hosts the conditional Approve and Issue Materials buttons.
/items/{id} — manage line items on a full page (Add Item is always available here).
/issues — every recorded issue, with a Work Order filter and a New Issue button.
Modal to record a hand-out: Issue # (read-only), Work Order, Item, Lot #, Quantity, UoM, Unit Cost, Notes.
Requisition header fields
These are the fields on the New / Edit Requisition modal plus the system-maintained header
values shown on the detail page. Auto-numbering uses the requisition_prefix setting
(default MR) plus a zero-padded 6-digit sequence, e.g. MR-000001.
| Field | Meaning | Required | Notes |
|---|---|---|---|
requisition_number — Requisition # |
Human-readable requisition identifier. | Required | Editable text input. New records are prefilled with the next auto-number: prefix (default MR) + - + 6-digit sequence, e.g. MR-000001. Unique per (requisition_number, deleted). |
order_id — Work Order |
The manufacturing work order this requisition supplies materials for. | Required (client-side only) | Select2 of in_progress work orders; each option shows order_number - product_name. Marked * in the modal but not enforced server-side — the DB column is NOT NULL with a FK, so saving without one can fail at the database level. |
required_date — Required Date |
Date the materials are needed by. | Required (client-side only) | HTML date input; stored as datetime, nullable. Marked * in the modal but not enforced server-side. |
notes — Notes |
Free-text remarks about the requisition. | Optional | Textarea. |
requisition_date — Requisition Date |
Date the requisition was created. | Auto | Not shown on the modal. Defaults to the current UTC time on save if not posted. |
status — Status |
Lifecycle state of the requisition. | Auto | Enum: draft, submitted, approved, issued, partial, completed, cancelled. Not editable on the modal; set to draft on new save, changed to approved only via the Approve action. |
requested_by — Requested By |
User who created the requisition. | Auto | Set to the logged-in user on creation; displayed as full name (first + last). |
approved_by — Approved By |
User who approved the requisition. | Auto | Set by the Approve action; shows Pending until approved. |
approved_at — Approved Date |
Timestamp of approval. | Auto | Set by the Approve action; shows N/A until approved. |
operation_id column (per-operation linkage) that is
not exposed anywhere in the UI. There is no separate Status selector on the create/edit
modal — status is driven entirely by the Approve action.
Requisition item (line) fields
Each requisition holds one or more material lines. Add them from the Add Requisition Item modal. On the detail page the Add Item button is shown only while the requisition is Draft; the standalone Items page always shows it.
| Field | Meaning | Required | Notes |
|---|---|---|---|
item_name — Item Name |
Name / description of the material line item. | Required | Free-text input — not a linked catalog picker. item_id is stored as 0 when not provided, so lines are not tied to real Inventory items. |
quantity_required — Required Quantity |
Quantity of the material needed. | Required | Number input, step 0.0001; stored decimal(15,4); displayed with 4 decimals + the UoM symbol. |
uom_id — Unit of Measure |
Unit the quantity is expressed in. | Required | Select2 of active Manufacturing UoMs (is_active=1); option label name (symbol). |
quantity_issued — Qty Issued |
Quantity already issued for this line. | System | Defaults to 0.0000 and is never automatically incremented when a Material Issue is saved. The Remaining column = quantity_required − quantity_issued, so it will not change after issuing. |
notes — Notes |
Remarks for the line item. | Optional | Textarea; shows - when empty. |
quantity_issued is never auto-updated, the requisition Items table's
Issued and Remaining columns are informational targets only — they do not reflect the
Material Issues you record. Track fulfilment manually if your process depends on it.
Material Issue fields
A Material Issue records one physical hand-out of material against a Work Order. Open it either from
an approved/partial requisition (Issue Materials) or standalone from the Material Issues
list (New Issue). Auto-numbering uses the issue_prefix setting (default
MI), e.g. MI-000001.
| Field | Meaning | Required | Notes |
|---|---|---|---|
issue_number — Issue # |
Human-readable material-issue identifier. | Required | Read-only, auto-numbered: prefix (default MI) + - + 6-digit sequence. Unique per (issue_number, deleted). |
order_id — Work Order |
Work order the material is issued / consumed against. | Required | Enforced server-side. Select2 of in_progress work orders. DB column NOT NULL with a FK to manufacturing_work_orders. |
requisition_id — Requisition (link) |
Optional link back to the originating requisition. | Optional | Hidden field; blank when the modal is opened standalone. Stored nullable. |
item_name — Item Name |
Material being issued. | Required | Free-text; item_id stored 0 if not provided (no catalog link). |
lot_number — Lot Number |
Batch / lot reference of the material, for traceability. | Optional | Free text. |
quantity_issued — Quantity |
Amount of material issued / consumed. | Required | Number input, step 0.0001; stored decimal(15,4). |
uom_id — Unit of Measure |
Unit the issued quantity is expressed in. | Required | Select2 of active UoMs. |
unit_cost — Unit Cost |
Cost per unit of the issued material. | Optional | Number input, step 0.0001; stored decimal(15,4). Defaults to 0. |
total_cost — Total Cost |
Extended cost of the issue. | Auto | Computed server-side = quantity_issued × unit_cost; stored decimal(15,2). Not shown as an input. |
issued_by — Issued By |
User who recorded the issue. | Auto | Set to the logged-in user; displayed as full name. |
issue_date — Date |
When the material was issued. | Auto | Set to the current UTC time on save. |
notes — Notes |
Remarks about the issue. | Optional | Textarea. |
Requisition status lifecycle
The requisition status column is an enum with seven values. Every value has a badge and
can be picked in the Status filter, but only Draft → Approved is wired to an action. The
remaining states are valid, filterable, badge-able values with no built-in transition trigger
in this controller — they would only be reached by editing records or by other code.
How issuing materials affects inventory
In plain terms: it doesn't. Recording a Material Issue writes a row to
manufacturing_material_issues and nothing else. There is zero Inventory
integration in this feature — no write to item_inventories, items, or
variants, and no stock '-' movement is posted.
'-' flowContrast this with a completing Manufacturing Order, which
does post consumption to Inventory. Here, the item lines and issues store an
item_id that defaults to 0 (no catalog picker in the forms) and the item
name is free text — so there is nothing to deduct against even if you wanted to.
- What it does capture
- Item, lot number, quantity, unit of measure, unit cost, auto-computed total cost, who issued it, and when — tied to a Work Order (and optionally a requisition).
- What it does not do
- Deduct
item_inventoriesstock; increment the requisition line's Qty Issued; advance the requisition status; validate against on-hand quantities.
Actions & permissions
The entire controller is gated by a single permission. The Manufacturing module must be
enabled and the manufacturing_requisition key must be granted — that one key controls
viewing, creating, editing, approving, issuing and deleting. There is no separate
create/update/delete enforcement in the controller.
| Action | Effect | Confirmation | Permission |
|---|---|---|---|
| New Requisition / Save | Opens the modal; on Save creates (status draft, sets uuid, requested_by = current user, created_at) or updates a requisition header. |
None | manufacturing_requisition |
| Edit requisition | Opens the same modal prefilled; Save updates the header (updated_at refreshed). Not restricted by status. | None | manufacturing_requisition |
| Delete requisition | Soft-deletes the requisition (deleted=1) via Crud_model. |
Standard delete-confirmation dialog (data-action="delete-confirmation"). |
manufacturing_requisition |
| Add Item / Save item | Adds a requisition line (uuid, requisition_id, item_id=0 if none, item_name, quantity_required, uom_id, notes, created_at). On the detail page the button shows only while status = Draft; the standalone Items page always shows it. | None | manufacturing_requisition |
| Delete item | Soft-deletes a requisition line item. | Standard delete-confirmation dialog. | manufacturing_requisition |
| Approve | Sets status = approved, approved_by = current user, approved_at = now, updated_at = now. Shown only when status = Draft. |
None — it is a plain GET link that approves immediately. | manufacturing_requisition |
| Issue Materials | Opens the material-issue modal from the detail page (shown only when status = Approved or Partial). On Save records a new issue row. Does not change status, update Qty Issued, or adjust inventory. | None | manufacturing_requisition |
| New Issue / Save issue | Creates a material issue with total_cost = qty × unit_cost, issued_by = current user, issue_date = now. Standalone from the Material Issues list. | None | manufacturing_requisition |
| Delete issue | Soft-deletes a material issue record. Restores no inventory (none was deducted). | Standard delete-confirmation dialog. | manufacturing_requisition |
| View / Items (row menu) | Navigate to the requisition detail page / the line-items page. | None | manufacturing_requisition |
| Status filter / Work Order filter | Filters the requisitions table by status, or the issues table by work order. | None | manufacturing_requisition |
Permission keys
| Key | What it does | Enforced? |
|---|---|---|
manufacturing |
The Manufacturing module must be enabled — the constructor calls with_module('manufacturing','redirect'). |
Yes |
manufacturing_requisition |
Module-level permission gating the entire controller (with_permission('manufacturing_requisition','redirect')). Controls view, create, edit, approve, issue, delete. |
Yes |
manufacturing_requisition_create |
Declared in config/permissions.php for granularity. |
Not checked |
manufacturing_requisition_update |
Declared in config/permissions.php for granularity. |
Not checked |
manufacturing_requisition_delete |
Declared in config/permissions.php for granularity. |
Not checked |
_create/_update/_delete keys exist for future
granularity but are not actually checked in MaterialRequisitions.php. Anyone
with manufacturing_requisition can do everything in this area. See the full
Permissions & Roles matrix.
SOP — Raise and fulfil a material requisition
-
Confirm the preconditions
The target Work Order must be in progress (only those appear in the dropdowns) and the Units of Measure you need must be active in Manufacturing UoM.
-
Create the requisition (Supervisor)
Open Production → Material Requisitions and click New Requisition. The Requisition # is prefilled (e.g.
MR-000002). Pick the Work Order, set the Required Date, add Notes, then Save. The requisition is created as Draft. -
Add the material lines (Supervisor)
From the row gear menu choose View (or Items). While the status is Draft, click Add Item; enter Item Name, Required Quantity, Unit of Measure and Notes, then Save. Repeat for each material.
-
Approve (Supervisor / Approver)
Back on the detail page, click Approve. The status flips to Approved and the Approval Info panel shows your name and the timestamp.
-
Issue the materials (Storekeeper)
On the approved (or partial) requisition, click Issue Materials. The Issue # is auto-filled (read-only). Select the Work Order, type the Item Name, add an optional Lot Number, enter the Quantity, select the Unit of Measure, and enter an optional Unit Cost. Click Save.
-
Reconcile manually
Because the system does not auto-update: manually track the requisition line's Qty Issued and the overall status per your local procedure, and separately deduct physical stock in the Inventory module — this feature does not deduct inventory.
Record ad-hoc consumption (no requisition)
-
Open Material Issues
Go to Production → Material Issues and click New Issue. This path needs no requisition.
-
Fill the issue
Select the Work Order (in-progress only), enter Item Name, Lot Number, Quantity, Unit of Measure, Unit Cost and Notes.
-
Save
Click Save. The consumption is logged against the Work Order and Total Cost is auto-computed (Quantity × Unit Cost). Use this for costing/logging only — adjust real stock in Inventory separately.
Validation & messages
Server-side validation runs on every save. Required fields are marked with a red * on
the modals, but note that some client-side * marks are not re-enforced on the
server (see the warning below).
| Operation | Server-side rules | Success message | Failure message |
|---|---|---|---|
| Save requisition | id numeric; requisition_number required. |
"The record has been saved." | error_occurred |
| Delete requisition | id required, numeric. | "The record has been deleted." | "The record is in use, you can't delete the record!" / "Record cannot be deleted!" |
| Save requisition item | requisition_id required, numeric; item_name required; quantity_required required, numeric; uom_id required, numeric. | "The record has been saved." | error_occurred |
| Delete item / delete issue | id required, numeric. | "The record has been deleted." | "Record cannot be deleted!" |
| Approve | id required, numeric. | "Requisition approved" (hardcoded English, not a lang key) | error_occurred |
| Save material issue | issue_number required; order_id required, numeric; item_name required; quantity_issued required, numeric; uom_id required, numeric. | "Material issued successfully" (hardcoded English) | error_occurred |
data-rule-required), but the server save() allows
order_id to be null — while the DB column is NOT NULL with a FK. Saving a
requisition without a Work Order can therefore trigger a database error. Always pick a Work Order.
Watch-outs
item_inventories) integration. Issues are a consumption/costing log only. Deduct real stock separately in the Inventory module. See How issuing affects inventory.0 and Remaining never changes after issuing; the requisition status is not advanced. Track fulfilment manually./items/{id}) always shows Add Item — so items can still be added after approval through that page.in_progress orders. If the relevant order is not in progress you cannot select it (and existing requisitions on other-status orders show the order but you cannot re-pick it).item_id defaults to 0, so requisition items and issues are not linked to real Inventory items. There is no variant picker in the forms.requisition_prefix or issue_prefix in Manufacturing Settings restarts numbering at -000001 for the new prefix.