Technical docs

Posting Policies

Configuration that controls how events become journal entries.

Policy Structure

A Posting Policy contains all the rules for how a tenant's events get converted to journal entries. The rules_json column stores the configuration.

Key Points

  • Each tenant has one default policy (marked is_default = true)
  • Multiple policies can exist for different scenarios
  • The PostingRules struct is parsed from rules_json

Category Mappings

Maps categories to their GL accounts. Uses string keys for flexibility: UUIDs for specific categories, or "sales"/"expense" for fallbacks.

{
  "category_mappings": {
    "sales": {
      "revenue_account_id": "uuid-of-4000-sales-revenue",
      "receivable_account_id": "uuid-of-1200-accounts-receivable"
    },
    "expense": {
      "expense_account_id": "uuid-of-5000-general-expenses",
      "payable_account_id": "uuid-of-2000-accounts-payable"
    },
    "specific-category-uuid": {
      "revenue_account_id": "uuid-of-4100-consulting-revenue"
    }
  }
}
KeyTypePurpose
"sales"FallbackDefault GL accounts for all sale categories
"expense"FallbackDefault GL accounts for all expense categories
"uuid-..."SpecificOverride for a specific category UUID

CategoryMapping Fields

  • RevenueAccountID: Where revenue posts (for sales)
  • ReceivableAccountID: AR account for invoiced sales
  • ExpenseAccountID: Where expense posts (for expenses)
  • PayableAccountID: AP account for billed expenses
  • RecognitionMode: immediate or deferred

Posting Defaults

System-wide GL accounts used for special scenarios that do not fit category mappings.

{
  "posting_defaults": {
    "suspense_account_id": "uuid-of-9000-suspense",
    "accounts_receivable_account_id": "uuid-of-1200-ar",
    "accounts_payable_account_id": "uuid-of-2000-ap",
    "owner_capital_account_id": "uuid-of-3000-capital",
    "owner_drawings_account_id": "uuid-of-3100-drawings"
  }
}
AccountUsed For
Suspense AccountTemporary holding for unclassified amounts
Accounts ReceivableCustomer balances owed
Accounts PayableVendor balances owed
Owner CapitalOwner contributions
Owner DrawingsOwner withdrawals

Posting Controls

Rules that govern the review workflow and period locking. These control who can approve flagged events and when edits are allowed.

{
  "posting_controls": {
    "who_can_override": "accountant_admin",
    "override_requires": "reason",
    "lock_after_days": 30,
    "lock_closed_periods": true
  }
}
ControlOptionsEffect
who_can_overrideadmin_only,accountant_admin,no_oneWho can mark flagged events as ready
override_requiresreason,reason_and_attachmentWhat is needed to override
lock_after_daysNumberEvents older than X days cannot be edited
lock_closed_periodsBooleanPrevent changes in closed accounting periods

Important Distinction

WhoCanOverride andOverrideRequires control the review workflow, not GL resolution. Category GL overrides are stored on the category itself (DefaultRevenueAccountID).

Transaction Categories

Categories hold the Layer 1 GL overrides and additional settings that affect review.

FieldTypeEffect on Events
AppliesTosale, expense, cash_only, transferDetermines which transactions can use this category
RequireAttachmentBooleanFlags event for review if no attachment uploaded
RequireInvoiceRefBooleanFlags event for review if no invoice/reference number
RecognitionModeimmediate, deferredWhen revenue/expense is recognized
DefaultRevenueAccountIDUUIDLayer 1 GL override for revenue (sale categories)
DefaultExpenseAccountIDUUIDLayer 1 GL override for expenses (expense categories)

Auto-Assignment on Create

When a new category is created without explicit GL accounts, defaults are pulled from the policy.