---
title: Add a stock arrival
order: 4
updated: 2026-07-21
---

# Add a stock arrival

When a supplier delivers goods, you log them as a *stock arrival*. Each arrival names the supplier, lists the items on the supplier's invoice, and places every item into a specific warehouse location (godown → room → rack). Once the arrival is approved, that quantity is added to your on-hand stock and its cost feeds the product's valuation.

There are two ways to log an arrival, and both end up in the same place — the *In Stock* screen's *Arrival History*:

- **Direct entry** — a standalone *Add Stock Entry* page you reach with the *Add Entry* button. Use this when the goods did not come in against a purchase order (a walk-in supply, a cash purchase, or any receipt you track without a PO).
- **Against a purchase order** — an *Upload Stock Arrival* modal opened from a pending PO. Use this when you sent the supplier a PO and are now receiving what they shipped. The form is pre-scoped to that PO's open lines and tracks the remaining quantity for you.

Every field below is re-checked by the server on save. The form's own validation is only a convenience — a forged or malformed payload (a fake product code, a rack that isn't in the chosen room, a location you have no rights to) is rejected before any stock moves.

## Before you start

- The supplier and their contact person must already exist. See [Suppliers](/docs/records/suppliers).
- The product head (category) and product code must exist. See [Products](/docs/records/products).
- The godown, room, and rack you are placing stock into must exist and be inside your permission scope. See [Warehouses](/docs/records/warehouses).

## Open the direct entry form

1. Open *Inventory* in the sidebar and click *In Stock*.
2. Click *Add Entry* at the top right. A full page opens with the heading *Add Stock Entry*.

The *Add Entry* button only appears if you are a firm admin or hold the *Generate Add Stock Request* (`generateAddStockRequest`) permission. Without it there is no way to reach this page, and the server rejects the save even if the request is sent directly.

## Supplier and invoice header

The top of the form captures who supplied the goods and against which document.

### Supplier

*Select Supplier* — a searchable picker of your suppliers. Required. Picking a supplier also scopes the product-category, product-code, and make searches below to that supplier's catalogue where one is configured, so you see the items you actually buy from them first.

### Contact person

*Select Contact Person* — the person at the supplier this invoice came from. Required, and enabled once a supplier is chosen. Changing the supplier clears the contact person so you can never save a mismatched pair. The server confirms the contact person exists before saving.

### Invoice number

*Invoice No.* — the supplier's invoice number, for example `INV-001`. Required on the direct form. This is what the *Arrival History* list and the arrival receipt email show as *Invoice No.*

### Invoice date

*Invoice Date* — the date printed on the supplier's invoice. Required. It defaults to today and you cannot pick a future date (the calendar caps at today). Shown as `dd/mm/yy` throughout the app.

### Header notes

*Notes* — an optional free-text line (placeholder *Any notes…*) for anything about the whole arrival that isn't tied to a single item. This is a plain-text field; per-item notes are separate (see [Per-line notes](#per-line-notes)).

## Add product lines

Each row on the supplier's invoice becomes one product line. The form starts with a single empty row; use *Add Product Row* to add more and the trash icon to remove one. Every row carries the fields below. The compact grid holds the essentials; the collapsible panel underneath each row (toggle with the chevron) holds the make/HSN, location, and per-line notes.

### Product category

*Select Category* — the product head. Required. This is the first thing to pick because it filters the product-code list. Changing the category clears the code you had chosen (and its cached defaults) so you can't leave a code that belongs to a different category.

### Product code

*Select Code* — the specific product code, searchable and filtered to the chosen category. Required. Selecting a code pulls that code's saved defaults into the row:

- its default **HSN code**,
- its **default tax rate** (falls back to `18` if the code has none set),
- its **allowed units** — if the code permits exactly one unit, that unit is filled in and locked; otherwise the *Unit* field is left for you to choose,
- and its **default description**, shown in the read-only panel on the left of the row.

### Quantity

*Qty* — how many units arrived. Minimum `1`, default `1`. The server requires a positive quantity.

### Unit

*Unit* — the unit of measure (searchable). If the product code allows only one unit, this is auto-filled and disabled. Otherwise it is required and you pick from the units your firm has defined. The value stored is the unit's short form.

### Price per unit

*Price/Unit* — the purchase cost of one unit, shown in `₹` (INR). Minimum `0`, default `0`. This price drives the arrival's value and the product's weighted-average cost, so enter the real invoice rate. The server rejects a negative price.

### Tax rate

*Tax %* — the GST slab for this line. Allowed values are the standard slabs `0`, `5`, `12`, `18`, and `28` percent. The default is `18` (or the product code's own default rate if it has one). If the product code is marked as always carrying the same tax rate, this field is locked to that rate. The server accepts any value from `0` to `100` but the picker only offers the five slabs.

### Final price

*Final Price* — a read-only figure the form computes as `quantity × price/unit × (1 + tax% ⁄ 100)`. It is there to sanity-check the line total; it is not an input and is not sent to the server.

### Make and HSN (the Factory button)

The **Factory** icon on the row's side strip opens a small popover holding two fields:

- *Make* — the manufacturer/brand for this line. **Required.** The picker is disabled until a category is chosen (it reads *Choose a category first* until then, and *Select Make* after). Make options are filtered by the chosen supplier and category. Because make is required, the Factory button is tinted red until a make is set, and after a failed submit the row shows a *Make required* hint pointing at it.
- *HSN Code* — a numeric field pre-filled from the product code. It is disabled when no product is selected or when the code is marked as always using the same HSN. Leave it as-is unless this particular invoice used a different HSN. If you clear it, the server falls back to the product code's stored HSN.

### Storage location (the Warehouse button)

The **Warehouse** icon opens a location popover with a three-step cascade — *Godown* → *Room* → *Rack*. All three are required; the button stays red until all three are set, and a *Location required* hint appears after a failed submit.

- The *Room* picker only appears once a *Godown* is chosen, and *Rack* only once a *Room* is chosen.
- Each list is filtered to the locations inside your permission scope (`manageGodownScope` / `manageRoomScope` / `manageRackScope`). Firm admins, or a scope set to `all`, see everything.
- When a level has exactly one option available to you, it is selected automatically and the cascade rolls on — so a user with access to a single rack barely has to click.
- The server independently re-verifies that the rack belongs to the room, the room belongs to the godown, and that you hold manage scope on the location — a hand-crafted request placing stock into a rack you don't control is rejected.

To split one delivered item across two racks, add the item on two rows and give each row a different location.

### Per-line notes

The rich-text box on the right of each row's panel (*Add custom notes for this product…*) records anything specific to that item — batch numbers, condition, a partial-delivery note. It is optional. On approval it is appended to the product code's default description to form the line's final description on the arrival.

## Invoice documents (attachments)

Below the product rows you can attach the supplier's delivery note, invoice, or any proof of receipt. Drag files onto the drop zone or click *browse*. PDF, image, and Word files are accepted, **up to `50 MB` each**. Duplicate file names (already in the list) and oversized files are skipped with a warning.

Whether an attachment is **mandatory** depends on a firm setting: *stock arrival attachment required*, which is **on by default**. While it is on, the server refuses to save an arrival with no file attached — even though the drop zone is labelled *(optional)* — and you get an error asking you to attach a file. An owner can turn this requirement off under [Firm customisation](/docs/settings/firm-customisation), after which attachments become genuinely optional. The same rule applies to reverse (return-to-supplier) entries.

## Submit and what the server checks

Click *Submit Stock Arrival*. The form first shows any missing-field problems inline (a red summary lists them). Once it passes, the arrival is uploaded — with a live percentage while files transfer — and you are returned to the *In Stock* list.

On the server, the arrival is created with status **pending** and re-validated end to end:

- you must hold *Generate Add Stock Request* (or be admin);
- the firm attachment rule is enforced if on;
- the supplier and contact person (if sent) must exist;
- every product code, godown, room, and rack must be a real, correctly-nested record you have scope over;
- notes, per-line notes, and remarks are sanitised against script injection.

A new arrival never adds stock on its own — it waits for approval (see [Approval: how stock actually moves](#approval-how-stock-actually-moves)).

## Record an arrival against a purchase order

When the goods came in against a PO you sent, log the arrival from the PO instead of the direct form. This keeps the two in sync: the PO's remaining quantity is tracked, and once everything has arrived the PO closes automatically.

### Open the upload form

Open *In Stock* → *Pending Arrivals*, click *View* on the PO row, and use the *Upload Arrival* action. (The same action also lives in a PO's own top-right *Arrival* menu.) The modal is titled *Upload Stock Arrival* and shows the PO number, supplier, and contact person in its subtitle. You need the *Upload Stock Arrival From PO* (`uploadArrivalFromPO`) permission; the server re-checks it and rejects the upload otherwise. See [In stock and arrivals](/docs/inventory/in-stock) for the surrounding screen.

The header carries an *Invoice No.* and *Invoice Date* (default today, no future dates) exactly like the direct form — you don't re-pick the supplier because it's pinned to the PO.

### Pick the PO line

The *Select product…* dropdown lists the PO's still-open lines (anything with a remaining quantity). Each entry shows the product code, its make, and how much is `left`; hovering reveals a card with *Ordered*, *Arrived*, and *Remaining* quantities plus HSN and description.

A PO can list the **same product code more than once** — for example the same item ordered under two makes, prices, or quantities. Each is a separate line, tracked on its own, and the two show up as distinct options (labelled with their make). Record what arrived against each independently; one make can stay open in *Pending Arrivals* while the other is fully received.

If you pick a product that is already on another row, a *Already in list* confirmation appears — choose *Re-add Anyway* to add it a second time (useful when one line's stock is split across two racks) or *Cancel*.

### Quantity, price, and tax

- *Qty* — defaults to the line's full remaining quantity, minimum `1`, and is capped at the remaining amount. If you split one line across several rows, the rows must total no more than that line's remaining quantity.
- *Unit Price* — locked. It is pre-filled from the PO line's authorised price so an arrival can't drift from what was ordered.
- **Tax** is frozen from the PO line as well (there is no tax picker in this modal — the rate quoted on the PO at upload time is what the arrival carries).

The *make* for each line is taken from the exact PO line, so you don't re-enter it here.

### Storage location with live stock hints

The *Godown* → *Room* → *Rack* cascade behaves like the direct form (scope-filtered, auto-picking single options), with one addition: each location option shows how much of the selected product it already holds, so you can place incoming stock next to what's already there. A per-product *Remarks* line sits under each row, and an *Additional Notes* box covers the whole arrival.

### Additional charges

If the purchase order carries additional charges (such as *Freight* or *Packing*), an *Additional Charges* section lets you tick the ones this arrival should bill, each with an optional remark. A charge can be billed on only **one approved arrival**: while arrivals are pending the same charge may sit on several, but once one is approved the charge drops off the others' pickers, and approving a second arrival that still claims it is blocked. Attached charges then appear on the arrival's detail view and roll into its subtotal and total. Direct (non-PO) arrivals and reverse entries never carry charges. Charges can optionally be printed in the arrival receipt email — off by default, set per firm under [Firm customisation](/docs/settings/firm-customisation) and [Arrival receipt personalisation](/docs/settings/document-templates#arrival-receipt-personalisation).

### Editing a pending PO arrival

Editing a pending or rejected PO-linked arrival reopens this same modal, pre-filled, titled *Edit Stock Arrival*. In edit mode the quantity caps are relaxed (you can adjust freely) because the server re-validates against the PO at approval time. Attachments are not re-required on an edit.

## Approval: how stock actually moves

A freshly logged arrival is always **pending** — nothing is added to stock yet. A second user with *Approve Stock Arrival* (`approveAddStockRequest`) approves it from the *Pending Approvals* tab. On approval:

- each line's final description is assembled (the product code's default description plus your per-line note);
- the quantity is added to on-hand stock at its rack;
- for a PO-linked arrival, the PO's status is recomputed to *partially arrived* or *arrived*.

Approval carries a race-safe guard for PO arrivals: if approving this arrival (added to everything already approved against the same PO) would push the received quantity **past what was ordered**, approval is blocked with an overage message. This catches the case where two arrivals for the same line were both drafted while each could still see the full remaining quantity. A parallel guard blocks approval if an additional charge on the arrival was billed on another approved receipt in the meantime.

See [In stock and arrivals](/docs/inventory/in-stock) for the approval tabs, and [Stock ledger](/docs/inventory/stock-history) to see the resulting movement.

## Reverse entry (return to supplier)

When received goods have to go back to the supplier — wrong item, damage, over-supply — you record a *reverse entry* rather than a fresh arrival. It is the mirror of an arrival: you enter a positive quantity to send back, and the system stores it as a negative movement so all stock figures net out. A reverse entry is raised from the **purchase order** (its top-right menu → *Reverse Entry*), can only return up to the net quantity received on a line, and — like an arrival — starts pending and needs a separate approval before stock actually leaves. The full behaviour (badges, PO-status roll-back, ledger, gating permissions) is documented under [In stock and arrivals](/docs/inventory/in-stock).

## Common questions

### Direct entry or from a purchase order — which should I use?

If you sent the supplier a PO, log the arrival from *Pending Arrivals* so the PO's remaining quantity and status stay correct. If there was no PO, use the *Add Entry* direct form. A direct arrival never links to a PO and never carries additional charges.

### Can I split one item across two locations?

Yes. Add the same item on two rows (on the direct form) or add the product twice and confirm *Re-add Anyway* (in the PO modal), then give each row a different godown/room/rack. On a PO arrival the two rows together must still stay within the line's remaining quantity.

### Why can't I see some warehouses, rooms, or racks?

The location pickers only show what your inventory permission scope allows. If a whole level is empty, ask an admin to widen your godown/room/rack scope. Admins (and a scope of `all`) see every location. The server enforces the same scope, so it isn't just a display filter.

### It says an attachment is required, but the file box is marked optional?

Your firm has *stock arrival attachment required* turned on (the default). The server won't accept an arrival with no file until an owner turns that setting off under [Firm customisation](/docs/settings/firm-customisation). Attach the supplier's invoice or delivery note and try again.

### The supplier delivered less than the PO promised — what do I record?

Record the actual quantity that arrived. The shortfall stays open against the PO and keeps appearing in *Pending Arrivals* until it is fulfilled or the PO is closed. See [Purchase order follow-up](/docs/procurement/purchase-order-follow-up).

### I picked the wrong tax rate — can I fix it?

On the direct form, choose the correct slab from *Tax %* before submitting; on a PO arrival the tax is frozen from the PO line and isn't editable in the modal (fix it on the PO). If the arrival is already saved but still pending or rejected, edit it from its row; after approval, undo it with a reverse entry or ask an admin.

### What happens after I submit?

The arrival is created as *pending* and waits for someone with *Approve Stock Arrival* to approve it. Only then does the quantity appear in your stock snapshot and the ledger. If your firm doesn't separate the two roles, the same person can log and approve.

### Can I email the supplier a receipt for what arrived?

Yes — after approval, send an arrival receipt confirming what was received. See [Send an arrival receipt](/docs/inventory/send-arrival-receipt).
