---
title: Convert stock
order: 9
updated: 2026-07-12
---

# Convert stock

A conversion turns stock of one product into stock of another. Use it when raw material becomes a finished good — say, 10 kg of steel becomes a finished steel pipe of a particular make — or when a bulk item is broken down into smaller sellable units. It is recorded as a single linked event with a *From (consumed)* side and a *To (produced)* side, so the audit trail always shows the two together as one movement.

A conversion is treated by every stock calculation as **two independent movements**: it subtracts the *From* quantity from the source product at the source rack, and adds the *To* quantity to the destination product at the destination rack. Because of that, it shows up everywhere a normal movement would — in the stock snapshot, the per-rack breakdown, the [stock ledger](/docs/inventory/stock-history), and location reports. There is no "recipe" or costing link between the two sides: the quantities are whatever you type, and the two products keep their own separate balances.

Like [Transfer stock](/docs/inventory/transfer-stock) and [Physical stock entry](/docs/inventory/physical-stock-entry), a conversion takes effect **immediately** — there is no approval step.

## Open Convert Stock

1. Open *Inventory* in the sidebar and click *Stock*.
2. Open the dropdown at the top right and hover *Convert* to open its submenu.
3. Pick *Convert Stock* to record a new conversion, or *Convert History* to review past ones.

The whole *Convert* submenu only appears if your role has the *Convert Stock* permission (`inventory.convertStock`) or you are a firm administrator (`admin.isAdmin`). If neither is set, the group is hidden entirely.

### Who can record a conversion

Recording is gated twice, and the backend re-checks both on every submit regardless of what the screen showed:

- **Permission** — you must have `inventory.convertStock`, or be a firm administrator.
- **Location scope** — you must hold *manage* scope on **each** side independently. For a side to pass, you need scope on **at least one** of its godown, room, or rack (it is an OR across the three, not all three). The source and destination are checked separately, so you cannot move stock *into* a location you do not manage even if you manage the source. Administrators bypass the scope check.

A conversion that fails either check is rejected server-side with a `403`, even if the form let you build it.

## Record a conversion

The *Convert Stock* modal has a *Date* at the top, two mirror-image sides (*From (consumed)* on the left, *To (produced)* on the right) joined by an arrow, then *Notes* and *Attachments*.

### Date

The date the conversion is recorded against. Defaults to today. The picker will not let you choose a future date (it caps at today). Backdating is allowed — a backdated conversion simply contributes to the running balance without recomputing earlier rows. The date is required; an unparseable or missing date is refused.

### From (consumed) side

This is the product and location that stock **leaves**.

#### Product Head

Searchable autocomplete. Required. Pick the product head (category) first — the *Product Code* and *Make* fields stay disabled until a head is chosen, and changing the head clears the code beneath it.

#### Product Code

Searchable autocomplete, filtered to codes under the chosen head. Required. This is the specific product being consumed. Picking a code triggers the location auto-fill described below and loads the code's allowed units.

#### Make

Searchable autocomplete, optional, filtered to the chosen head. Pick it only if the source stock is tracked by a specific make/brand. Leaving it blank targets the "unspecified make" bucket. The make you pick narrows which stock the conversion draws from.

#### Quantity and Unit

- *Quantity* — a number field, minimum `0`, defaulting to `0`. It must be **greater than zero** to save; both the form and the server reject `0` or negatives.
- *Unit* — a dropdown, disabled until a code is picked. The options are the units allowed for that product code (its `allowedUnit` list); if the code allows only one unit, it is filled in automatically. Required.

> There is **no stock-availability check.** The conversion subtracts the quantity you enter even if the source rack does not hold that much — the balance can go negative. Confirm the source has the stock before saving.

#### Godown, Room, Rack

Three linked dropdowns for where the source stock currently sits. All three are required.

- *Godown* lists only godowns within your manage scope (administrators see all). Picking one loads its rooms.
- *Room* is disabled until a godown is picked; it lists rooms in scope. Picking one loads its racks. If a godown has exactly one in-scope room, it is selected for you.
- *Rack* is disabled until a room is picked. A single in-scope rack is selected for you.

Each option in these dropdowns shows the quantity of the chosen product currently held at that location, so you can see where the stock actually is before choosing.

**Location auto-fill.** As soon as you pick the *From* product code, the source location auto-fills to the rack **holding the most stock** of that product (within your scope), drilling the godown → room → rack for you. You can override any level manually. If the product has no in-scope stock anywhere, nothing is auto-filled.

### To (produced) side

Identical fields to the *From* side — *Product Head*, *Product Code*, *Make*, *Quantity*, *Unit*, *Godown*, *Room*, *Rack* — for the product that stock is **added** to. The two quantities are independent: converting 10 units of A can produce 3 units of B, 10 of B, or any figure you enter.

The destination can be the same rack as the source or a different one. What it **cannot** be is fully identical: if the *To* side matches the *From* side on product code **and** rack **and** make **and** unit, the conversion is a pointless self-loop and is refused both in the form and on the server. At least one of those four must differ.

**Location auto-fill (destination).** Picking the *To* product code auto-fills the destination to the rack most in **deficit** (most negative) for that product — so a correction lands where it is needed — falling back to the rack with the most stock, then to a zero-stock location that already exists in the product's history. It never invents an unrelated rack, and only picks within your scope.

### Notes

Optional free-text (*Reason, batch reference, etc.*). Record a batch number, the reason, or a supervisor-approval reference here. Notes are sanitised on the server — any embedded scripting is stripped and logged as a security event — so only safe text is stored.

### Attachments

Optional. Drag and drop files onto the drop zone, or click *browse*. Supported: PDF, images, and Word documents, **up to 50 MB each**; oversized files are skipped with a warning, and duplicate filenames are ignored. There is no fixed cap on the number of files. Uploads must finish processing (reach a `READY` state) before the conversion will save — the server rejects the submission if any attachment is still uploading.

### Save

Click *Save Conversion*. On success the source balance drops and the destination balance rises immediately, and the event appears in *Convert History* and as two linked rows in the stock ledger. The form validates every field before sending and shows the first problem as a warning; the server re-validates everything (ids, location relationships, permission, scope, self-loop, date, attachments) and returns a clear message on any failure.

## Review past conversions

From the *Convert* submenu on *Stock*, pick *Convert History*. The modal lists every conversion newest-first with filters across the top.

### Filters

- *Product Head* — matches conversions that touch a code under this head on **either** side (From or To).
- *Product Code* — disabled until a head is picked; narrows to conversions touching this exact code on either side.
- *From Date* / *To Date* — limit the date range. Either can be used alone.

Both date pickers cap at today. Clearing a filter re-runs the list.

### What each row shows

Each row shows the *Date*, the *From* side (product, `−quantity unit`, make, and `godown › room › rack`), an arrow, the *To* side (same, shown as `+quantity`), and who performed it (*By*). A hidden-by-default *Notes* column can be enabled from the table's column control. The list is paginated `10` per page with page controls at the bottom.

### Who sees which rows

The list respects your scope. Administrators and users with an `all` scope see every conversion. A scoped user sees only conversions whose source **or** destination location falls inside their manage scope. A user with `convertStock` but **no** location scope at all sees only the conversions they performed themselves.

### Row actions

- *View* — opens the full detail (both sides with locations, notes rendered, and downloadable attachments). Viewing requires the *View Inventory* permission (`inventory.viewInventory`) on the server.
- *Edit* (pencil) and *Delete* (trash) — shown only if you have the *Convert Stock* permission (or are an administrator). Both re-check your scope on the entry's existing locations before doing anything.

## Edit a conversion

Click the pencil on a history row. The *Edit Stock Conversion* modal loads the entry.

**Locked (cannot change):** the *Product Code*, *Godown*, *Room*, and *Rack* on each side. These are shown as a read-only header. If any of them is wrong, delete the conversion and record a fresh one.

**Editable:**

- *Date* — same picker rules as recording (no future dates).
- *Quantity* — per side; must stay greater than zero.
- *Unit* — per side, from the product code's allowed-unit list.
- *Make* — per side; can be changed or cleared (clearing sets it back to "unspecified").
- *Notes* — sanitised on save like on create.
- *Attachments* — remove existing files (click the ✕) and/or add new ones (same 50 MB, `READY`-state rules).

Click *Save Changes*. The server verifies your scope on the entry's **existing** locations before applying anything, so a user who lost scope on either side can no longer edit it. Editing quantities immediately re-flows the affected balances.

## Delete a conversion

Click the trash icon and confirm *Delete this conversion?*. The entry is **soft-deleted**: it stops contributing to stock on both sides immediately, but the record stays in the database for audit (flagged deleted, with who and when). Deletion needs the *Convert Stock* permission plus manage scope on both of the entry's locations. There is no separate "restore" action — to bring the movement back, record it again.

## How conversions show in the stock ledger

Every conversion produces **two** rows in the [stock ledger](/docs/inventory/stock-history), one on each product's own ledger:

- A *Convert Out* row on the source product code, captioned `→ converted to <destination product>`.
- A *Convert In* row on the destination product code, captioned `← converted from <source product>`.

Both rows share the conversion's date, so you can trace the same event from either product. This is also why the audit filter in *Convert History* matches on either side — the two ledgers are separate, but the caption ties them back to one event.

## Common questions

### Why are there two ledger rows for one event?

Because the two products keep separate stock totals. Each ledger is product-specific, so the conversion has to appear on both sides — a *Convert Out* on the source and a *Convert In* on the destination. The linkage caption (`converted to` / `converted from`) tells you it is the same event.

### Can a conversion be undone?

Soft-delete it from *Convert History*. Both balances revert immediately. The deleted record drops out of the ledger and stock figures but stays in the database for audit; it cannot be un-deleted, so re-record it if you removed it by mistake.

### I picked the wrong product or location — can I fix it in Edit?

Only quantity, unit, make, date, notes, and attachments are editable. Product code and the godown/room/rack on each side are **locked** once recorded. Delete the conversion and create a fresh one with the correct product and location.

### Does a conversion need approval?

No. It takes effect the moment you save — unlike deliveries and arrivals, there is no pending/approve step. The two permission checks (*Convert Stock* plus manage scope on both sides) are the only gate.

### The stock went negative after a conversion — is that a bug?

No. Conversions do not check that the source rack holds enough stock before subtracting, so entering more than is on hand drives the balance negative. Verify the source quantity (each location dropdown shows the on-hand figure) before saving, or use [Physical stock entry](/docs/inventory/physical-stock-entry) to correct a genuinely wrong snapshot.

### I can see some conversions but not others — why?

The history list is scoped. You only see conversions whose source or destination location is within your manage scope. If you have the *Convert Stock* permission but no location scope, you see only the conversions you recorded yourself. Administrators and `all`-scope users see everything.

### Can I convert between two makes of the same product?

Yes. As long as at least one of product code, rack, make, or unit differs between the two sides, the conversion is valid — so converting make A of a code into make B of the same code (or into the unspecified bucket) is allowed.
