User guide › Stock lifecycle
Stock, receiving and purchasing are surfaces of the Point of Sale app, not separate apps you install. One catalog, one set of warehouses, one stock ledger — shared by the register, the online store and Manufacturing. Accounting is a separate app; if you haven't installed it, everything below still happens to your stock, it just doesn't reach a ledger.
The three records that matter
Almost everything in this page is one of three things, and it helps to keep them straight from the beginning:
| Record | What it is |
|---|---|
| Stock | A running balance — one row per product per warehouse, holding the quantity on hand. This is what the register checks before it lets you sell. |
| Stock movement | The audit trail. Every single change writes one, signed positive or negative, tagged with a reason: receipt, sale, return, transfer, adjustment, void, consume, produce. |
| Documents | Purchase orders, goods receipts and supplier returns. Header-plus-lines paperwork that sits on top of the movements and links them to a supplier. |
The balance is a cache of the movements, and BackOffice keeps them in step by updating both inside one locked transaction. If a stock change fails halfway, the whole thing rolls back — you never get a movement without a balance change, or the other way round.
Two settings decide the rest of this page
Before you trace anything, know where these two live, because they change what
every step below does. Both are at
Settings → Accounting (/__accounting), on the
Settings tab.
| Setting | Default | What it changes |
|---|---|---|
| Inventory method | None / periodic | On the default, stock operations post nothing to the ledger — receiving, adjusting and transferring are pure stock events, and purchases reach the books through the supplier bill. Switch to Perpetual and inventory becomes a balance-sheet asset that moves with every operation. |
| Costing method | Weighted average | How a unit leaving stock is valued. Average blends every receipt into one running cost per product. FIFO keeps a layer per receipt and relieves the oldest first — or the soonest-expiring first, for lot-tracked products. |
Perpetual only balances if the purchase side capitalises stock as it arrives. Turning it on halfway through a trading year, on top of purchases that were already expensed, will make the inventory account disagree with reality. Decide it at setup, with your bookkeeper, and leave it alone. See Accounting.
The journey
-
Raise a purchase order —
/pos-purchase-ordersPick a supplier, a destination warehouse and the lines you want. Saving creates a Purchase Order document numbered
PO-YYYYMMDD-NNNN, with one line per product carrying ordered quantity and unit cost, at status draft.Stock: unchanged. Ledger: nothing. A purchase order is an intention, not an event. Nothing has arrived and nothing is owed.
Send to supplier emails the order to the supplier's address with you on copy and advances a draft PO to sent. Mark sent does the status flip without the email, for orders you phoned in. Needs the
purchasingcapability. -
Receive the delivery —
/pos-receiveThe moment the goods land, this is the screen. Choose the warehouse, the supplier, and optionally the purchase order it fulfils; enter a line per product with quantity and unit cost. Freight, duty and other landed costs go in the header.
In one transaction, receiving:
- Raises stock on hand at that warehouse, per line, under a row lock.
- Writes a receipt stock movement per line.
- Creates a Goods Receipt document,
GR-YYYYMMDD-NNNN, header plus lines — the record a supplier return is later raised against. - Recalculates the product's cost (see below).
- If you linked a purchase order, bumps the received quantity on the matching PO lines and recomputes the PO's status to partially received or received.
- Registers lot numbers and expiry dates, or serial numbers, for products set to track them.
Ledger: nothing on periodic. Under perpetual, with the "Post goods receipt to ledger" auto-action enabled, it posts Dr Inventory (1340) / Cr GRNI (3240) at the receipt's total cost. No VAT is recognised here — that arrives with the supplier's tax invoice.
Needs the
receivecapability. -
Stock is on hand —
/pos-stock-overviewThe overview is a read-only pivot: products down, warehouses across, quantity in the cells, with anything at or below its reorder point highlighted. It also carries a value column — quantity × unit cost — and a grand total, which is the number you reconcile against the inventory account.
Under FIFO the same page grows a Batch cost layers panel: every open layer with its received date, lot, expiry, quantity left and unit cost.
Any user with access to the POS app can read this. The raw records are also browsable at Stock and Stock movements in the sidebar.
-
Something happens to it
From here the unit takes one of five exits. Each is covered in its own section below: it sells, it moves to another location, it gets adjusted, it gets counted, or it goes back to the supplier.
Exit 1 — it sells
A sale at the register (/pos) or through the
online store runs the same checkout. Inside one
transaction it locks each product's stock row, decrements it, writes a
sale movement, and creates the Sale plus Sale Lines with a
server-computed total and a monotonic receipt number.
Checkout also snapshots the cost it relieved onto the sale — per line and as a header total. That snapshot is what a later refund or void reverses, so goods are always valued at what they cost when they sold, not at today's catalog cost.
| Situation | Stock | Cost relieved |
|---|---|---|
| Product with no stock row (untracked — services, prep, made-to-order) | Sells freely, nothing to decrement | Zero. There's no cost basis to relieve. |
| Tracked, enough on hand | Decrements normally | The full quantity, at weighted-average cost — or oldest-layer cost under FIFO. |
| Tracked, short on hand | Refused, unless the register has Allow overselling switched on — then it goes negative | Only the units that were actually on hand. The oversold portion relieves nothing. |
That last rule is deliberate and it's what keeps the books honest: cost is only ever relieved for units that were genuinely capitalised, so the inventory asset can't be driven below zero by an oversell.
Ledger: a completed sale posts Dr Cash / Cr Sales revenue / Cr VAT payable — and, under perpetual, an additional Dr COGS (7100) / Cr Inventory (1340) leg for the cost it relieved. Full detail in Order to cash.
Exit 2 — it moves to another location
/pos-transfer moves quantity between warehouses. Pick source and
destination, add lines, submit. Each line produces two movements: an
OUT with negative quantity on the source and an IN with positive quantity on the
destination, so both ends carry an audit trail.
A pre-flight check refuses the whole transfer if any line is short — there are no partial transfers. Fix the line and resubmit.
And they shouldn't. Nothing has been bought, sold or lost — the same value is simply sitting in a different building. Under FIFO the cost layers move with the goods, so the destination inherits what the source actually paid and total inventory value is conserved to the penny.
Needs the transfer capability.
Exit 3 — you adjust it
/pos-adjust sets the absolute quantity on hand for a
product at a warehouse. You type what's actually there; the server works out the
difference and writes that difference as an adjustment movement, so
the audit trail stays a continuous chain rather than a series of overwrites. Lines
where the new quantity already matches are skipped.
Three reasons are available, and they behave differently in the books:
| Reason | Use it for | Ledger under perpetual |
|---|---|---|
| Adjustment | Damage, breakage, a correction you spotted | Net decrease → Dr Inventory write-off (7110) / Cr Inventory (1340). Net increase reverses it. |
| Count | The result of physically counting a shelf | Same as adjustment. Also stamps a last-counted date on the stock row. |
| Opening | Go-live: the stock you already owned on day one | Net increase → Dr Inventory (1340) / Cr Opening balance equity (5500). You can supply a unit cost, which also sets the product's cost. |
The value posted is the quantity difference at the product's current cost — or, under FIFO, at the actual cost of the layers relieved. On periodic (the default) none of this posts; the stock still moves, quietly.
/pos-import is the same machinery behind a CSV paste
(sku, qty, notes) with reason opening, for loading a
starting position at go-live. It resolves SKUs before submitting and shows you the
invalid rows so you can fix them rather than importing junk. One file, one warehouse.
All three screens need the count capability.
Exit 4 — you count it properly
/pos-stocktake is the guided version: pick a warehouse, work through the
products, enter counted quantities, and review the variance before you commit.
Submitting posts the whole thing through the same adjustment path with reason
count — so a stocktake is a batch of delta movements, valued and
posted exactly like a manual adjustment, but with the counting workflow around it.
This is the reconciliation point of the whole lifecycle. If the count and the system disagree, the count wins and the difference lands as a write-off or a recovery.
Exit 5 — it goes back to the supplier
Supplier returns are raised against a goods receipt, not out of thin
air. Open /pos-goods-receipts, select the receipt, and enter per-line
return quantities with a reason.
Each line is validated twice before anything happens — against what's still returnable on that receipt (received minus already returned) and against what's actually on hand. Any bad line aborts the entire return. Then, in one transaction:
- A return movement (negative) is written and stock is decremented.
- The receipt line's returned quantity goes up.
- The receipt's status recomputes: received → partially returned → returned.
- A Supplier Return document is stored,
SR-YYYYMMDD-NNNN.
Ledger under perpetual: the return reverses the receipt's capitalisation. You choose how it settles — against GRNI (the usual case, when the supplier hasn't billed you yet) giving Dr GRNI (3240) / Cr Inventory (1340), or against A/P when the bill has already landed and the return becomes a supplier credit. Periodic posts nothing.
/pos-supplier-returns is the read-only history. Both screens need the
purchasing capability; goods receipts need receive.
Every step, side by side
The ledger column assumes perpetual inventory with the relevant posting enabled, and uses the Georgia chart's account codes. On the default periodic setting the whole column reads "nothing".
| Step | Screen | Record | Stock | Ledger |
|---|---|---|---|---|
| Order | /pos-purchase-orders |
Purchase Order + lines | — | — |
| Receive | /pos-receive |
Goods Receipt + lines, receipt movements | Up | Dr 1340 / Cr 3240 |
| Supplier bill | Your bill entity | Bill | — | Dr 3240 + Dr VAT input / Cr A/P |
| Sell | /pos or the store |
Sale + lines, sale movement | Down | Dr Cash / Cr 6100 / Cr 3330, plus Dr 7100 / Cr 1340 |
| Transfer | /pos-transfer |
Two transfer movements per line | Moves | — |
| Adjust / count | /pos-adjust, /pos-stocktake |
Delta adjustment movement | Set to counted | Dr 7110 / Cr 1340 (or reverse) |
| Opening balance | /pos-import, /pos-adjust |
Delta adjustment movement | Up | Dr 1340 / Cr 5500 |
| Return to supplier | /pos-goods-receipts |
Supplier Return + lines, return movement | Down | Dr 3240 (or A/P) / Cr 1340 |
Account codes come from the country pack your workspace uses and are editable per workspace — the inventory, GRNI and cash accounts are all settings, not hard-coded. The codes above are the Georgia pack's defaults.
How cost is worked out
Cost matters because it decides what a sale relieves and what your stock is worth. There is one rule that surprises people and it's worth stating on its own:
Selling, transferring and returning to a supplier never move the average. That's correct — a moving average only changes when new stock arrives at a new price. Opening balances set it, and a manufacturing completion updates it for the finished good. Nothing else does.
Weighted average (the default) blends each receipt in:
- New cost = (prior quantity × prior cost + received value) ÷ (prior quantity + received quantity), computed across all warehouses.
- If the product had no prior cost, it adopts the receipt cost outright rather than blending down from zero.
- Lines received without a unit cost leave the average alone entirely.
- Freight, duty and other landed costs are spread across the lines by value and folded into each unit's cost before any of this runs — so inventory is valued at what it truly cost to get on the shelf.
FIFO keeps a cost layer per receipt instead. A sale walks the layers oldest-received first and relieves each at its own actual cost. For products flagged as lot-tracked it orders by soonest expiry instead — the right rule for pharmacy and perishables, where a batch received later but expiring sooner should go out first, at that batch's cost.
Switching to FIFO seeds an opening layer from your current on-hand at the current average cost, so nothing is left uncosted. It's a workspace-wide choice, not per product.
When stock is wrong
"I received a delivery and stock didn't change"
Check whether the receipt was deduplicated. If you fill in the reference field, receiving is idempotent on it — a second submission with the same reference is treated as a retry of the first and does nothing. That's what stops a double-click or a flaky connection creating phantom stock. Use a fresh reference for a genuinely separate delivery.
"On-hand went negative"
Only one thing does that: a register with Allow overselling switched on. Everything else — transfers, supplier returns, manufacturing issues — refuses outright when there isn't enough. Turn overselling off on the register unless you genuinely run backorders, and never run it alongside perpetual inventory: the oversold units sell with no cost basis, so your margin reads high until you receive them.
"The cost on a product looks wrong"
Work backwards through the receipts. The usual causes: a delivery entered with no unit cost (which leaves the average untouched, so an expensive batch never registered), a landed cost you forgot to enter, or a first receipt at an unrepresentative price that the average has been carrying ever since. A count or an adjustment can't fix a cost — it only moves quantity. To correct a cost, receive at the right price, or set it on the product.
"A transfer never showed up in accounting"
It isn't meant to. Moving stock between your own warehouses doesn't change what the business owns. Look at the two movements on the stock-movements list instead — one negative on the source, one positive on the destination.
"Stock is right but the ledger doesn't move at all"
Two independent gates, and both must be open. First, inventory method must be perpetual — on the default periodic setting stock operations post nothing by design, and purchases reach your P&L through the supplier bill. Second, the relevant posting has to be switched on under Settings → Reconciliation → Auto-actions: goods receipts, supplier returns and POS sales each have their own toggle and all start off.
"The inventory account doesn't match the stock overview total"
Compare the overview's value total against the inventory account balance and look for these, in order of likelihood:
- Perpetual was switched on partway through. Receipts before the switch never capitalised, so the account starts from an arbitrary point. The account and the shelf can only agree from a clean start.
- A posting toggle is on for one operation and off for another — receipts capitalising but sales not relieving will run the account up forever.
- Oversold units. They sold with no cost basis, so the account holds value the shelf doesn't.
- Price variance. When a supplier bill's net differs from the cost you received at, the difference is left sitting in GRNI or inventory rather than posted to a variance account. Small by design; check it if it's growing.
- A locked period. Ledger posting is deliberately best-effort — if the period was locked, or accounting wasn't configured yet, the stock change still committed and the journal didn't. Stock is never rolled back because the books had a problem.
"GRNI has a balance that won't clear"
GRNI is the clearing account between "goods arrived" and "supplier invoiced us". A receipt credits it; the matching supplier bill debits it. A persistent balance means deliveries you haven't been billed for yet — which is often correct and worth reviewing — or bills entered against something other than the bill entity that clears it.
"A colleague can't open Receive or Transfer"
Each screen has its own capability: receive, count,
transfer, purchasing. Granting someone access to the POS app
lets them use the register and read the overview; the operational screens are granted
individually. Admins always pass. See
Permissions & access.
"A product sells but never appears in stock"
It has no stock row, which makes it untracked — deliberate, for services and made-to-order items. Untracked products sell freely and relieve no cost. To start tracking one, receive some or set an opening quantity; the decrement path switches on by itself from then on.
Where to go next
Stock & warehouse
Every stock screen in detail — overview, adjust, transfer, stocktake, lots and serials.
🚚Purchasing & suppliers
Suppliers, purchase orders, goods receipts and supplier returns, screen by screen.
🏭Make to stock
What happens when the stock you sell is something you built rather than bought.
📒Accounting
The chart of accounts, journals, periods and the settings that gate everything above.