Skip to content

Document Numbering

You have just watched a cashier at branch GS-KV-01 ring up a sale, and the cash bill says Doc No (Tenant) 1000583. The next cash bill, at GS-PEN-01 four hundred kilometres away, says 1000584. Your auditor wants to know why the two branches share one sequence, whether numbers can be skipped or reused, and whether the branch can have a sequence of its own. This page answers those three questions from the code that assigns the numbers, tells you which numbers you can show on a listing and a printout, and is honest about the one thing you may well want and cannot have from a screen: a prefix or a starting number of your choosing. Reading it takes about ten minutes; there is nothing to set up, because numbering runs on its own from the first document.

Meet GadgetSphere

GadgetSphere Sdn Bhd (GS) has 22 retail branches, GadgetSphere Online (GSO) has a fulfilment centre, and GadgetSphere Distribution (GSD) invoices corporate accounts. All three companies live in one BigLedger tenant. On a Saturday the group writes about 1,800 cash bills, 40 sales invoices, 60 receipt vouchers and a handful of stock transfers, from 22 tills and six back-office desks at once. Every one of those documents needs a number that is unique, never reused, and handed out fast enough that two tills pressing Save in the same second do not wait for each other.

One table numbers everything

BigLedger keeps a single universal counter, and every running number in the tenant — cash bills, invoices, vouchers, stock documents, customer codes, job orders — is drawn from it. The platform’s own description of it:

“This table is used to calculate all sort of running numbers needed by various documents, journals, at different level (global counter, company counter, branch counter etc). This table will be shared by various module, it is the universal counter per instance of the application.” — the platform’s description of the counter

A counter row is identified by what it counts and for whom:

Part of the keyWhat it holdsExample for a GadgetSphere cash bill
Document typeThe document type being countedSales Cash Bill
QualifierA second qualifier, used by non-document countersempty for documents; the customer-code counter for customer codes
Tenant“usually, this one refers to the global GUID” — in practice the tenantthe tenant
Company“usually, this one refer to the company GUID”the GS company
Branch“usually, this one refer to the branch GUID”the GS-KV-01 branch
Last number“the running number in digits” — the last number handed out (see the pool, below)1000999

There are eleven key slots, so a counter can be as narrow as the engine needs; documents use up to four. The same document type at the same level is always the same row, and a row is created the first time it is needed — nobody sets counters up.

The three numbers on every document

A generic document carries several running numbers side by side, and they are assigned at different moments:

NumberCounter keyShown asAssigned
Tenant numbertenant + document typeDoc No (Tenant)the moment the document is created, even as a draft
Company numbertenant + company + document typeDoc No (Company)when the document becomes FINAL
Branch numbertenant + branch + document typeDoc No (Branch)when the document becomes FINAL
Location numbertenant + company + location + document typenot shown on the standard listingswhen the document becomes FINAL
Device numbertenant + POS device + document typeDocument No (Device), on the POS cash bill listing onlywhen the document becomes FINAL, only for documents that carry a device

Why there are five server columns and five client ones, and which of them an auditor or the tax authority will actually see, is The Generic Document. This page is about where the numbers come from.

So the cashier’s 1000583 is the tenant number: one sequence per document type across all three companies and all 22 branches, and it exists from the first Save. The branch number the auditor wants also exists — GS-KV-01’s own cash-bill sequence — but it is only stamped at FINAL, and whether a listing shows it depends on the applet — Step 1 below says which.

Three things follow from the table that catch people out:

  • The number on a draft can be lower than the number on a bill finalised earlier. Tenant numbers are handed out at creation; a draft made at 09:00 and finalised at 17:00 keeps its 09:00 number.
  • A voided or discarded document keeps its number. Nothing gives a number back once it is written on a document, so a void does not open a hole in the sequence: the voided document is still there, with its number, for an auditor to find.
  • The numbers are plain integers. No prefix, no year, no zero-padding, no branch code — the listing shows the branch code in its own column beside the number, and a printable format can compose the two. The e-Invoice number is a separate thing assigned by LHDN’s system, not by this counter.
Custom documents (INTERNAL_CUSTOM) are the only type numbered per sub-type: their counter key also includes the Client Document Type, so each custom document kind gets its own sequence. Every other document type has one sequence per level regardless of what is on the document.

The document with no number at all — TEMP

Occasionally a document turns up in a listing with no number, showing a status of TEMP, and it looks like a fault. It is not one, and it is worth knowing what it is because the cure is usually to do nothing.

Some screens need a document to exist before you have finished making one. A document built from a source — lines imported from a file, an e-invoice being converted, a scanned bill — needs somewhere to put those lines, the uploaded file, the serial numbers it has locked and the e-invoice details, and all of those hang off a document. So the applet registers an empty row up front, marked TEMP with no posting status, purely to have something to attach to. It flips to a real document the first time it is genuinely saved or converted. (Whether the marketplace order feeds use the same path we could not confirm; if you meet a TEMP row you did not expect, the state means the same thing either way.)

A TEMP document is deliberately not numbered. It gets its tenant running number on the TEMP → live transition, and not before. That is the same reasoning as the pool: a running number is a promise that it will appear on a document somebody keeps, and half of the empty rows a busy import screen creates are abandoned before anyone types into them. The repair that back-fills missing numbers (see Common mistakes) skips TEMP documents for the same reason.

So the answer to “this document shows as TEMP and has no doc number” is: open it and save it. The number is assigned at that moment.

And if it is genuinely abandoned, leave it. A TEMP document older than three hours is permanently deleted — not soft-deleted, removed — by a background sweeper, which the standard tenant configuration runs every fifteen minutes. Nothing you keep is at risk: the sweeper only ever looks at rows that are still TEMP, and a document stops being TEMP the moment it is saved.

The sweeper is not scheduled everywhere. What makes it run is a schedule in your own tenant — not a platform-wide setting. The standard tenant configuration creates it; a tenant that never had it has nothing sweeping, and abandoned TEMP rows accumulate without limit. They are inert — no number, no posting, nothing in the ledger — but they are visible in any listing that does not filter them out, and that is where the question usually comes from. If you see old TEMP rows, ask support whether the sweeper is scheduled on your tenant before you assume it is broken.

Customer, supplier and employee records work the same way: a TEMP entity is not given a code either, which is why an abandoned New Customer screen can leave a row with a blank name and a blank code.

Why two tills never wait for each other — the pool

Every counter that is drawn on has a pool of pre-issued numbers. It works like this:

  1. When a document needs a number, the engine takes the lowest available number out of that counter’s pool and uses it. Two tills asking at the same instant each get their own number without queuing.
  2. If the pool for that counter is empty, the engine moves the counter on by 500 in a transaction of its own and writes those 500 numbers into the pool, then takes the lowest.
  3. After every draw it checks, in the background, whether fewer than 100 numbers remain and tops up by another 500 if so.

What the pool guarantees, and what it does not. A counter never hands the same pool number out twice: the draw deletes the row it takes, and two tills asking together skip past each other’s row. What the pool does not promise is a sequence without gaps. On the ordinary path — the tenant number, given right after the document is created — the number is taken from the pool on one database connection and written onto the document on another, so the two steps are not one transaction. If writing the number fails after it was taken, that number is spent, and the next document takes the one after it. The same split holds when a converter stamps the numbers on a document it creates, and on one of the two finalise routes in the code. A few paths do take and write the number in one transaction — a TEMP document’s first real save, and the other finalise route — but we have not traced which screens use which finalise route, so do not count on it. So a number missing from a sequence is a question to ask, not proof that somebody deleted a document — and a number repeated is not impossible either, because nothing in the database refuses a duplicate (the reset job in Step 4 is one way to get one).

The same mechanism is why the counter’s last-issued number is always ahead of the highest number actually on a document: it is the top of the pool, not the last number used.

The first number is 1,000,000. A counter that has never existed is created at the platform default of 999,999 and the first number drawn is one more. The design note says the default “should be … 1000”; the shipped default is 999,999, which is why every tenant’s documents start in the millions.

What you can do — and how

Step 1: Show the company and branch numbers on the listing

The document applet › Settings › Application Settings — and the role’s permissions

The outcome: the branch manager at GS-KV-01 can see their own sequence on the listing they work from, and you know which listings let you hide a number column from a role and which do not.

Whether a listing shows the number columns, and whether a setting can hide them, is decided applet by applet. The setting names are the same everywhere; what they do is not. Three cases, as read in the applets’ code:

  • The pair is applied. On the Receipt Voucher (v2), Sales Debit Note, Sales Credit Note, Sales Quotation, Sales Refund Note, Consignment Billing, Purchase Requisition, Purchase GRN (both applets), Purchase Invoice (no stock-in), Purchase Debit Note, Purchase Credit Note, Purchase Refund Note, Consignment Purchase Order, Consignment GRN, Consignment Return, Packing Order and Reimbursement Payment Voucher listings each column is governed by a pair — HIDE_SERVER_DOC_1 / SHOW_DOC_NO_TENANT, HIDE_SERVER_DOC_2 / SHOW_DOC_NO_COMPANY, HIDE_SERVER_DOC_3 / SHOW_DOC_NO_BRANCH. With the hide setting off the column is shown to everyone; switch it on and only roles holding the matching show permission see it — and only if that permission code is offered in the applet’s Permission Set screen, which for many applets it is not (see the applet’s own reference page under Feature visibility).
  • The pair is listed and changes nothing. The Sales Invoice, Sales Return and Purchase Return listings name the same pairs in their code but never hand them to their grid. Their Doc No (Tenant), Doc No (Company) and Doc No (Branch) columns are ordinary columns, and switching HIDE_SERVER_DOC_2 on does not hide anything there (on Sales Return and Purchase Return it still hides the field on Main Details). The Blanket Purchase Order listing has only its tenant number, as BPO No, and no setting hides it.
  • The cash bill has its own rule. The POS General cash bill listing shows Document No (Tenant), Document No (Branch) and Document No (Device), and no company column at all. HIDE_SERVER_DOC_3 and HIDE_SERVER_DOC_4 hide the branch and device columns from everybody; no permission brings them back.

For any other applet, check its reference page, and if the page does not say, test it: switch the hide setting on, sign in as a role without the show permission, and look. Do this before you rely on a hidden column to keep a number from somebody.

The five Client Doc columns are a different thing altogether — free text, holding the number some other system gave the document. They are explained in The Generic Document. The listing’s quick search looks in Doc No (Tenant), all five Client Doc columns, Reference and the e-Invoice number by default.

The commonest failure: the branch column is on, and it is blank on half the rows. Those are drafts and documents that were never finalised — the company and branch numbers are only stamped at FINAL.

Step 2: Put the right number on the printout

Organisation › Branch › Default Printable Format, or the printable format itself

Printable formats are the place a prefix lives, if you want one: a format prints the branch number under a heading of your choosing, and it can print the branch code next to it, so GS-KV-01’s bill can read KV01 / 1000017 while the tenant number stays the audit trail. How a branch picks its layout is on Printable Formats and Per-Branch Defaults.

Step 3: Start a sequence at a number of your choosing — before the first document

There is no screen for this. Not in the Organisation applet, not in Tenant Admin, not anywhere. What the platform supports is a starting value: when a counter is created for the first time, the engine looks for a starting value with the same key and begins from it instead of 999,999.

Two facts decide whether this can work for you:

  • It only applies to a counter that does not exist yet. If a single cash bill has ever been numbered at that level, the counter exists and any starting value is ignored. An existing counter can be moved — and, because up to 500 numbers are already sitting in the pool, those are handed out first.
  • There is no user-facing way to set it. It is a BigLedger support task, done at go-live, not something to try on a live tenant.

For GadgetSphere, wanting cash bills to begin at 5,000,001 on the day the tills go live, support sets a tenant-level starting value for the cash-bill type before the first bill is raised. The first cash bill then takes 5,000,001 and the pool fills with 5,000,001–5,000,500. A company- or branch-level start is a separate value for that company or branch.

Nothing else about a sequence is configurable. Skipping a range of numbers, or handing numbers back to a queue, is not something the platform does — the pool already does the reuse job.

Step 4: Reset a sequence (a job, not a screen)

No screen of its own — a background job processor, queued through the platform’s job machinery (see the Scheduler applet, which pairs a processor with a cron expression and a JSON payload)

A job processor named App Sequence Counter Sequence Reset Processor (APP_SEQUENCE_COUNTER_SEQUENCE_RESET_PROCESSOR in the Scheduler applet’s processor picker) takes two properties, a document type and a reset value, and sets the counter to the reset value on every ACTIVE counter of that document type — tenant, every company, every branch, every location, every device, in one statement. It does not touch the pool, so the numbers already pooled (up to 500 per counter) keep being issued until each pool drains, and only then does the reset show. Use it for what it is: a way to restart a type’s numbering across the whole tenant, for example at a system migration, with the pool caveat in mind. It is not a per-branch reset.

Caution: the reset does not look at the numbers already on your documents. It sets the counter to the value it is given, and the next top-up hands out the 500 numbers above that value without checking whether any of them is already on a document. Reset cash bills to 1,000,000 in a tenant whose cash bills reach 1,250,000 and, once the pool drains, new cash bills take numbers that older ones already carry — and nothing in the database refuses the duplicate. The same happens with numbers that are not yet on any document: every counter sits at the top of its own pool, so its figure is ahead of the highest number on any document. Reset to a value above your documents but below that figure, and a number still waiting in the old pool can go out twice: once from the old pool, and once more when the first top-up after the reset writes the 500 numbers above the new value into the same pool. So the value you ask for has to be above two things: the highest number of that type on any document, and every counter’s current figure for that type — at every level the reset moves, which is tenant, each company, each branch, each location and each device, all set to the one value. You can see the first on your listings; the counter figures have no screen, so ask support to read them for you. Anything lower repeats numbers, unless that is what you intend and your auditor has agreed.

Customer, supplier and employee codes come from the same table

When you save a customer without typing a code, BigLedger builds one from a per-type prefix and a running number: the prefix is a tenant configuration value that no applet screen currently edits (the Supplier applet has no working Supplier Code Prefix control — ask support to set it), and the number comes from a tenant-level counter per entity type (customer, supplier, merchant, employee). With prefix C and the default start, your first customer is C1000000. The engine checks the code is unused and moves on if it is not — so a tenant that imported customers with numeric codes can find its generated codes jump past them. A customer saved as a draft (TEMP) is not numbered until it is made active, and a code that is already filled in is never overwritten. Have the prefixes set before the first record; the Core module page puts this at step 8 of the setup order for that reason, and the Supplier applet page describes the same rule from the supplier side.

Job orders, consultations, appointments, pick-pack queues, price books and fixed-asset registers also number themselves from this table through a shared helper that keeps a number the user typed if it is unique and generates one otherwise.

What success looks like

Open the Sales Cash Bill listing for any branch, sort by Doc No (Tenant) descending, and look at the top three rows. You should see: consecutive tenant numbers in the millions with no prefix; a Doc No (Branch) on every FINAL row that is smaller than the tenant number and consecutive within that branch; and a blank branch number on any draft. Then open the Journal or the e-Invoice screen for one of them: its e-Invoice number, if it has one, is a different string altogether. If the tenant column is blank on a FINAL document, see the first common mistake.

Common mistakes

  1. “The tenant number is blank on a finalised document.” Number assignment runs right after the create and, if it fails (a database hiccup, a pool that could not be refilled), the error is logged and the document is saved anyway, still marked as awaiting a number. Nothing retries. BigLedger support repairs it with a running-number back-fill that works on the documents you name to it, not a sweep: it gives a tenant number to each named document that lacks one — drafts included, TEMP and discarded documents excluded — and the company and branch numbers to each named FINAL document that lacks them. So the job on your side is the list: find the blank rows on the listing and send support those documents. There is also a scheduled job in the Scheduler’s picker named for this, Populate Gen Doc Running Number (POPULATE_GEN_DOC_RUNNING_NUMBER_PROCESSOR); it does nothing — its body is switched off in the code — so a successful run of it fixes no blank number.
  2. “Two branches share one sequence.” They share the tenant sequence by design; the per-branch sequence is the Doc No (Branch) column — see Step 1 for whether your listing shows it. Asking for the tenant number to restart per branch is asking for a different product.
  3. “A starting value was set and nothing changed.” A document of that type had already been numbered at that level, so the counter existed and the starting value was never read. Have the counter moved instead, and expect the pooled numbers to be issued first.
  4. “I reset the counter and the next bill still has the old number.” The reset job moves the counter, not the pool. Up to 500 already-pooled numbers per counter go out before the reset shows.
  5. “Numbers on the listing are not in date order.” Correct and expected: a draft takes its tenant number when it is created, not when it is finalised. The sequence is neither chronological nor guaranteed gap-free: a number can be spent without reaching a document (see the pool, above).

Related documentation

  • Core Module — where document numbering sits in the setup order; entity code prefixes at step 8
  • Printable Formats and Per-Branch Defaults — composing the number you print from the columns above
  • Organisation Applet — branches and the branch-level settings the numbers key on
  • Scheduler — how a background job processor such as the counter reset is queued with a JSON payload
  • Sales Invoice (Internal) — the listing’s number columns, which its hide/show pairs do not affect, and its search by a range of company numbers