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. |