Financial truth,
behind one fluent API.
A headless, mathematically rigorous Financial Management System (FMS) and General Ledger for Laravel and Obelawium ERP. Enforces zero-sum integer parity down to minor units, immutable Storno reversals, Maker-Checker governance, multi-currency ledger snapshots, and Anti-Corruption Layer (ACL) ingestion.
composer require obelaw/ium-accounting // Create a balanced journal voucher with minor unit integer precision
$entry = ium()->accounting()->journalEntries()->createDraft(
CreateJournalEntryDto::fromMajor([
'entry_date' => '2026-03-31',
'currency_code' => 'USD',
'memo' => 'Enterprise Q1 SaaS Subscription Invoicing & Sales Tax',
'lines' => [
['account_code' => '1120', 'side' => 'debit', 'amount' => 11500.00, 'memo' => 'Accounts Receivable'],
['account_code' => '4100', 'side' => 'credit', 'amount' => 10000.00, 'memo' => 'Recurring Cloud Revenue'],
['account_code' => '2150', 'side' => 'credit', 'amount' => 1500.00, 'memo' => 'Output VAT / Sales Tax Payable'],
],
])
);
// Strict Maker-Checker governance: Distinct approver posts to the General Ledger
ium()->accounting()->journalEntries()->submit($entry->id, $accountantId);
ium()->accounting()->journalEntries()->approve($entry->id, $controllerId);
ium()->accounting()->journalEntries()->post($entry->id, $controllerId); Accounting by numbers
The 8 Non-Negotiable Domain Invariants.
Financial ledgers must never compromise on mathematical truth. Every write operation through the fluent gateway is guarded by hard architectural invariants.
1. Zero-Sum Parity
Every voucher must balance perfectly: Σ Debits = Σ Credits down to integer minor units. Imbalanced vouchers are rejected immediately.
2. GL Immutability
Posted entries are strictly immutable. Row-level updates and deletions are forbidden by Eloquent hooks. Corrections require equal-and-opposite Storno reversal vouchers.
3. Leaf-Only Postings
Transactions are only permitted on leaf accounts (is_leaf = true). Parent aggregators hold tree rolls but reject direct financial postings.
4. Fiscal Period Locks
Transactions resolve automatically to fiscal calendars. Closed or locked months/quarters strictly reject any new voucher submissions or backdated modifications.
5. Maker-Checker Rules
Under strict governance, the creator of a voucher cannot approve their own entry. This enforces four-eyes segregation of duties for high-value journal postings.
6. Base Rate Immutability
The reporting base currency is the immutable ledger denominator. Its exchange rate is locked to 1.000000. All foreign currencies quote relative to base.
7. Functional GL Postings
While vouchers record in their original transaction currency, all General Ledger postings convert and persist in functional base currency minor units at posting time.
8. ACL Isolation
External domains (WMS, POS, Billing, CRM) never touch accounting database tables. All upstream domain events route strictly through the Anti-Corruption Layer.
9 Core Financial Engine Services.
Orchestrated effortlessly through the unified ium()->accounting() gateway.
accounts() Chart of Accounts (COA)
Hierarchical multi-level account tree. Distinguishes assets, liabilities, equity, revenues, and expenses. Enforces leaf-only postings and automated aggregator classification.
journalEntries() Journal Vouchers
Draft, submit, approve, and post double-entry vouchers. Features strict Maker-Checker segregation, zero-sum minor unit validation, and statutory Storno reversals.
ledger() General Ledger & Reports
Immutable book of entry. Instantly compile real-time Trial Balances, Balance Sheets, and Income Statements (P&L) partitioned by open or closed fiscal periods.
fiscalPeriods() Fiscal Calendar & Locks
Fiscal years and quarterly/monthly periods. Resolves transactions to active periods automatically. Enforces soft audit review locks and statutory hard closing locks.
costCenters() Analytical Dimensions
Multi-dimensional cost accounting. Tag individual journal voucher lines with Cost Centers, Projects, Departments, and Business Units for granular managerial P&L breakdown.
currencies() Multi-Currency & FX Engine
ISO 4217 currency registry with daily exchange rate snapshots. Convert amounts cleanly, format major/sub-units, and automatically denominate GL entries to base currency.
acl() Anti-Corruption Layer (ACL)
Isolates financial accounting from operational domains. Ingests facts from WMS, CRM, and Billing, automatically mapping domain events into posted double-entry journal vouchers.
closing() Year-End Closing
Executes statutory annual closing. Automatically sweeps and zeroes nominal revenue/expense accounts, creating an equity transfer voucher into Retained Earnings.
audit() Forensic Audit Trail
Append-only forensic log recording all lifecycle actions, author IDs, approver IDs, IP addresses, timestamps, and payload snapshots for external statutory auditors.
Intuitive syntax for mission-critical accounting.
Zero HTTP controllers. Zero presentation coupling. Pure PHP 8.2+ domain orchestration through a chainable, type-safe interface.
// 1. Draft a zero-sum journal voucher (amounts in minor units / cents)
$entry = ium()->accounting()->journalEntries()->createDraft(
CreateJournalEntryDto::fromMajor([
'entry_date' => '2026-03-31',
'entry_type' => JournalEntryType::Standard,
'currency_code' => 'USD',
'memo' => 'Payroll Processing - Engineering Dept',
'lines' => [
['account_code' => '5110', 'side' => 'debit', 'amount' => 25000.00, 'cost_center_code' => 'CC-ENG'],
['account_code' => '2110', 'side' => 'credit', 'amount' => 20000.00, 'memo' => 'Net Salaries Payable'],
['account_code' => '2130', 'side' => 'credit', 'amount' => 5000.00, 'memo' => 'Payroll Tax Withholding'],
],
])
);
// 2. Submit for review
ium()->accounting()->journalEntries()->submit($entry->id, $preparerId);
// 3. Maker-Checker Segregation: Distinct approver authorises posting
ium()->accounting()->journalEntries()->approve($entry->id, $managerId);
ium()->accounting()->journalEntries()->post($entry->id, $managerId);
// 4. If correction is needed: Never edit! Issue an immutable Storno reversal
$reversalVoucher = ium()->accounting()->journalEntries()->reverse(
$entry->id,
$managerId,
'Erroneous payroll calculation reissued'
); // Create an Asset aggregator account (parent node)
$currentAssets = ium()->accounting()->accounts()->create(
new CreateAccountDto(
'1100',
'Current Assets',
AccountType::Asset,
'USD',
null, // Root level
'Parent aggregator for all liquid assets'
)
);
// Add child leaf account: Automatically converts parent to aggregator
$bankOperating = ium()->accounting()->accounts()->create(
new CreateAccountDto(
'1110',
'JPMorgan Chase - Operating Account',
AccountType::Asset,
'USD',
$currentAssets->id
)
);
// Retrieve the entire hierarchical COA tree with rolled-up children
$accountTree = ium()->accounting()->accounts()->tree(); // 1. Generate real-time Trial Balance with zero-variance verification
$trialBalance = ium()->accounting()->ledger()->generateTrialBalance($periodId);
if (!$trialBalance['is_balanced']) {
throw new RuntimeException('Trial balance disparity detected!');
}
// 2. Compile statutory Balance Sheet (Assets = Liabilities + Equity)
$balanceSheet = ium()->accounting()->ledger()->generateBalanceSheet();
// 3. Run Income Statement (P&L) for active fiscal period
$incomeStatement = ium()->accounting()->ledger()->generateIncomeStatement($periodId);
$netProfit = $incomeStatement['net_income']; // Register an automated mapping for cross-domain Billing facts
ium()->accounting()->acl()->registerMapping(
'billing.invoice_settled',
'1110', // Debit: Bank Operating Cash
'1120' // Credit: Accounts Receivable
);
// Ingest domain event from upstream Billing/WMS without coupling
$voucher = ium()->accounting()->acl()->ingest(
new AclIngestEventDto(
'billing.invoice_settled',
450000, // $4,500.00 stored in integer cents
'USD',
'2026-03-31',
'Customer INV-8921 settlement via Stripe',
'billing.invoice',
'8921'
)
); // Establish daily exchange rate against base currency (USD)
ium()->accounting()->currencies()->setRate(
'EUR',
1.085000, // 1 EUR = 1.085 USD
'2026-03-31',
'ecb_daily_feed'
);
// Exact integer minor unit conversion
$usdCents = ium()->accounting()->currencies()->convertMinor(
10000, // 100.00 EUR
'EUR',
'USD',
'2026-03-31'
); // Output: 10850 ($108.50)
// Format minor units for statutory UI/reports
$display = ium()->accounting()->currencies()->formatMinor($usdCents, 'USD'); How Accounting anchors the ERP ecosystem.
Operational domains emit business events. The Anti-Corruption Layer translates them into zero-sum vouchers. The General Ledger remains an immutable financial sanctuary.
Operational Domains
Emits facts; holds no foreign keys to accounting tables.
Boundary Translation
Translates operational metadata into balanced debit/credit lines.
Resolves DR/CR chart accounts
Exact integer cents conversion
Σ Debits === Σ Credits ($0 drift)
General Ledger
Statutory book of truth; strictly immutable tables.
Supercharge AI Agents with Accounting Intelligence.
Financial domains are complex. Equip Google Antigravity, Claude Code, and Cursor AI with the official Obelawium Accounting skill to ensure every line of code complies with strict GAAP invariants.
Turnkey AI pair-programming for double-entry ledgers.
The skill provides AI assistants with step-by-step decision matrices, automated DTO blueprints, invariant verification procedures, and Pest PHP testing harnesses.
- Zero-sum math parity and integer minor unit precision awareness
- Automatic Storno reversal generation instead of forbidden row edits
- Maker-Checker duty segregation compliance checking
- ACL cross-domain ingestion mapping patterns
---
name: ium-accounting-development
description: Guide for AI agents developing with
or extending Obelawium Accounting (FMS & GL).
---
## Non-Negotiable Domain Invariants:
1. Zero-Sum Parity: Sum(Debits) === Sum(Credits)
2. GL Immutability: Storno reversals only
3. Leaf-Only Postings on Chart of Accounts
4. Hard Fiscal Period Lockout
5. Maker-Checker Duty Segregation
6. Base Functional Currency Rate = 1.000000
7. amount_functional Minor Units Denomination
8. Anti-Corruption Layer (ACL) Isolation Explore the Accounting Documentation.
Comprehensive guides covering installation, Chart of Accounts, voucher drafting, fiscal closing, multi-currency, and API reference.
Overview & Philosophy
Headless double-entry architecture, the 9 services catalog, and core domain philosophy.
Installation & Setup
Composer setup, configuration publishing, migration execution, and turnkey demo seeding.
Chart of Accounts
Hierarchical COA trees, account classes, normal balances, and leaf-only posting validation.
Journal Vouchers & GL
Drafting vouchers, zero-sum checking, Maker-Checker reviews, and Storno reversal mechanics.
Fiscal Periods & Closing
Calendar creation, transaction date resolution, period locks, and statutory Year-End rollover.
Multi-Currency & FX
ISO 4217 registry, base rate locking, daily FX snapshots, and minor unit arithmetic.
Analytical Dimensions
Tagging departments, projects, and business units for granular managerial P&L breakdown.
Anti-Corruption Layer
Cross-domain fact ingestion from WMS, CRM, and Billing without tight database coupling.
Invariants & Audit Log
The 8 domain invariants, complete exception catalog, and forensic audit trail.
Fluent API Reference
Complete catalog of methods, signatures, input DTOs, and returns across all 9 services.
Answers for Engineers & Auditors.
Everything you need to know about Obelawium Accounting's invariants, immutability, and architecture.
Why does Obelawium Accounting store amounts in integer minor units instead of floats?
What is the Storno reversal pattern, and why are posted vouchers immutable?
How does Maker-Checker segregation of duties prevent internal fraud?
How does the Anti-Corruption Layer (ACL) isolate Accounting from operational domains?
Can I use Obelawium Accounting with Filament, Laravel Nova, or custom Blade dashboards?
How does Multi-Currency accounting handle daily FX fluctuations and reporting?
How does the Fiscal Year-End closing workflow work?
What is the AI Agent Skill and how does it help development?
Ready for mathematical financial precision?
Eliminate floating-point drift, enforce Maker-Checker duty segregation, and anchor your Laravel enterprise applications on an immutable General Ledger.
composer require obelaw/ium-accounting