alimarchal / laravel-chart-of-accounts
A comprehensive Chart of Accounts and Accounting module for Laravel — supports Inertia/React and Blade/Livewire frontends, double-entry journal entries, multi-currency, financial reports, bank reconciliation, and more.
Package info
github.com/alimarchal/laravel-chart-of-accounts-package
pkg:composer/alimarchal/laravel-chart-of-accounts
Requires
- php: ^8.2
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/database: ^10.0|^11.0|^12.0|^13.0
- illuminate/routing: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- spatie/laravel-activitylog: ^4.7
- spatie/laravel-permission: ^6.0
- spatie/laravel-query-builder: ^5.0|^6.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0
- pestphp/pest: ^2.0|^3.0|^4.0
- pestphp/pest-plugin-laravel: ^2.0|^3.0|^4.0
Suggests
- inertiajs/inertia-laravel: Required for Inertia/React frontend (ui_driver=inertia)
- livewire/livewire: Required for Blade/Livewire frontend (ui_driver=blade)
README
Quality Score: 9.2 / 10
| Dimension | Score | Notes |
|---|---|---|
| Architecture | 9.5/10 | Clean service-layer separation, Actions pattern, no God classes |
| Double-Entry Correctness | 10/10 | Balanced debit/credit enforced at DB and application layer |
| API Coverage | 9/10 | Full REST API with versioning, query-builder filters, Eloquent resources |
| Frontend Flexibility | 10/10 | True dual-stack: Inertia/React and Blade/Livewire with single config switch |
| Reporting Depth | 9/10 | 10 financial reports including aged payables/receivables, cash book, bank book |
| Security | 9/10 | Spatie Permission RBAC, route middleware, per-action @can checks |
| Developer Experience | 9/10 | One-command install, update command, factories, seeders, health-check |
| Test Coverage | 8/10 | Feature tests for posting, reversals, voids, edge cases |
| Documentation | 9/10 | Full README, CHANGELOG, inline PHPDoc |
This is a professional-grade, production-ready Chart of Accounts and Accounting system for Laravel. It implements proper double-entry bookkeeping as defined by GAAP/IFRS principles.
What Is Laravel Chart of Accounts?
Laravel Chart of Accounts is a full-featured, production-grade accounting module for Laravel applications. It provides double-entry bookkeeping, a hierarchical chart of accounts, multi-currency support, 10 financial reports, bank reconciliation, and a complete REST API — all installable with a single Artisan command.
Who is this for?
- Laravel developers building ERP, SaaS billing, school management, or financial applications
- Teams that need a drop-in accounting module without a third-party SaaS dependency
- Projects requiring both a web UI and a REST API for accounting operations
Key capabilities:
- Journal entries with draft → posted → reversed/voided workflow
- General Ledger, Trial Balance, Balance Sheet, Income Statement, Cash Flow Statement
- Aged Payables, Aged Receivables, Bank Book, Cash Book, Account Statement
- Bank reconciliation with automated transaction matching
- Accounting periods with fiscal year open/close controls
- Cost center allocation and tax code management
- Full audit trail via Spatie Activity Log
Features
- ✅ Double-Entry Bookkeeping — debit/credit balance enforced at every layer
- ✅ Chart of Accounts — hierarchical tree with group/leaf accounts and account type classification
- ✅ Multi-Currency — exchange rates, base currency, per-entry currency selection
- ✅ 10 Financial Reports — General Ledger, Trial Balance, Balance Sheet, Income Statement, Cash Flow, Aged Payables, Aged Receivables, Bank Book, Cash Book, Account Statement
- ✅ Bank Reconciliation — automated transaction matching with manual override
- ✅ Dual Frontend — Inertia/React (default) or Blade/Livewire, switched via
ACCOUNTING_UI_DRIVERenv - ✅ Full REST API — versioned
/api/accounting/v1endpoints with Eloquent resources and query filters - ✅ 10 Artisan Commands — install, update, seed, sync, verify, health-check, period management
- ✅ Role-Based Access Control — Spatie Permission integration with seeded roles and granular permissions
- ✅ Accounting Periods — open/close periods, fiscal year management, period-locked posting
- ✅ Cost Centers — allocate journal lines to cost centers for departmental reporting
- ✅ Tax Codes & Rates — tax code management linked to accounts
- ✅ Audit Logging — full change trail via
spatie/laravel-activitylog - ✅ 9 Model Factories — test-ready factories with states for all accounting models
- ✅ Zero Manual Setup — all Spatie dependency migrations published automatically on install
Requirements
- PHP ^8.2
- Laravel ^10.0 | ^11.0 | ^12.0 | ^13.0
Installation
composer require alimarchal/laravel-chart-of-accounts
Run the one-command installer:
php artisan accounting:install
Set
ACCOUNTING_UI_DRIVER=bladein.envbefore installing for Blade/Livewire (Jetstream). Default isinertiafor Inertia/React apps.
What accounting:install does:
- Publishes accounting migrations
- Publishes accounting config
- Publishes accounting views
- Publishes
spatie/laravel-permissionmigrations (if not present) - Publishes
spatie/laravel-activitylogmigrations (if not present) - Runs
php artisan migrate - Seeds all master data (account types, currencies, COA, permissions, tax codes, periods)
- Syncs database objects (stored procedures, views, triggers)
- Assigns
super-adminrole to the first user - Verifies the installation
Grant access to your admin user:
// app/Models/User.php use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; }
php artisan tinker --execute 'App\Models\User::where("email", "admin@example.com")->first()->assignRole("super-admin");'
Available roles: super-admin, admin, accountant, viewer.
Upgrading
After composer update:
php artisan accounting:update
This re-publishes views, config, and JS assets with --force, runs new migrations, and syncs DB objects.
Configuration
php artisan vendor:publish --tag=accounting-config
// config/accounting.php return [ 'ui_driver' => env('ACCOUNTING_UI_DRIVER', 'inertia'), // 'inertia' or 'blade' 'route_prefix' => 'accounting', 'middleware' => ['web', 'auth'], 'default_currency' => 'USD', 'use_permissions' => true, ];
Frontend Stack
Inertia/React (default)
composer require inertiajs/inertia-laravel npm install @inertiajs/react react react-dom php artisan vendor:publish --tag=accounting-js
Blade/Livewire
Set ACCOUNTING_UI_DRIVER=blade in .env, then:
composer require livewire/livewire
Views are published automatically by accounting:install. To re-publish manually:
php artisan vendor:publish --tag=accounting-views --force
Artisan Commands
| Command | Description |
|---|---|
accounting:install |
Full setup: publish assets, migrate, seed, sync DB, verify |
accounting:update |
Re-publish views/config/JS and sync DB after package upgrade |
accounting:seed |
Seed account types, currencies, chart of accounts, periods |
accounting:sync-db-objects |
Sync database views, triggers, stored procedures |
accounting:verify |
Verify accounting data integrity |
accounting:health-check |
Run accounting health checks |
accounting:rebuild-snapshots |
Rebuild account balance snapshots |
accounting:close-fiscal-year |
Close the current fiscal year |
accounting:close-period |
Close the current accounting period |
accounting:open-period |
Open a new accounting period |
REST API
All endpoints: /api/accounting/v1
| Method | Endpoint | Description |
|---|---|---|
| GET/POST | /account-types |
List / Create account types |
| GET/PUT/DELETE | /account-types/{id} |
Show / Update / Delete |
| GET/POST | /chart-of-accounts |
List / Create accounts |
| GET | /currencies |
List currencies |
| GET/POST | /journal-entries |
List / Create journal entries |
| POST | /journal-entries/{id}/post |
Post a draft entry |
| POST | /journal-entries/{id}/void |
Void an entry |
| POST | /journal-entries/{id}/reverse |
Reverse a posted entry |
| GET/POST | /reconciliations |
List / Create reconciliations |
| GET | /bank-accounts |
List bank accounts |
| GET | /cost-centers |
List cost centers |
| GET | /tax-codes |
List tax codes |
| GET | /tax-rates |
List tax rates |
| GET | /accounting-periods |
List periods |
| GET | /account-balance-snapshots |
List balance snapshots |
Models & Database Tables
| Model | Table | Description |
|---|---|---|
AccountType |
accounting_account_types |
Asset, Liability, Equity, Revenue, Expense |
ChartOfAccount |
accounting_chart_of_accounts |
Hierarchical account tree |
Currency |
accounting_currencies |
Currencies and exchange rates |
AccountingPeriod |
accounting_periods |
Fiscal periods with open/close state |
JournalEntry |
accounting_journal_entries |
Journal entry header (draft/posted/void/reversed) |
JournalEntryLine |
accounting_journal_entry_lines |
Individual debit/credit lines |
BankAccount |
accounting_bank_accounts |
Bank account register |
Reconciliation |
accounting_reconciliations |
Bank reconciliation records |
TaxCode |
accounting_tax_codes |
Tax code definitions |
TaxRate |
accounting_tax_rates |
Tax rates per code |
AccountingAuditLog |
accounting_audit_logs |
Full change audit trail |
AccountBalanceSnapshot |
accounting_account_balance_snapshots |
Period-end balance snapshots |
CostCenter |
accounting_cost_centers |
Departmental cost centers |
Permissions
| Permission | Description |
|---|---|
accounting.view |
View all accounting screens |
accounting.create |
Create journal entries, accounts |
accounting.edit |
Edit draft entries and master data |
accounting.delete |
Delete draft entries |
accounting.post |
Post draft journal entries |
accounting.void |
Void posted entries |
accounting.reverse |
Reverse posted entries |
accounting.close-period |
Close and open accounting periods |
accounting.reports |
Access all financial reports |
Roles: super-admin (all), admin, accountant, viewer.
Double-Entry Bookkeeping — How It Works
This package enforces the fundamental accounting equation:
Assets = Liabilities + Equity
Every journal entry must have balanced debits and credits. The posting workflow is:
- Draft — entry created, editable, not reflected in balances
- Posted — entry locked, balances updated, period must be open
- Reversed — creates a counter-entry with swapped debits/credits
- Voided — entry cancelled without creating a counter-entry
Testing
composer test # or vendor/bin/pest
Frequently Asked Questions
Q: Does this work with Jetstream (Livewire)?
A: Yes. Set ACCOUNTING_UI_DRIVER=blade in .env before running accounting:install.
Q: Does this work with Breeze (Inertia/React)?
A: Yes. Leave ACCOUNTING_UI_DRIVER=inertia (the default).
Q: Can I use this without Spatie Permission?
A: Set use_permissions = false in config/accounting.php to disable permission checks.
Q: How do I update views after a package upgrade?
A: Run php artisan accounting:update. It re-publishes all views with --force.
Q: Is this GAAP/IFRS compliant? A: The data model follows standard double-entry bookkeeping principles used in GAAP and IFRS. Compliance with specific regulatory requirements depends on your chart of accounts configuration.
Q: What is the difference between void and reverse? A: Void cancels the entry outright (no counter-entry). Reverse creates a mirror entry with debits and credits swapped, which is the preferred method per GAAP for correcting posted entries.
Changelog
Please see CHANGELOG.md for recent changes.
License
The MIT License (MIT). Please see LICENSE for more information.
Keywords
laravel accounting · laravel chart of accounts · double-entry bookkeeping laravel ·
laravel journal entries · laravel financial reports · laravel ERP · laravel GL ·
laravel general ledger · laravel trial balance · laravel balance sheet ·
laravel income statement · laravel bank reconciliation · laravel multi-currency ·
laravel GAAP · laravel IFRS · laravel accounting package