Skip to main content

FGL Journals and Posting

The general ledger records financial activity through journal entries that are grouped into batches and posted to update stored balances. This page explains the batch/header/line model, the posting process, suspense handling, journal reversal, balance roll-forward, and the reporting views.

Batch / header / line model​

Journal entries follow a three-level hierarchy:

Journal Batch
└── Journal Header (one or more per batch)
└── Journal Line (one or more per header)

Batches​

A journal batch is the unit of posting. All headers within a batch are posted together when the fgl_post_batch function is called. A batch belongs to a single ledger and carries a status:

StatusMeaning
UNPOSTEDInitial state; the batch has not been posted
POSTEDAll headers in the batch posted successfully
ERROROne or more headers failed validation during posting

A batch also records an optional posted_date (set on successful posting) and error_text (set when errors occur).

Headers​

A journal header represents a single journal entry. Each header belongs to a batch and records:

FieldPurpose
ledger_idThe ledger this entry belongs to
period_idThe accounting period for this entry
journal_nameA descriptive name for the entry
journal_dateThe effective date of the entry
sourceWhere the entry originated: MANUAL, RECEIVABLES, or PAYABLES
categoryThe nature of the entry: ADJUSTMENT, SALES_INVOICES, RECEIPTS, PURCHASE_INVOICES, PAYMENTS, or REVERSAL
currency_codeThe entry (entered) currency
statusUNPOSTED, POSTED, or ERROR
reversal_flagWhether this header is a reversing entry
reversed_header_idFor reversals, points to the original header
running_total_dr / running_total_crTrigger-maintained totals of all line debits and credits

The running_total_dr and running_total_cr columns are maintained automatically by a database trigger whenever lines are inserted, updated, or deleted. They are never written directly.

Lines​

A journal line is a single debit or credit entry on a header. Each line references a code combination (the account being posted to) and records both entered and accounted amounts.

A line is always exactly one of a debit or a credit — the database enforces that exactly one of entered_dr / entered_cr is non-null and greater than zero, and the same rule applies to accounted_dr / accounted_cr.

Entered vs accounted amounts​

Each journal line carries two pairs of amount columns:

ColumnsCurrencyPurpose
entered_dr / entered_crEntry currency (from the header)The amount in the currency of the original transaction
accounted_dr / accounted_crFunctional currency (from the ledger)The amount converted to the ledger's reporting currency

When the entry currency matches the ledger's functional currency, the entered and accounted amounts are the same and the conversion_rate is 1. When they differ, the conversion_rate on the line records the exchange rate used, and the accounted amounts are the converted values.

The posting process uses accounted amounts for balance checks and balance updates, ensuring that all stored balances are in the ledger's functional currency.

Posting​

Posting is performed by the fgl_post_batch function, which processes every UNPOSTED header in a batch. The function runs the following checks and steps for each header:

1. Period check​

The GL period status for the header's period must be OPEN. If the period is not open, the header is marked ERROR.

2. Code combination check​

Every code combination referenced by the header's lines must be both enabled and allow_posting. If any combination fails this check, the header is marked ERROR.

3. Balance check​

The sum of accounted_dr across all lines must equal the sum of accounted_cr. If the header is unbalanced:

  • Suspense enabled — if the ledger has suspense_enabled = TRUE and a suspense_ccid configured, the posting function automatically inserts a balancing suspense line using the ledger's suspense code combination. The suspense line records the difference needed to bring the header into balance.
  • Suspense not enabled — the header is marked ERROR with a message indicating the imbalance.

4. Balance upsert​

For each line, the function upserts the fgl_balances table:

  • If no balance row exists for the combination of ledger, period, code combination, and currency, one is created
  • The line's accounted debit or credit is added to period_net_dr or period_net_cr
  • If the entry currency differs from the functional currency, a separate balance row is maintained for the entered currency

5. Roll-forward​

After updating the current period's balances, the posting function rolls the closing position (begin balance + period net) into the next period of the same fiscal year as the opening balance. This ensures that the trial balance for any period reflects cumulative activity from the start of the year.

6. Status update​

If all checks pass, the header is marked POSTED with the current timestamp as posted_date. After processing all headers, the batch is marked POSTED if every header succeeded, or ERROR if any header failed.

Error statuses​

When a header fails posting, its status is set to ERROR and the error_text column records the reason. Common error codes:

CodeMeaning
FGL-00100Batch is already posted
FGL-00101Batch not found
FGL-00102Period is not open for GL
FGL-00103Code combination is disabled or does not allow posting
FGL-00104Header is unbalanced and suspense is not enabled
FGL-00105Suspense code combination is not configured
FGL-00106Suspense code combination is disabled

The batch-level error_text aggregates header-level errors.

Suspense​

Suspense handling allows unbalanced journals to be posted by automatically inserting a balancing line. This is useful when sub-ledger feeds produce rounding differences or when manual entry errors need to be corrected after the fact.

Suspense is controlled by two ledger-level settings:

  • suspense_enabled — must be TRUE to activate suspense handling
  • suspense_ccid — the code combination that receives the balancing entry

When both are configured and a header's accounted debits do not equal its accounted credits, the posting function inserts a single suspense line that brings the header into balance. The suspense line uses the ledger's functional currency with a conversion rate of 1.

tip

Review suspense entries regularly. A suspense balance that grows over time indicates a systematic data quality issue in journal entry or sub-ledger feeds.

Reversal​

The fgl_reverse_header function creates a reversing journal for a previously posted header. Reversal is used to correct errors or to create accrual reversals at the start of a new period.

The function:

  1. Validates that the source header is POSTED and is not itself a reversal
  2. Creates a new batch named Reversal: {journal_name}
  3. Creates a new header with reversal_flag = TRUE, reversed_header_id pointing to the original, and category = 'REVERSAL'
  4. Copies all lines from the original header with debits and credits swapped
  5. Posts the new reversal batch by calling fgl_post_batch
  6. Returns the new header's ID

The target period for the reversal can differ from the original header's period, allowing reversals to be recorded in the current period for entries that were posted in a prior period.

Reversal error codes​

CodeMeaning
FGL-00110Source header not found
FGL-00111Source header is not in POSTED status
FGL-00112Source header is already a reversal
FGL-00113Target period not found
FGL-00114Target period is not open for GL

Balances and roll-forward​

The fgl_balances table stores period-level financial totals for each combination of ledger, period, code combination, and currency. Balance rows are created and updated exclusively by the posting process — they are read-only to application users.

Each balance row contains:

ColumnPurpose
begin_balance_dr / begin_balance_crOpening position for the period, rolled forward from the prior period's closing position
period_net_dr / period_net_crNet activity posted during this period

The closing position for a period is computed as:

end_balance_dr = begin_balance_dr + period_net_dr
end_balance_cr = begin_balance_cr + period_net_cr

When a journal is posted, the posting function updates the current period's period_net columns and then propagates the updated closing position into the next period's begin_balance columns within the same fiscal year. This roll-forward ensures that opening balances are always current without requiring a separate batch process.

Trial balance​

The trial balance view (fgl_trial_balance) provides a period-by-period summary of balances across all code combinations. It joins balances with code combinations and periods to present:

  • Concatenated segment string and account type
  • Period name, year, and number
  • Begin balance (DR and CR)
  • Period net (DR and CR)
  • Computed end balance (DR and CR)

The trial balance is exposed through the General Ledger menu as a read-only entry. It does not support create, edit, or delete actions.

Account activity​

The account activity view (fgl_account_activity) provides line-level detail for posted journals. It shows every posted journal line with:

  • Code combination and account type
  • Period information
  • Journal header details (name, date, source, category)
  • Line number and description
  • Entered amounts (DR and CR) with currency and conversion rate
  • Accounted amounts (DR and CR)

This view is useful for drilling into the detail behind a trial balance figure to see which journal entries contributed to a particular account's balance.

General Ledger menu​

The General Ledger menu in the application provides access to journals and the trial balance:

EntrySchemaActions
Journalsts_fgl_journal_batchCreate, Edit, PostBatch
→ Headers (child of Journals)ts_fgl_journal_headerCreate, Edit, ReverseHeader
→ → Lines (child of Headers)ts_fgl_journal_lineCreate, Edit
Trial Balancets_fgl_trial_balanceRead-only (no create, edit, or delete)

The PostBatch custom action triggers fgl_post_batch on the selected batch. The ReverseHeader custom action triggers fgl_reverse_header on the selected header.