Core Concepts
Eight ideas explain almost everything that surprises people in this module. Learn them once here and the twenty-odd applet pages stop being a list of screens.
1. The chain is held together by knock-off, and knock-off is an open queue
Every purchasing document is a generic document with a header and lines, a DRAFT state where
it has done nothing, and a FINAL state where it is locked and whatever it was going to do has
happened. What ties one document to the next is knock-off: on the new document’s KO For tab
you pick a finalised source, and its open lines — supplier, items, quantities, prices — are copied
forward and linked.
Behind the tab is the open queue. When a document goes FINAL, a processor reads the company’s Knock Off Configuration and, for every downstream document type enabled there, writes one queue row per line with the line’s open quantity. A downstream document that knocks a line off reduces that open quantity; when it reaches zero the source stops appearing in anyone’s picker.
flowchart LR
PR["Purchase Requisition<br/>FINAL"] -->|"queue row per line"| Q1[("open queue")]
Q1 -->|"KO For"| PO["Purchase Order<br/>FINAL"]
PO -->|"queue row per line"| Q2[("open queue")]
Q2 -->|"KO For"| GRN["Purchase GRN<br/>FINAL"]
Q2 -->|"KO For"| PI
GRN -->|"queue row per line"| Q3[("open queue")]
Q3 -->|"KO For"| PI["Purchase Invoice<br/>FINAL"]
PO -. "CLOSE empties the queue" .-> Q2
Four consequences:
- Partial deliveries need no special handling. Receive 180 of 200 and the remaining 20 sit in the queue for the next receipt.
- The queue only exists where the configuration says so. A company with no Purchase Requisition → Purchase Order row finalises requisitions that no order can find. This is the first thing to check when a picker is empty.
- CLOSE and VOID are different. CLOSE on an order sets every open quantity to zero and deletes the queue rows — the supplier is not sending the rest. VOID cancels the document. Neither is undone.
- VOID reopens. Voiding an invoice marks its knock-off links deleted, so the receipt’s lines become open again. The reverse is refused: a receipt that an invoice has already knocked off cannot be voided. The server’s message names the invoice by type and number, but the GRN screen shows only that the document has been knocked off with another document, so read the receipt’s Doc Link tab to find the invoice. Void the invoice first, then the receipt — the Doc Link tab shows you the order before you start.
2. Two numbers on each document type decide everything
A quantity signum (does stock move, and which way) and an amount signum (does money move, and which way). Zero means nothing happens. They are fixed in the backend per server document type; they are not settings, not per tenant, and the applet’s own copy is overwritten by the server on every save.
| Document | Quantity | Amount | So finalising it… |
|---|---|---|---|
| Purchase Requisition, Purchase Quotation, Blanket Purchase Order, Purchase Order, Consignment Purchase Order | 0 | 0 | locks it and opens its lines for knock-off. Nothing else |
| Purchase GRN (plain) | 0 | 0 | records the receipt. Nothing reaches stock or the ledger |
| Purchase GIN | 0 | 0 | records an issue toward a supplier. Nothing else |
| Purchase Invoice | +1 | −1 | books the stock in, updates the item’s last purchase cost, posts Dr Purchase / Dr Input Tax / Cr Creditor |
| Purchase GRN Stock In | +1 | −1 | books the stock in, posts Dr Inventory Not Invoiced / Dr Input Tax / Cr Creditor Not Invoiced |
| Purchase Invoice No Stock In | 0 | −1 | posts Dr Purchase / Dr Input Tax / Cr Creditor, and — when knocked off from a GRN Stock In — Dr Creditor Not Invoiced / Cr Inventory Not Invoiced to clear the accrual |
| Purchase Return | −1 | +1 | takes the goods out of stock, posts Dr Creditor / Cr Purchase Return |
| Purchase Refund Note | −1 | +1 | behaves like a return, with its own settlement lines |
| Purchase Debit Note | 0 | +1 | Dr Creditor / Cr Purchase — you owe less |
| Purchase Credit Note | 0 | −1 | Dr Purchase / Cr Creditor — you owe more |
| Consignment GRN | +1 | −1 | stock in; Dr Consignment Stock / Cr Consignment Liability |
| Consignment GIN | −1 | +1 | stock out; falls back to the ordinary purchase and creditor accounts |
| Consignment Return | 0 | +1 | Dr Consignment Liability / Cr Consignment Stock. Moves no stock |
| Consignment Billing | 0 | −1 | a purchase invoice plus Dr Consignment Liability / Cr Consignment Stock |
A line only reaches stock if its item resolves to an inventory item. A service item or an unlinked item on a +1 document is silently skipped by the stock processor — no error, no ledger line.
3. The receiving pair, and where the accrual lives
This is the fact that trips nearly everyone coming from another system: in the standard flow the invoice moves the stock, not the receipt.
| If your flow is | The stock arrives on | And the other document |
|---|---|---|
| Purchase Order → Purchase GRN → Purchase Invoice | the purchase invoice | the GRN records the receipt and moves nothing |
| Purchase Order → Purchase GRN Stock In → Purchase Invoice No Stock In | the GRN Stock In | the invoice books only the money |
The GR/IR (Goods Received / Invoice Received) accrual belongs to the second pair only. GRN Stock In posts Dr Inventory Not Invoiced / Cr Creditor Not Invoiced; the No Stock In invoice that knocks it off posts the ordinary purchase journal and then reverses that pair. Two details worth knowing:
- The reversal leg fires whenever the invoice carries any knock-off link — the source type is not checked. An invoice built from a plain GRN or a PO in the No Stock In applet will still post the reversal, against an accrual that was never made.
- The GRN Stock In accrues the net amount as inventory and tax separately as input tax; the invoice reverses the total including tax. If tax is captured on both documents the two accrual accounts do not clear by exactly the tax amount. Capture tax on one of the pair.
On the standard pair there is no accrual at all. Between delivery and bill the goods are on the floor and absent from the stock ledger; you can see them as GRN quantity in Stock Availability, and that is the whole of your visibility.
4. Matching is a person, not an engine
There is no three-way matching in BigLedger. No tolerance setting, no variance report, no automatic flag, and nothing that blocks a supplier invoice because its price or quantity differs from the order. What exists is knock-off: the invoice shows the order’s or the receipt’s real lines, and the person keying it compares them with the supplier’s paper. If the supplier billed RM 132 where the order said RM 128, the line can be changed and the invoice finalises anyway.
Controls over that live in permissions — who may edit a price, who may finalise an invoice — not in a rule. The Purchase Invoice applet does carry a Knock Off Settings screen with switches named for GRN and PO knock-off; its menu entry is not available and nothing reads the values — the switches appear nowhere in the backend at all, and in the applet only on the five unlinked screens that write them. The KO For tab offers both sources whatever they are set to.
5. Approval is optional, off by default, and causes FINAL rather than gating it
BigLedger’s document-approval engine covers exactly three document types: Purchase Order, Purchase Requisition and Stock Requisition. It is off until somebody creates an Approval Setting in the applet’s own Settings. And the dependency runs the way people do not expect: the document goes FINAL on the FIRST approval, not the last. The engine runs the move to FINAL on every approving request it processes, so on a two-level rule the level-1 approval finalises the document while the level-2 request is still in someone’s inbox. Level 2 is still e-mailed and the approval record only reads Approved when they act — but the document has already moved, and a second level is therefore a recorded opinion rather than a gate. Nothing in the document lifecycle checks for an approval — an order with a request still pending can be finalised by hand, and it posts exactly the same.
What a setting contains, and what actually does something:
- Approvers are not named on the setting. They are the employees placed under Settings → Branch → Designation, each with an approval level; the submitter’s designation comes from their employee job title.
- Min Approval Amount does not route to a different approver. It decides how many levels a document must clear: every level whose minimum is at or below the document amount is required. Levels at RM 0, RM 10,000 and RM 50,000 make a RM 25,600 order need two approvals.
- Max Approval Amount and Approval Logic are stored and never read. ANY versus ALL is decided by the quorum.
- There is no delegation, no escalation, no reminder and no stand-in approver. A request sits until its approver acts.
- The Purchase Order applet alone has an Approval Monitor rule that can require every order submitted for approval to have been built from a requisition.
No approval exists for GRNs, invoices, payment vouchers, returns, credit or debit notes. Where a spending policy matters, control who holds the finalise permission — that is the only hard stop in the module. The full walkthrough is in Document Approvals.
6. The notes point the way the ledger points, not the way the name suggests
In this platform a Purchase Debit Note posts Dr Creditor / Cr Purchase: it lowers what you owe the supplier — an overcharge, a rebate, a short delivery. A Purchase Credit Note posts on the same side as an invoice: Dr Purchase / Cr Creditor, so it raises what you owe — a further charge the supplier is adding. This is the reverse of how many people name them from the supplier’s point of view, and the applet pages carry the warning in the same words.
Neither note moves stock. When goods go back, the document is a Purchase Return (stock out, supplier debited), and it leaves a positive balance on the supplier’s account that is closed by contra against their invoices or by a settlement when they refund cash.
7. Supplier credit terms and limits are records, not rules
The Supplier applet stores credit terms and credit limits, with listings, uploads and per-company variants. In the backend:
- A purchase invoice carries no due date. The applet’s Due Date field is switched off, the date it works out from the terms reaches no field, and nothing on the server computes one; the terms themselves are stored only when Purchaser is filled (Purchase invoice processing, Step 1). The only server reader of a credit term is statement-of-account reporting, and it reads the sales side.
- Nothing reads a supplier’s purchase credit limit. The purchase-side limit reaches no service, report or job; the sales-side limit, by contrast, is joined into the outstanding-document report. The one credit-availability service is advisory, never throws, and is hard-coded to sales orders and sales invoices. The one hard stop — the nightly blacklist — queries customers only and blocks four sales document types.
- Because the credit-limit status sits on the shared entity header, a supplier who is also a customer can be blacklisted by their receivables behaviour, and the effect lands on their sales documents only.
If a supplier limit matters to your business it is a policy for the buyer, enforced by nothing in the product.
8. Consignment is its own chain, with its own accounts
Stock a consignor places with you and still owns does not run through the standard chain. It has its own six documents, two GL codes of its own, and one naming trap.
flowchart LR
CPO["Consignment PO<br/>0 / 0"] -->|"KO For"| CGRN["Consignment GRN<br/>stock +1<br/>Dr Consignment Stock<br/>Cr Consignment Liability"]
CGRN -->|"goods sell on a<br/>Sales Invoice (stock −1)"| SOLD(["sold"])
SOLD --> CBILL["Consignment Billing<br/>Dr Purchase / Cr Creditor<br/>+ Dr Consignment Liability<br/>/ Cr Consignment Stock"]
CGRN -->|"unsold, goes back"| CRET["Consignment Return<br/>Dr Consignment Liability<br/>/ Cr Consignment Stock<br/>stock unchanged"]
CGRN -->|"issued without a sale"| CGIN["Consignment GIN<br/>stock −1<br/>ordinary purchase / creditor accounts"]
CBILL --> PV["Payment Voucher"]
- The GRN and the Return post to
CONSIGNMENT_STOCKandCONSIGNMENT_LIABILITY, and a GL code typed on a line is ignored for these types. The two accounts are found differently. The liability (and any input tax) comes only from the company default GL codes. Each goods line’s stock account is looked for in turn: a GL code on the document header, then the item’s ownCONSIGNMENT_STOCKcode for this company, then the company default. A missing code does not stop FINAL at either end of the cycle: the journal posting that runs after it fails —MISSING_DEFAULT_GL_CODE: CONSIGNMENT_LIABILITY, orNO_JOURNAL_CREATEDwhen no goods line found a stock account — and the document sits FINAL with no journal. - One unresolved line is quieter than all of them. When some goods lines find a stock account and one does not, that line is left out, the liability is written for the lines that remain, and the journal balances and posts — short by that line, with no error. Compare a consignment GRN’s journal total with its document total when an item is new to consignment.
- The GIN is not in the consignment list: a posted consignment GIN falls back to the ordinary purchase and creditor accounts. Use it for issues without a sale; use the Return to reverse value.
- Consignment Billing is the consignor’s bill to you. Its applet sits in the sales folder and is named as if it billed a customer; it is a purchase invoice in every respect, and it moves no stock — the GRN already brought the quantity in.
- Consignor Purchase Billing is a period worksheet in its own tables. It has no FINAL, posts no journal, and creates no creditor balance; the amount owed is still recorded by a purchase document.
A consignment GRN keyed at RM 0 — common when the price is not yet agreed — enters the moving-average cost pool at zero and pulls the item’s average down for everything in stock.