FleetbaseFleetbase

Core Concepts

The foundational concepts of Ledger — double-entry bookkeeping, accounts, journal entries, wallets, invoices, transactions, and how it all fits together.

Core Concepts

Ledger implements proper double-entry bookkeeping. Understanding the core accounting model helps you use the system correctly and interpret your financial reports.

The Accounting Equation

Everything in Ledger follows this fundamental rule:

Assets = Liabilities + Equity

Every financial event is recorded as a journal entry that debits one account and credits another — the equation always stays balanced.

Account Types

Ledger uses five standard account types. Account code values in Ledger are alphanumeric tags (e.g. CASH-DEFAULT, WALLET-POOL, REVENUE-DELIVERY), not numeric ranges.

TypeNormal BalanceSeeded examples
AssetDebitCash, Bank Account, Accounts Receivable, Stripe Clearing
LiabilityCreditAccounts Payable, Wallet Liability Pool, Driver Earnings Payable, Tax Payable
EquityCreditOwner's Equity, Retained Earnings
RevenueCreditDelivery Revenue, Service Fee Revenue, Subscription Revenue, Other Revenue
ExpenseDebitDriver Payout Expense, Payment Gateway Fees, Refunds & Chargebacks, Other Operating Expenses

Debit-normal accounts (Assets, Expenses): debits increase the balance; credits decrease it. Credit-normal accounts (Liabilities, Equity, Revenue): credits increase the balance; debits decrease it.

See Chart of Accounts for the complete seeded list.

Journal Entries

Every financial event creates one journal entry with:

  • A debit account and a credit account
  • An amount in the account's currency (stored as integer minor units)
  • A type — system-written types include general (default), manual_entry, revenue_recognition, invoice_payment, gateway_payment, and storefront_sale. The form picker for manual entries also offers standard, adjusting, closing, reversing, and opening
  • A status — currently only posted is produced by the system; there is no built-in reversal or void action
  • An is_system_entry flag — true for automated entries, false for manual ones

Journal entry numbers follow the format JE-00001 (5-digit zero-padded).

Example — customer pays an invoice:

DEBIT  Cash (Asset)               +$100
CREDIT Accounts Receivable (Asset) +$100  ← decreases the AR balance

(AR is debit-normal, so the credit reduces the customer's outstanding balance.)

Wallets

A Wallet is a digital balance tracked in Ledger. Wallets are polymorphic — subject_uuid + subject_type point at the entity that owns the balance:

Wallet TypeSubjectUse Case
DriverFleet-Ops DriverTrack earnings from completed deliveries
CustomerStorefront / Fleet-Ops CustomerPrepaid credit or store loyalty balance
CompanyYour organizationOperating account, platform revenue
UserIndividual userPersonal account

Wallet operations:

  • Credit — manual credit, no gateway charge
  • Top-Up — gateway-charged top-up via Stripe or QPay
  • Transfer — move funds between two wallets — produces two transactions (transfer_out and transfer_in) and one journal entry between the two wallet liability accounts
  • Payout — debit the wallet (e.g., driver earnings payout)
  • Freeze / Unfreeze — toggle status. The is_frozen attribute is a computed accessor derived from status === 'frozen'
  • Recalculate — recompute the balance from completed transactions

Every wallet operation automatically creates a journal entry:

Top-up:    DEBIT Cash → CREDIT Wallet Liability
Payout:    DEBIT Wallet Liability → CREDIT Cash
Transfer:  DEBIT Wallet A's liability → CREDIT Wallet B's liability   (direct, no intermediate)

Each wallet has its own ledger account auto-created with code WALLET-{wallet_uuid}. See Wallets.

Invoices

An Invoice is a formal payment request with a lifecycle:

draft → sent → viewed → partial / paid / overdue / cancelled / refunded / void
StatusMeaning
draftCreated, not yet sent
sentMarked as sent
viewedCustomer opened the public URL
partialSome payment received
paidFully paid (balance = 0)
overduePast due date, not yet paid (set by the ledger:update-overdue-invoices console command)
cancelledUser-cancelled
refundedSet when a gateway refund is processed
voidSet programmatically when a draft invoice is superseded by a new one (e.g., from Fleet-Ops auto-invoicing)

Key invoice fields:

  • Number — auto-generated, format INV- plus a 6-digit random integer (e.g., INV-004821); not sequential
  • Customer — polymorphic reference (customer_uuid + customer_type); supports Fleetbase contacts, vendors, drivers, and users
  • Line Items — description, quantity, unit price, tax_rate (decimal 0–100); subtotal, tax, total are computed
  • Totalssubtotal, tax, total_amount, amount_paid, balance (all computed)
  • Due Date — auto-set from the due_date_offset_days invoice setting (only when non-zero)
  • Order link — optional order_uuid linking back to a Fleet-Ops order
  • Transaction link — optional transaction_uuid linking to the wallet transaction that paid it

When an invoice is created from a Fleet-Ops PurchaseRate, a revenue_recognition journal entry is posted (DEBIT Accounts Receivable → CREDIT Revenue).

When payment is recorded, an invoice_payment journal entry is posted (DEBIT Cash → CREDIT Accounts Receivable).

Transactions

A Transaction is the immutable record of money moving relative to a wallet. Transactions are never edited or deleted — they are the audit trail.

Key fields:

  • directioncredit (money in) or debit (money out)
  • status — currently the system only produces completed (the model also supports pending, failed, voided, reversed, expired timestamps if you write them yourself)
  • type — types written by the system are deposit, withdrawal, transfer_in, transfer_out, earning, payout, and invoice_payment
  • amount, fee_amount, tax_amount, net_amount — full cost breakdown
  • gateway — the payment processor that handled this, if any
  • subject / payer / payee / initiator / context — polymorphic relationships capturing who/what was involved

See Transactions.

Payment Gateways

Gateways are payment processors with encrypted credentials. Ledger ships with three drivers:

DriverCapabilities
stripepurchase, refund, tokenization, setup_intent, checkout_session, webhooks, sandbox, recurring
qpaypurchase, refund, webhooks, sandbox
cashpurchase, refund

Every gateway interaction creates a GatewayTransaction audit record — used for idempotency (duplicate webhook protection via the isProcessed() check) and debugging.

Third-party drivers can be registered via the PaymentGatewayManager::extend() API.

How It All Connects

Fleet-Ops:

Fleet-Ops Order → PurchaseRate created
  → Ledger PurchaseRateObserver creates a draft Invoice
    → Customer pays via gateway (or you record payment manually)
      → invoice_payment journal entry posted
        → Invoice marked paid; AR Aging cleared

Storefront:

Storefront Checkout completes (order.type === 'storefront')
  → Ledger StorefrontOrderObserver creates a storefront_sale journal entry
    DEBIT Cash → CREDIT Revenue
  (No invoice — the order record itself is the receipt)

Wallet flows:

Customer top-up via Stripe → GatewayTransaction logged → Wallet Transaction (deposit, credit) → Journal entry (DEBIT Cash → CREDIT Wallet Liability)
Driver earning payout → Wallet Transaction (payout, debit) → Journal entry (DEBIT Wallet Liability → CREDIT Cash)
Core Concepts | Fleetbase