Skip to main content

Stock adjustments

Route: /org/inventory/maintenance · Module: org_inv_maintainence — 4 permissions Permission to adjust: Adjust Inventroy

The module code is misspelled, and it matters

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."

Figure 1 — The list. 1 operation filter · 2 item-type filter.
ColumnNotes
OperationStock Adjustment or Wastage / Spoilage
ScopeRaw Materials or Finished Goods
ReferenceYours
ReasonDecoded from the remarks
ItemsLines in the batch
Net ΔSum of the deltas — can be positive or negative

2. Four entry modes, one screen​

Figure 2 — Operation × scope. Four combinations.

New Entry asks two questions at once:

Raw MaterialsFinished Goods
Stock AdjustmentCounted RM that doesn't match system stock — adjust +/−Counted FG that doesn't match — adjust +/−
Wastage / SpoilageSpoiled, expired or damaged RM — decrement onlySpoiled, 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​

Figure 3 — Enter what you counted; the app computes the delta.

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.

FieldRequiredNotes
Counted quantityper lineOnly lines that differ are posted
Reference—Yours, e.g. AUD-2607-07
Reason✅Pick or type
Remarks—Free text

Validation — exact strings​

ConditionMessage
No line differs from systemEnter at least one counted quantity that differs from the system
No reason givenPick or type a reason for this entry
SuccessStock Adjustment posted • N items
FailureFailed to post entry

4. Reasons​

The reason picker is permanently empty

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:

FieldValue
transaction_typeADJUSTMENT
quantityThe delta — signed
batch_idShared across the entry
reference_noYours
remarks[REASON:…] <your notes>
An adjustment does not change current_stock either

This 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​

ActionPermissionEnforced?
Viewmaintenance.view✅
Menumaintenance.menu✅
Adjustmaintenance.adjust✅ at the API
Wastagemaintenance.waste❌ never checked — wastage is gated by adjust

7. Troubleshooting​

SymptomCause
Reason dropdown is emptyThe master list is empty on every org and cannot be populated — see §4
Save refusedNo line differs from system, or no reason was given
A counted line was not postedIts delta was 0
System stock still wrong afterwardsAdjustments write the ledger, not current_stock
A colleague can open the form but not postThey lack maintenance.adjust; the UI does not hide the button