Skip to content

KB-212 – Accounting Engine Architecture

Knowledge Base ID: KB-212
Chapter: 5 - Fact & FactLine
Project: BLACK ERP
Version: 0.5
Status: Draft
Last Updated: 2026-06-26
Applies To: ADempiere 3.9.4


Purpose

This chapter explains how ADempiere represents accounting entries internally before they are persisted into the General Ledger.

The Fact and FactLine classes are the core accounting objects responsible for building journal entries during the posting process.

Understanding these classes is essential before analyzing any specific accounting implementation.


Conceptual Model

The Accounting Engine never writes directly into the FACT_ACCT table.

Instead, it constructs an in-memory accounting document composed of one or more accounting lines.

Business Document
        │
        ▼
Doc
        │
        ▼
Fact
        │
        ▼
FactLine
        │
        ▼
FACT_ACCT

Only after all validations succeed are the generated accounting entries persisted into the database.


The Fact Class

Class:

org.compiere.acct.Fact

A Fact represents a complete accounting document for a specific accounting schema.

It contains:

  • Accounting Schema
  • Posting Type
  • Currency
  • Accounting Lines
  • Posting Metadata

Conceptually, one Fact is equivalent to one accounting journal.


The FactLine Class

Class:

org.compiere.acct.FactLine

Each FactLine represents a single accounting movement.

Every line contains:

  • Account Combination
  • Debit Amount
  • Credit Amount
  • Currency
  • Organization
  • Business Partner
  • Product
  • Project
  • Campaign
  • User Dimensions

Multiple FactLine objects compose a single Fact.


Object Relationship

Doc
 │
 ▼
Fact
 │
 ├──────────────┐
 ▼              ▼
FactLine     FactLine
 │              │
 ▼              ▼
Debit        Credit

A valid accounting document always contains balanced debit and credit lines.


Posting Sequence

The Accounting Engine follows a consistent sequence.

Instantiate Fact

↓

Create Debit FactLine

↓

Create Credit FactLine

↓

Validate Balance

↓

Persist into FACT_ACCT

No database records are written until the Fact is complete.


Fact Creation

Each Doc_* implementation is responsible for constructing one or more Fact objects.

Typical pattern:

Fact fact = new Fact(...);

fact.createLine(...);

fact.createLine(...);

return facts;

The document-specific implementation determines:

  • Which accounts are used.
  • Which amounts are posted.
  • Which dimensions are assigned.

The posting infrastructure itself remains generic.


Multiple Facts

A single business document may generate multiple accounting documents.

Examples include:

  • Different Accounting Schemas.
  • Different Posting Types.
  • Parallel Accounting.

Conceptually:

Invoice

↓

Fact (Primary Ledger)

↓

Fact (Secondary Ledger)

↓

Fact (Tax Ledger)

Each Fact remains independent while sharing the same business document.


Account Resolution

FactLine objects never invent accounting accounts.

Instead, they receive valid account combinations previously resolved by the Doc class.

Doc

↓

Resolve Account

↓

Valid Combination

↓

FactLine

This separation keeps account determination independent from accounting persistence.


Persistence

After successful validation, every FactLine is stored in:

FACT_ACCT

Each row represents a single debit or credit movement.

Conceptually:

Fact

↓

FactLine

↓

FACT_ACCT Record

BLACK ERP Example

Our Mexican VAT Cash Basis implementation follows the standard architecture.

Doc_AllocationHdr

↓

MXVATCashBasisEngine

↓

Fact

↓

FactLine (119.001)

↓

FactLine (118.001)

The customization generates additional accounting lines while preserving the standard posting workflow.


Engineering Notes

When implementing accounting customizations:

  • Never write directly to FACT_ACCT.
  • Always create FactLine objects.
  • Keep all accounting logic inside the corresponding Doc_* implementation.
  • Allow the Accounting Engine to persist the results.

Following this pattern preserves compatibility with future ADempiere upgrades.


Key Takeaways

  • Fact represents an accounting document.
  • FactLine represents an accounting movement.
  • Multiple FactLine objects compose a balanced journal.
  • Only completed Fact objects are persisted.
  • FACT_ACCT is the persistence layer, not the business logic.

Next Chapter

Chapter 6 explains how ADempiere resolves accounting accounts using MAcctSchema, MAccount, and MAccountLookup before creating FactLine objects.


Revision History

Version Date Description
0.5 2026-06-26 Added Fact and FactLine architecture.