Skip to content

Core Concepts

Six ideas explain almost everything surprising about this module. Learn them once here and the twenty-two applet pages stop being a list of screens.

1. The balance is a running total, not a stored number you can edit

There is no screen anywhere in BigLedger where you type a stock balance. The balance is the tip of a signed stock ledger — one row per item per movement — that the server appends to when a document is finalised. The Stock Balance applet is the enquiry over that total and nothing more.

    flowchart TD
  F["Document set to FINAL"] --> P1["Generic-document primary processor<br/>fans out to its subscribed jobs"]
  P1 --> P2["Inventory transaction line processor<br/>one signed ledger line per item line<br/>with a non-zero quantity signum"]
  P2 --> P3["Ledger line → current stock balance processor<br/>upserts the location row and the company row,<br/>updates the cost bases, then serial / batch / bin"]
  P3 --> B["Stock balance<br/>item × company × location"]
  F -.->|"VOID"| V["Void processor<br/>writes a <b>negated copy</b> of every line<br/>— nothing is deleted"]
  V --> B
  

Four consequences:

  • If a number is wrong, the fix is a document, never the screen. Usually a Stock Adjustment.
  • FINAL is not instant. The work happens in background processors. On a busy day the balance can lag the document by moments. A page that says “real time” is overstating it.
  • VOID does not delete history. It writes a negated copy of every ledger line, marked as a void. The movement and its reversal both stay.
  • A backdated document is inserted mid-chain and the balance is re-projected from there, which is why backdating is expensive and why the FIFO chain is rebuilt after one.

Where a movement lands

The location on a ledger line is the first of these that is set: the line’s delivery location, then the line’s store, then the header’s store, then the branch’s default location. Most “the stock went to the wrong place” cases are a line with no location falling through to a branch default nobody had looked at.

2. The quantity signum decides everything

Two numbers on a document type decide its effect: the quantity signum (does stock move, and which way) and the amount signum (does money move). A zero means nothing happens. They are fixed in the backend for each document type — not settings, not per tenant, and the applet’s own copy is overwritten by the server on every save.

Moves stock in (+1)Moves stock out (−1)Moves nothing (0)
Purchase InvoiceSales InvoiceSales Order, Purchase Order, Quotation
Purchase GRN Stock InCash Billplain Purchase GRN, plain Sales GIN
Sales ReturnSales GIN Stock OutInvoice No Stock In / No Stock Out
Sales Refund NotePurchase ReturnCredit Note, Debit Note
Transfer InPurchase Refund NoteStock Requisition
Consignment GRNTransfer OutDelivery Order, Goods Delivery Note
Consignment GINPacking Order, Jobsheet, Job Order

Stock Adjustment takes its direction from the line (adjust-in or adjust-out). Stock Conversion takes it from the tab the line was entered on.

The receiving pair is the one that catches people. A plain Purchase GRN records that goods arrived; it does not put them in stock. Either the purchase invoice books the stock (and the GRN is paperwork), or you use GRN Stock In, which books the stock and leaves the invoice to book only the money. Use one pair or the other. A GRN Stock In and a stock-booking purchase invoice for the same goods counts them twice.

The same trap exists on the sales side: a plain Sales GIN and a plain Sales GRN are inert, and the document types that really issue and receive stock — GIN Stock Out, GRN Stock In — are different documents.

3. Balance and availability are different numbers, and availability can exceed balance

Balance is what the ledger says you physically hold.

Availability is what you can still promise. It is not balance minus reservations. It is the balance plus a signed adjustment for open documents:

    flowchart LR
  SB["Stock balance<br/>ledger quantity at this company and location"]
  SO["Open sales orders<br/>not yet invoiced · signum −1"]
  GRN["Goods received notes<br/>not yet invoiced · signum +1"]
  ADJ["Adj Qty<br/>signed sum"]
  AV["Available Qty<br/>balance + Adj Qty"]
  SO --> ADJ
  GRN --> ADJ
  SB --> AV
  ADJ --> AV
  

So “50 on the shelf, 0 available” means open sales orders, and “10 on the shelf, 35 available” means goods received and not yet invoiced. Both are correct. The Details screen in Stock Availability lists the documents behind the adjustment by type, so the difference is always traceable to specific documents rather than to a mystery.

Reservation is a third, separate thing. A reservation adds to the reserved column on the balance row, which the availability screens subtract. It moves no stock and posts nothing. It is opt-in — an action somebody takes in the Stock Reservation applet, or one that the Sales Order, Job Order and Packing Order applets take on a document’s behalf. There is no “hard” and “soft” allocation, and a plain FINAL sales order does not lock anything.

4. Counting measures the gap; adjusting closes it

These are two applets and two documents, and conflating them is the commonest misunderstanding in the module.

Stock TakeStock Adjustment
What it isA counting session for one location, with devices attached and records captured by scan or by handA document with lines, saved as a draft and finalised
What it producesA report: counted against system, a tolerance band for movements during the count, missing and unexpected serials, and the cost of the differenceA ledger line per item and a journal
Effect on the balanceNone. It never changes a balanceChanges it
Effect on the ledgerNoneOne signed line per item

There is no “post the variance” button. Somebody reads the count report and raises an adjustment.

The stock take report values the variance at the location’s latest moving-average price. Items with no moving-average history value at zero, and a FIFO tenant never sees FIFO cost on that report. Treat the count report’s cost column as indicative and value the variance from the stock reports if the number matters.

5. One document in this module posts a journal

Stock Adjustment. That is the list.

Adjustment directionDebitCredit
Adjust-Out (quantity down)Stock adjustment expense (STOCK_ADJUSTMENT, or the line’s own GL code)Stock (STOCK_BALANCE)
Adjust-In (quantity up)Stock (STOCK_BALANCE)Stock adjustment (STOCK_ADJUSTMENT, or the line’s own GL code)

A consignment GRN posts through the consignment handler — CONSIGNMENT_LIABILITY against CONSIGNMENT_STOCK — because the stock is not yours until it sells. The consignment GIN that sends it back does not: it has no consignment mapping of its own and posts through the ordinary purchase mapping, so it reaches your ordinary supplier (CREDITOR) and purchase (PURCHASE) accounts. Check those accounts, not the consignment ones, when a returned consignment does not seem to have left the books.

Everything else in the module posts nothing. Stock transfers carry quantity only: value stays on the balance sheet wherever the goods physically are, and the company’s unit cost is untouched by construction — the transfer types are excluded from the moving-average calculation, so the transfer is a cost-neutral relieve. The per-location cost is a different number and it does not follow the goods: the location calculator seeds from the previous line at the receiving location, so a location that has never held the item seeds at zero and values the arrival at zero. Read the company figure for valuation; see Stock Transfer for the three cases. Stock conversions post no journal either. On 2026-10-01 they post no stock at all: nothing is connected to the conversion’s posting run, so a FINAL conversion leaves the balance where it was (§6).

The cost of goods sold on a sale is posted by the sales journal handler, from the sales document. No document in this module posts cost of sales.

6. Four cost bases are kept at once, and moving average is the one that bites

Every balance row carries moving-average, weighted-average, FIFO and LIFO amounts and prices, plus last purchase cost and landed cost. They are columns maintained side by side, not a costing mode you select. Each screen decides which one to show.

Moving average is what most screens use, and three things distort it or leave it short:

  • A stock conversion moves no cost between items. Once its posting chain is connected (it is not, on 2026-10-01), the kit comes in at its own last price at that location — zero for a new item — and the components leave at their running average. Each item’s average holds; the kit never carries its components’ cost.
  • A trade-in unit is not inventory stock at all. Trade-ins live in their own tables with their own cost, appear in Stock Availability because that screen unions the two, and never appear in the historical balance report.
  • A backdated document re-projects the chain, which moves every average computed after it.

Reset Moving Average, in the Stock Adjustment applet, is the correction. It changes inventory value on the balance sheet and cost of sales on the income statement, so it belongs to finance and to nobody else.

7. Nothing in this module is approved

BigLedger’s document-approval engine covers three document types — Purchase Order, Purchase Requisition and Stock Requisition — is off until a tenant configures it, and causes FINAL rather than gating it. No transfer, adjustment, conversion or count consults it.

And the one inventory document the engine nominally covers is a dead end today: the Stock Requisition applet shows an Approval Settings screen but has no approval tab on the document, no request screen and no history screen, so a setting created there cannot be used from that applet.

Your control over who may write stock off, move it between branches or reset a cost is the permission set, and nothing else. Say so during implementation rather than after the first write-off nobody expected.

Where this leads