Skip to content

KB-212 – Accounting Engine Architecture

Knowledge Base ID: KB-212
Chapter: 8 - Accounting Metadata Layer
Project: BLACK ERP
Version: 0.8
Status: Draft
Last Updated: 2026-06-26
Applies To: ADempiere 3.9.4


Purpose

This chapter explains the Accounting Metadata Layer used by ADempiere to store and retrieve accounting configuration.

The previous chapter introduced MAcctSchema, which defines accounting rules and ledger behavior.

This chapter explains where the actual General Ledger account mappings are stored and how the Accounting Engine retrieves them during the posting process.

Unlike the previous conceptual chapters, this document is based on the actual source code structure of ADempiere 3.9.4.


Overview

The Accounting Engine never hardcodes General Ledger accounts.

Instead, it resolves accounting metadata stored in specialized tables.

These metadata tables define the relationship between business objects and their corresponding accounting accounts.

Conceptually:

Business Object
        │
        ▼
Accounting Metadata
        │
        ▼
Account Combination
        │
        ▼
FactLine

Metadata Model Pattern

The source code reveals that accounting metadata follows the standard ADempiere persistence architecture.

Database Table
        │
        ▼
I_* Interface
        │
        ▼
X_* Generated Model
        │
        ▼
M_* Business Model (Optional)

The important discovery is that the last layer is optional.

Many accounting metadata tables are represented only by generated model classes.

This explains why some accounting objects do not have a manual M* implementation.


Accounting Metadata Groups

The source code identifies several independent accounting metadata groups.

Metadata Area Purpose
Accounting Schema Defaults Default accounting configuration
Product Accounting Inventory and product-related accounts
Product Category Accounting Category-level accounting defaults
Business Partner Accounting Customer, Vendor and Employee accounts
Tax Accounting Tax posting accounts
Charge Accounting Charge posting accounts
Bank Account Accounting Bank transaction accounts
Cash Book Accounting Cash journal accounts

Each group is responsible for a different portion of the Accounting Engine.


Accounting Schema Defaults

Source files:

org/adempiere/core/domains/models/I_C_AcctSchema_Default.java
org/adempiere/core/domains/models/X_C_AcctSchema_Default.java
org/compiere/model/MAcctSchemaDefault.java

This layer stores the default accounts associated with an Accounting Schema.

Whenever a more specific accounting definition is unavailable, the Posting Engine can fall back to these defaults.

Conceptually:

Accounting Schema
        │
        ▼
C_AcctSchema_Default
        │
        ▼
Default Account Combination

This layer represents the base accounting configuration for an entire ledger.


Product Accounting

Source files:

org/adempiere/core/domains/models/I_M_Product_Acct.java
org/adempiere/core/domains/models/X_M_Product_Acct.java

org/adempiere/core/domains/models/I_M_Product_Category_Acct.java
org/adempiere/core/domains/models/X_M_Product_Category_Acct.java

org/compiere/model/MProductCategoryAcct.java

During the source code review, no manual MProductAcct class was found.

Instead, product accounting relies on generated models together with category-level accounting support.

Typical product accounts include:

  • Product Asset
  • Product Expense
  • Product Revenue
  • Cost of Goods Sold
  • Inventory Clearing
  • Purchase Price Variance
  • Invoice Price Variance

Conceptually:

Product

↓

Product Accounting

↓

Product Category Accounting

↓

Account Combination

Business Partner Accounting

Source files:

I_C_BP_Customer_Acct.java
X_C_BP_Customer_Acct.java

I_C_BP_Vendor_Acct.java
X_C_BP_Vendor_Acct.java

I_C_BP_Employee_Acct.java
X_C_BP_Employee_Acct.java

I_C_BP_Group_Acct.java
X_C_BP_Group_Acct.java

Business Partner accounting is organized by business role.

Role Metadata Table
Customer C_BP_Customer_Acct
Vendor C_BP_Vendor_Acct
Employee C_BP_Employee_Acct
Group Defaults C_BP_Group_Acct

This allows a single Business Partner to maintain independent accounting definitions depending on its role.

Conceptually:

Business Partner
        │
        ├── Customer Accounting
        ├── Vendor Accounting
        ├── Employee Accounting
        └── Group Default Accounting

Tax Accounting

Source files:

org/adempiere/core/domains/models/I_C_Tax_Acct.java
org/adempiere/core/domains/models/X_C_Tax_Acct.java

Tax accounting defines the accounts used during tax posting.

Examples include:

  • Tax Due
  • Tax Credit
  • Tax Expense
  • Tax Liability
  • Tax Receivable

Conceptually:

Tax

↓

C_Tax_Acct

↓

Tax Account Combination

This layer is especially important for tax localizations such as Mexico.


Charge Accounting

Source files:

org/adempiere/core/domains/models/I_C_Charge_Acct.java
org/adempiere/core/domains/models/X_C_Charge_Acct.java

org/compiere/model/MChargeAcct.java

Charge accounting defines the accounts associated with Charges.

Unlike Products, Charges represent accounting movements that are not inventory items.

Conceptually:

Charge

↓

C_Charge_Acct

↓

Charge Account Combination

Bank Account Accounting

Source files:

org/adempiere/core/domains/models/I_C_BankAccount_Acct.java
org/adempiere/core/domains/models/X_C_BankAccount_Acct.java

Bank Account Accounting stores the accounts used during payment processing and bank statement posting.

Typical accounts include:

  • Bank Asset
  • Bank In Transit
  • Bank Expense
  • Bank Interest
  • Payment Selection

Conceptually:

Bank Account

↓

C_BankAccount_Acct

↓

Bank Account Combination

Cash Book Accounting

Source files:

org/adempiere/core/domains/models/I_C_CashBook_Acct.java
org/adempiere/core/domains/models/X_C_CashBook_Acct.java

Cash Book Accounting stores the accounts used by Cash Journals and Cash Transactions.

Conceptually:

Cash Book

↓

C_CashBook_Acct

↓

Cash Account Combination

Metadata Is Not Posting Logic

A common misunderstanding is assuming these metadata classes perform accounting.

They do not.

The Accounting Metadata Layer only stores accounting mappings.

Posting logic belongs to:

Doc_*

Accounting construction belongs to:

Fact
FactLine

Database persistence belongs to:

FACT_ACCT

The Metadata Layer simply answers:

Which account should be used?


BLACK ERP Engineering Notes

One of the most important discoveries during the BLACK ERP API project involved Business Partner accounting.

New Business Partners required accounting metadata before they could participate in accounting transactions.

The API therefore creates:

  • C_BP_Customer_Acct
  • C_BP_Vendor_Acct
  • C_BP_Employee_Acct

using:

C_BP_Group_Acct

as the source of default accounting configuration.

Without these records, document posting fails with invalid account errors.

This behavior confirms that Accounting Metadata must exist before any posting process can succeed.


Mexican Localization Notes

The Mexican VAT Cash Basis implementation depends entirely on properly configured accounting metadata.

The following accounts must exist as valid accounting combinations:

  • 119.001 — VAT Pending Payment
  • 118.001 — VAT Paid
  • 209.001 — VAT Collected Pending
  • 208.001 — VAT Collected

The localization resolves these accounting combinations before generating additional FactLine entries.

No General Ledger account is hardcoded inside the posting logic.


Engineering Principles

The source code review confirms several important design principles.

  • Business logic never hardcodes General Ledger accounts.
  • Accounting metadata is completely configuration-driven.
  • Generated X_* models are first-class components of the Accounting Engine.
  • Manual M_* models are created only when additional business logic is required.
  • Missing metadata often causes posting failures even when Java code is correct.

Key Takeaways

  • The Accounting Metadata Layer stores accounting mappings.
  • Multiple independent metadata groups participate in account resolution.
  • Not every accounting table has a manual M_* implementation.
  • Business Partner accounting is organized by business role.
  • Product accounting combines product and category metadata.
  • Tax and Charge accounting are independent metadata layers.
  • Posting logic consumes metadata but does not own it.

Next Chapter

Chapter 9 explores how the Posting Engine consumes the Accounting Metadata Layer through Doc.getAccount() to resolve C_ValidCombination records before constructing FactLine objects.


Revision History

Version Date Description
0.8 2026-06-26 Added Accounting Metadata Layer based on source code analysis and accounting metadata discovery.