Finance #finance #general-ledger #gl #chart-of-accounts #journal-entries #trial-balance #accounting #fiscal-periods #invariants Raw .md

General Ledger & Chart of Accounts

Manage financial accounts, create manual journal entries, monitor fiscal locking, and generate balanced Trial Balances.

Routes: /general-ledger /general-ledger/trial-balance /general-ledger/journal-entries /general-ledger/journal-entries/new

General Ledger & Chart of Accounts

The General Ledger (GL) is the financial backbone of HeroBM. It records all automated postings from operations, supports manual adjusting journal entries, enforces fiscal period lock boundaries, and validates Trial Balance mathematical integrity.


Chart of Accounts & ERPNext Format Import

HeroBM organizes all financial postings within a structured, hierarchical Chart of Accounts (COA) across five root classifications: Asset, Liability, Equity, Revenue, and Expense.

HeroBM natively supports importing Chart of Accounts structured in the ERPNext JSON format. When provisioning a new company or updating accounting structures:

  • Built-in Presets: HeroBM includes ready-to-use regional presets such as Australia Standard (au_standard.json) and US Standard (us_standard.json), stored in apps/api/src/gl/charts/.
  • ERPNext Verified Templates & Custom Charts: You can import or adapt any country-specific template from the official ERPNext Verified Chart of Accounts repository.
  • Importing in the UI: Navigate to Administration → Settings → Financial Settings (/admin/settings/financial), scroll to the Chart of Accounts section, and click Import CoA:
    • Upload JSON File: Select or drag & drop any .json file from your local machine to upload and import directly in your browser.
    • Predefined Presets: Select from pre-packaged regional presets or custom template files placed on the API server in apps/api/src/gl/charts/.

Double-Entry Accounting Invariants & Validation

1. The Zero-Sum Invariant Rule

Every journal transaction in HeroBM is verified before persistence:

Total Debits - Total Credits = 0.00 (Tolerance: |Balance| <= 0.005)

If debits and credits do not match within half a cent, the journal is rejected by the API.

2. Posting Account & Period Validation

Before an entry is committed:

  1. Posting Node Check: Accounts must be active leaf nodes (transactions cannot post directly to abstract group header accounts).
  2. Fiscal Period Gate: Transaction date must fall within an Open fiscal period. If the period is Soft Locked, an elevated confirmation is required; if Hard Closed, the posting is blocked.
  3. Control Account Protection: System control accounts (Accounts Receivable, Accounts Payable, Inventory Asset, GRNI Clearing) are updated automatically by operational subledgers. Manual adjustments require explicit reconciliation notes.

3. Automated Postings Master Map

Operational EventDebit Leg(s)Credit Leg(s)
Customer Sales InvoiceAccounts Receivable ControlSales Revenue + Output Tax Payable
Sales Order Dispatch (COGS)Cost of Goods Sold (COGS)Inventory Asset Account (at WAC)
Sales Credit NoteSales Revenue + Output TaxAccounts Receivable Control
Goods Receipt (GRN)Inventory Asset AccountGoods Received Not Invoiced (GRNI) Accrual
Supplier Invoice MatchGRNI Accrual + Input Tax (+ PPV/FX)Accounts Payable Control (+ PPV/FX)
Customer Payment ReceivedBank Account (+ Payment Gateway Fees)Accounts Receivable Control
Supplier Bill PaymentAccounts Payable ControlBank Account (+ Early Payment Discount)
Inventory Scrap / Count LossInventory Shrinkage ExpenseInventory Asset Account

4. Auditability, Ledger Immutability & Compliance Architecture

HeroBM is architected from the database up to satisfy strict statutory accounting standards (including SOX, GAAP, IFRS, and ATO audit requirements). The ledger incorporates multiple cryptographic, systemic, and operational safeguards to ensure complete auditability, non-repudiation, and tamper detection:

flowchart TD
    subgraph Operations["Operational Subledgers (Invoices, Payments, Goods Receipts, Dispatches)"]
        A[Operational Event] -->|Atomic DB Transaction| B[Post GL Journal Entry + Lines]
        A -->|Atomic DB Transaction| C[Transactional Outbox Event]
    end

    subgraph Database["PostgreSQL Engine Guards"]
        B --> D[Compute SHA-256 Hash Chain: prev_hash + payload -> entry_hash]
        D --> E[(gl_journal_entries & gl_journal_lines)]
        E --> F[Trigger: prevent_financial_deletion]
        E --> G[Trigger: prevent_financial_modification]
        E --> H[Trigger: enforce_gl_journal_fiscal_period_lock]
    end

    subgraph Verifier["Continuous Ledger Verification Engine (BullMQ)"]
        I[Nightly 2:00 AM Cron / On-Demand Audit] --> J[1. Sequence Continuity: Zero Gaps]
        I --> K[2. Chronological Continuity: Monotonic Timestamps]
        I --> L[3. Double-Entry Zero-Sum: Total DR = Total CR]
        I --> M[4. SHA-256 Hash Recalculation: Genesis to Head]
        I --> N[5. Subledger-to-GL Parity Reconciliation]
        
        J & K & L & M & N -->|Violation Detected| O[Emit system.ledger_integrity_violation]
        O --> P[Dashboard Timeline Alert + Administrator Email]
    end

A. Cryptographic SHA-256 Hash Chaining

Every posted general ledger journal entry is cryptographically bound to the entire historical sequence of journal entries using a Merkle-style SHA-256 hash chain:

  1. Genesis Seed: The very first journal entry in the system chains from a fixed 64-zero genesis seed:
    0000000000000000000000000000000000000000000000000000000000000000
  2. Deterministic Payload Hashing: When entry N is posted, its cryptographic hash (entry_hash) is computed deterministically from:
    • prev_entry_hash: The SHA-256 hash of entry N-1.
    • journal_entry_id and entry_number.
    • entry_date and source_type.
    • Sorted list of line items (account_code, debit, credit, currency).
  3. Tamper Detection: If any record in gl_journal_entries or gl_journal_lines is modified, inserted out-of-order, or deleted at the database level, the hash chain breaks from that point forward, rendering tampering immediately evident during automated verification.

B. Database-Level Trigger Protection (Immutability by Default)

HeroBM enforces immutability directly inside PostgreSQL via native triggers that execute before any SQL statement commits:

  • herobm_core.prevent_financial_deletion: Strictly blocks DELETE operations across all financial tables (gl_journal_entries, gl_journal_lines, sales_invoices, sales_invoice_lines, purchase_invoices, purchase_invoice_lines, sales_credit_notes, purchase_debit_notes, payment_entries, payment_allocations, and inventory_ledger). Draft unposted records can be discarded, but once posted, records are permanent.
  • herobm_core.prevent_financial_modification: Prevents in-place updates to posted monetary amounts, account codes, debit/credit values, and transaction dates.
  • The “Reversal Only” Accounting Law: To correct any historical transaction, operators must post an explicit offsetting reversal journal entry or issue a formal credit/debit note. This guarantees a permanent, transparent paper trail for auditors.

C. Continuous Automated Ledger Integrity Audits (BullMQ)

A dedicated background BullMQ verification engine runs automated integrity audits daily at 2:00 AM (as well as on-demand):

  1. Sequential Monotonicity: Verifies that journal entry numbers, invoice numbers, and credit note numbers increment continuously without gaps.
  2. Chronological Continuity: Validates that transaction timestamps never regress or invert.
  3. Zero-Sum Mathematical Invariant: Recalculates total debits and credits across the entire general ledger, asserting that Total Debits - Total Credits = 0.00.
  4. Full SHA-256 Hash Chain Recalculation: Recomputes all entry hashes sequentially from the genesis seed to the latest entry, confirming cryptographic integrity.
  5. Subledger-to-GL Parity: Cross-checks every operational document (sales invoices, customer payments, supplier bills, inventory dispatches) against its corresponding GL double-entry lines.

If any anomaly or discrepancy is detected, the verification engine immediately raises a high-priority system.ledger_integrity_violation domain event, triggers an administrative email dispatch, and creates a critical alert banner on the Dashboard Timeline.

D. Strict Fiscal Period Hard Locking

Fiscal periods can be placed in Open, Soft Locked, or Hard Closed states:

  • Hard Closed Periods: Permanently locked against new postings or backdated adjustments. Database triggers (herobm_core.enforce_gl_journal_fiscal_period_lock()) block any write whose transaction date falls within a hard-closed period.
  • Audit Attribution: All period status changes record the user ID, timestamp, and justification reason.

E. Transactional Outbox Event Colocation

All state transitions and ledger postings atomically insert an audit event into the herobm_core.outbox table within the same database transaction (emitEvent). This provides an immutable event log recording the actor, timestamp, prior state, new state, and full execution payload for forensic auditing.


Balance Sheet & Movement Calculations (MTD, YTD, Last YTD)

The Balance Sheet (/general-ledger/balance-sheet) provides a point-in-time financial statement of the organization’s assets, liabilities, and equity as of a chosen cutoff date (asOfDate), alongside period-over-period movement analytics.

flowchart LR
    subgraph BalanceSheet["Balance Sheet Equation (Invariant Parity)"]
        Assets["Total Assets\n(Debit Normal)"]
        Liabilities["Total Liabilities\n(Credit Normal)"]
        Equity["Total Equity\n(Credit Normal)\n+ Current Net Income"]
        
        Assets <===>|Must Exactly Balance| Sum["Liabilities + Equity"]
        Liabilities --> Sum
        Equity --> Sum
    end

1. Structure & Root Classifications

  1. Assets (Debit Normal): Liquid cash, accounts receivable, inventory assets, equipment, and other economic resources owned.
  2. Liabilities (Credit Normal): Accounts payable, tax liabilities, short-term accruals, and long-term debt obligations.
  3. Equity (Credit Normal): Shareholder capital, retained earnings from prior fiscal years, and Current Period Earnings / Net Income.

Dynamic Current Period Earnings (Net Income)

HeroBM dynamically calculates unclosed earnings for the active fiscal period directly from the income statement accounts:

Net Income = Total Revenue - Total Expense

and presents it within the Equity section. This guarantees that the Balance Sheet balances at any point in time without requiring manual period-end closing journals.


2. Mathematical Formulas & Movement Calculations

Every row in the Balance Sheet report presents the point-in-time balance alongside three distinct movement metrics:

+---------------+---------------------+--------------------+--------------------+-------------------------+
| Account Name  |   Balance (Amount)  |    Movement MTD    |    Movement YTD    |    Movement Last YTD    |
+---------------+---------------------+--------------------+--------------------+-------------------------+
| Cutoff Range  | Cumulative to As-Of | Month-to-Date      | Fiscal Year-to-Date| Prior Fiscal YTD        |
|               | (<= asOfDate)       | (YYYY-MM-01..As-Of)| (FY Start..As-Of)  | (Prior FY Start..Prior) |
+---------------+---------------------+--------------------+--------------------+-------------------------+

A. Cumulative Balance (Amount)

The cumulative position of the account from the inception of the ledger up to the end of the asOfDate:

  • Asset Accounts:
    Ending Balance = Cumulative Debits - Cumulative Credits
  • Liability & Equity Accounts:
    Ending Balance = Cumulative Credits - Cumulative Debits
  • Current Period Net Income (Equity):
    Cumulative Net Income = Cumulative Revenue - Cumulative Expense

B. Movement MTD (Month-to-Date)

The net financial change posted within the calendar month of the asOfDate (from YYYY-MM-01 through asOfDate):

  • Asset Movement MTD: Period Debits - Period Credits
  • Liability & Equity Movement MTD: Period Credits - Period Debits
  • Current Period Net Income MTD: MTD Revenue Movement - MTD Expense Movement

C. Movement YTD (Fiscal Year-to-Date)

The net financial change posted from the start of the active fiscal year through asOfDate:

  • Date Range: Determined dynamically from the organization’s fiscalYearStartMonth (e.g. Month 7 / July 1 for Australian fiscal years, Month 1 / January 1 for calendar fiscal years).
  • Asset Movement YTD: Period Debits - Period Credits
  • Liability & Equity Movement YTD: Period Credits - Period Debits
  • Current Period Net Income YTD: YTD Revenue Movement - YTD Expense Movement

D. Movement Last YTD (Comparative Prior Fiscal Year-to-Date)

The net financial change posted during the equivalent comparative period in the prior fiscal year:

  • Date Range: From the prior fiscal year start date (fiscalYearStart - 1 year) through the comparative prior cutoff date (asOfDate - 1 year).
  • Purpose: Enables immediate comparative benchmarking of asset accumulation, debt reduction, and retained earnings growth against the prior year’s performance at the exact same point in time.
  • Asset Movement Last YTD: Period Debits - Period Credits
  • Liability & Equity Movement Last YTD: Period Credits - Period Debits
  • Current Period Net Income Last YTD: Last YTD Revenue Movement - Last YTD Expense Movement

3. Balance Sheet Invariants & Validation

HeroBM enforces and displays real-time mathematical validation across all four columns:

  1. Cumulative Balance Invariant:
    Total Assets = Total Liabilities + Total Equity (Tolerance: <= 0.005)
  2. Movement Invariants (MTD, YTD, Last YTD):
    Total Assets Movement = Total Liabilities Movement + Total Equity Movement (Tolerance: <= 0.005)

If any rounding or out-of-balance condition occurs, the UI displays a warning banner indicating the exact out-of-balance variance for immediate investigation.


Step-by-Step Workflows

1. Creating a Manual Journal Entry

  1. Go to Finance → General Ledger → Journal Entries (/general-ledger/journal-entries).
  2. Click New Journal Entry (/general-ledger/journal-entries/new).
  3. Enter the Transaction Date and a clear Description / Reference.
  4. Add line items: select leaf GL accounts and enter Debit and Credit amounts.
  5. Verify that total debits equal total credits (Zero-Sum Variance = 0.00).
  6. Click Post Journal Entry.

2. Viewing the Trial Balance

  1. Go to Finance → General Ledger → Trial Balance (/general-ledger/trial-balance).
  2. Select the financial period or custom date range.
  3. Review debit/credit balances across all active accounts.
  4. Verify the zero-sum balanced status banner at the top of the report.

3. Reviewing the Statement of Cash Flows

  1. Go to Finance → General Ledger → Cash Flow (/general-ledger/cash-flow).
  2. Select an active Fiscal Period or Custom Date Range.
  3. Verify that the Parity Verification Banner is green (reconciled with zero drift).
  4. Review direct operating, investing, and financing cash flow breakdowns.

4. Analyzing the Balance Sheet & Movements

  1. Go to Finance → General Ledger → Balance Sheet (/general-ledger/balance-sheet).
  2. Select the As Of Date using the date picker or quick presets.
  3. Inspect Total Assets, Total Liabilities, and Total Equity subtotals.
  4. Review Movement MTD, Movement YTD, and Movement Last YTD to identify working capital velocity and equity trends.
  5. Confirm the green Balanced status banner confirming Assets = Liabilities + Equity with zero drift.

Field Reference

FieldDescription
Account CodeUnique numerical GL identifier (e.g. 1000 Bank).
Account NameDescriptive label of the ledger account.
Account ClassificationRoot category (Asset, Liability, Equity, Revenue, Expense).
As Of DatePoint-in-time cutoff date for cumulative balances and movement intervals.
Balance (Amount)Cumulative ending balance posted up to the asOfDate (DR - CR for Assets, CR - DR for Liabilities/Equity).
Movement MTDNet monetary change posted from the start of the calendar month to asOfDate.
Movement YTDNet monetary change posted from the start of the current fiscal year to asOfDate.
Movement Last YTDNet monetary change posted during the comparative prior fiscal year period.
Debit / CreditDouble-entry transaction amounts (must balance to zero).
Journal Entry NumberUnique audit sequence identifier (e.g. JRN-2026-00041).
Zero-Sum VarianceDifference check ensuring debits equal credits (<= 0.005).

Field Reference & Data Dictionary

Key database fields, input parameters, and definitions associated with this workflow screen:

Field / Parameter Display Name Description & Rules
account_code Account Code Unique numerical GL code (e.g. 1000 Bank, 4000 Sales, 5000 COGS).
account_type Account Classification Standard accounting class: Asset, Liability, Equity, Revenue, or Expense.
entry_number Journal Entry Number Unique transaction identifier (e.g. JRN-2026-00041).
debit Debit (DR) Left-side transaction value increasing Assets/Expenses or decreasing Liabilities/Equity/Revenue.
credit Credit (CR) Right-side transaction value increasing Liabilities/Equity/Revenue or decreasing Assets/Expenses.