Skip to content

Chart of Accounts & Journals

Backend domains:

RBAC Paths: ACCOUNTS, JOURNALS, LEDGER.

Accounts (chart of accounts)

The chart is a tree of Account rows with:

  • account_number, name, account_type (ASSET / LIABILITY / EQUITY / REVENUE / EXPENSE), account_subtype, is_active.
  • parent_id — supports nested grouping for the balance-sheet / income-statement layout.
  • currency, is_bank_account, is_inventory_account, is_ar_account, is_ap_account, is_tax_account — flags consumed by domain services to pick the right account automatically.
  • default_for_* — per-tenant defaults pulled by domains that need a fallback (e.g. default cash account, default AR, default ITBMS payable).

Key mutations: createAccount, updateAccount, deleteAccount.

Key queries: accountSearch, getAccountById, getDefaultAccount (resolves by purpose, e.g. "give me the default ITBMS payable account").

Templates for the Panama chart can be loaded at tenant onboarding (see onboard_tenant.py and the accounts/strategies/ folder).

Manual Journals

A Journal is a manual JE. It must balance (SUM(debits) == SUM(credits)) and posts through LedgerService. Each line points at an account, has a memo, optional cost-centre / project tag, and optional FX rate.

Key mutations: createJournal, updateJournal, deleteJournal.

Key queries: getJournalById, getJournalByNumber.

Recurring journals (rent accruals, depreciation prepayments, FX revaluations) live in Recurring Journals.

Ledger

The ledger is read-only from the API side. LedgerService is the only code path that writes ledger rows; every other domain (invoices, receipts, payments, expenses, supplier invoices, credit notes, payroll, fixed-asset depreciation, opening balances, recurring journals) calls into it.

Two guards always run before a row is written:

  1. Accounting Period Guard (app/graphql/accounting_periods/) — rejects any post into a CLOSED period unless the user has explicit override permission. See Period Close.
  2. Ledger Audit (app/graphql/ledger_audit/) — writes a hash-chained audit row for every POST and REVERSE. See Ledger Audit Trail.

Reversal is the only way to "undo" — entries are never edited or deleted in place.