Postings & Ledger Lines

The double-entry posting model in Omnium — how sales, VAT, tender, returns, and gift cards become balanced ledger lines, plus the posting lifecycle and reposting behaviour.

A posting is a voucher: a header plus a set of ledger lines whose debits equal credits. Omnium produces one posting per source event and books each line to a general-ledger account drawn from your Chart of Accounts.

Posting sources

SourceWhen it is builtScope
PosZReportInline, when a register's Z-report is closedOne register's settlement: its sales, tender, and cash movements
WebFulfillmentA daily batch, per store and accounting dayThe web / click & collect orders shipped from that store on that day

A POS posting references the Z-report it was built from (ZReportId, ZReportNumber) and the register(s) it covers. A web-fulfillment posting covers a single store for a single posting date and references the contributing orders in OrderIds.

The accounting day a posting falls on is determined from the store-local time zone, so a sale just before midnight books to the correct period regardless of the server's clock. See time zone configuration.

The double-entry model

Each ledger line records an amount as either a debit or a credit against one GL account. Omnium follows standard retail accounting conventions:

EventAccount categoryDebitCredit
Sale of goodsSales
Output VAT on a saleOutputVat
Shipping charged to the customerShipping
Tender received (card, Vipps, cash, …)PaymentMethod
Gift card used as tenderGiftCardLiability
Gift card soldGiftCardLiability
Return / credit of goodsSales
Output VAT reversed on a returnOutputVat
Refund paid back to the customerRefundPaymentMethod
Rounding differenceRounding✓ or ✓

Sales and output VAT are credited when goods are sold and debited when goods are returned; tender is debited when money comes in and refunds are credited when money goes out. The two sides meet so that the voucher balances.

Account categories

Every ledger line is classified with a category. Categories are how the Chart of Accounts decides which account number to book against.

CategoryRepresents
SalesRevenue from goods sold
OutputVatVAT collected on sales (output/sales VAT)
PaymentMethodTender received for a sale
RefundPaymentMethodTender paid back on a refund
ShippingShipping/freight charged to the customer
DiscountDiscounts given
RoundingCurrency rounding differences
ReceivableAmounts owed by the customer (e.g. web sales awaiting settlement)
GiftCardLiabilityOutstanding gift-card balance (a liability)
PaymentProviderFeeFees charged by a payment provider
InternalTransferOut / InternalTransferInMovement of stock or cash between locations
CashFloatOpening / closing till float (a balance-sheet asset)
CashInTransitCash deposited to the bank but not yet cleared
OverShortCash discrepancy — counted minus expected (suspense)
TipTip-pool liability (in markets that support tips)
OtherAnything not covered above

How sales and VAT are split

Sales and output VAT lines are split by VAT rate. If a Z-report or fulfillment day contains goods at 25% and goods at 15%, the posting carries a separate Sales line and a separate OutputVat line for each rate. When tax groups are enabled, the split also carries the tax-group code and its external VAT code (MVA-kode), so the same 0% rate can be distinguished between, for example, "zero-rated" and "outside VAT scope".

This means a posting's VAT lines map one-to-one onto the rows your accountant expects on a VAT return.

Gift cards

Gift cards are handled as a liability, not as revenue or ordinary tender:

  • Selling a gift card credits GiftCardLiability (you now owe the bearer that value).
  • Redeeming a gift card as tender debits GiftCardLiability (the liability is drawn down), instead of booking to a PaymentMethod account.
  • Refunding to a gift card credits GiftCardLiability again.

This keeps gift-card float off the revenue and cash accounts and isolates it on a single liability account.

Auto-balancing

A posting must balance. If the lines leave a residual imbalance larger than the configured balance tolerance, Omnium adds a single balancing line and flags the posting with AutoBalanced = true:

  • POS postings balance to the Over/Short account (OverShort) — a genuine till discrepancy belongs there.
  • Web fulfillment postings, where sales exceed tender (the customer still owes money), balance to a Receivable account.

Small imbalances within the tolerance are left as-is. The Imbalance field on the posting reports the signed residual (debit minus credit); it should be 0 on a balanced posting.

Posting lifecycle

A posting moves through a status lifecycle:

StatusMeaning
DraftBeing assembled; not yet final. Draft postings are internal and are never returned by the public API.
PostedFinal and balanced; the normal state of a completed posting.
ExportedSent to the ERP / accounting system. Carries an ExternalReference (the ERP voucher ID) and ExportedAt.
ReconciledConfirmed reconciled against the ERP.
RejectedRejected by an operator; carries a RejectionReason.
SupersededReplaced by a newer posting for the same source event. SupersedesPostingId on the replacement points back to the original.

When a source event is reposted (for example, a Z-report is recomputed), the previous posting is marked Superseded and a new posting is created. Superseded postings are retained for audit and can be included in searches and exports on request.

Reposting and the posting hash

Every posting carries a posting hash — a deterministic SHA-256 over its identity fields and its ordered ledger lines. Lifecycle fields (status, export timestamp, external reference) are deliberately excluded from the hash.

Because the hash depends only on the underlying facts, recomputing the same source event yields the same hash. This lets Omnium detect whether a repost would actually change anything, and keeps historical postings byte-stable: a posting that is regenerated with no underlying change produces an identical voucher. This is what makes safe, repeatable exports possible.

On this page