Stock adjustments
Route: /org/inventory/maintenance · Module: org_inv_maintainence — 4 permissions
Permission to adjust: Adjust Inventroy
The module is registered as org_inv_maintainence. Its permissions are spelled correctly —
org.inventory.maintenance.*. Only the module code carries the typo, and it is what a package or
module-map row must match.
1. What an adjustment is
A correction: what you counted does not match what the system says, so you record the difference. The screen's subtitle is "Stock audits and wastage records — keep system stock honest with what's on the shelf."
| Column | Notes |
|---|---|
| Operation | Stock Adjustment or Wastage / Spoilage |
| Scope | Raw Materials or Finished Goods |
| Reference | Yours |
| Reason | Decoded from the remarks |
| Items | Lines in the batch |
| Net Δ | Sum of the deltas — can be positive or negative |
2. Four entry modes, one screen
New Entry asks two questions at once:
| Raw Materials | Finished Goods | |
|---|---|---|
| Stock Adjustment | Counted RM that doesn't match system stock — adjust +/− | Counted FG that doesn't match — adjust +/− |
| Wastage / Spoilage | Spoiled, expired or damaged RM — decrement only | Spoiled, expired or damaged FG — decrement only |
The distinction is signed:
- Adjustment can go either way. You counted more, or you counted less.
- Wastage only goes down. The cards carry a
−badge to say so.
See Wastage and spoilage for the lower row.
3. Recording an adjustment
You enter the counted quantity, not the difference. The delta is computed:
delta = counted − system
A row with delta = 0 is skipped entirely — it is not posted as a zero-movement row.
| Field | Required | Notes |
|---|---|---|
| Counted quantity | per line | Only lines that differ are posted |
| Reference | — | Yours, e.g. AUD-2607-07 |
| Reason | ✅ | Pick or type |
| Remarks | — | Free text |
Validation — exact strings
| Condition | Message |
|---|---|
| No line differs from system | Enter at least one counted quantity that differs from the system |
| No reason given | Pick or type a reason for this entry |
| Success | Stock Adjustment posted • N items |
| Failure | Failed to post entry |
4. Reasons
Reasons are meant to come from a master list (organization_inventory_adjustment_reasons). That
table is empty on every organisation, and there is no route to add to it — the API exposes
GET /adjustment-reasons and nothing else.
So the dropdown never has options and every reason is free text. Nothing normalises the wording, and
the [REASON_ID:] tag the app is designed to store is never written.
If you want consistent reporting on why stock moves, agree the wording as a team convention — the product will not enforce it.
Reasons are encoded into the row's remarks as [REASON:<text>], which is how the list decodes them.
5. What an adjustment writes
One ADJUSTMENT ledger row per differing line:
| Field | Value |
|---|---|
transaction_type | ADJUSTMENT |
quantity | The delta — signed |
batch_id | Shared across the entry |
reference_no | Yours |
remarks | [REASON:…] <your notes> |
current_stock eitherThis is the screen whose entire purpose is "keep system stock honest with what's on the shelf" —
and it writes a ledger row while leaving current_stock untouched.
If the number you were trying to correct was the one on the Raw materials or Products screen, this did not correct it. Edit the record directly for that. See How stock is counted.
6. Permissions
| Action | Permission | Enforced? |
|---|---|---|
| View | maintenance.view | ✅ |
| Menu | maintenance.menu | ✅ |
| Adjust | maintenance.adjust | ✅ at the API |
| Wastage | maintenance.waste | ❌ never checked — wastage is gated by adjust |
7. Troubleshooting
| Symptom | Cause |
|---|---|
| Reason dropdown is empty | The master list is empty on every org and cannot be populated — see §4 |
| Save refused | No line differs from system, or no reason was given |
| A counted line was not posted | Its delta was 0 |
| System stock still wrong afterwards | Adjustments write the ledger, not current_stock |
| A colleague can open the form but not post | They lack maintenance.adjust; the UI does not hide the button |