Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Chart Of Accounts Laravel Package

alimarchal/laravel-chart-of-accounts

Production-ready chart of accounts and double-entry accounting for Laravel. One-command install, works with Jetstream (Blade/Livewire) and Breeze (Inertia/React). Includes versioned REST API, RBAC, and core financial reports.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require alimarchal/laravel-chart-of-accounts
    php artisan vendor:publish --provider="AliMarchal\ChartOfAccounts\ChartOfAccountsServiceProvider"
    php artisan migrate
    
    • Publishes migrations, config, and seeders (default accounts, currencies, and tax rules).
  2. First Use Case:

    • Create a basic journal entry (double-entry):
      use AliMarchal\ChartOfAccounts\Facades\JournalEntry;
      
      $entry = JournalEntry::create()
          ->debit('Asset-Cash', 1000, 'USD')
          ->credit('Equity-OwnerCapital', 1000, 'USD')
          ->save();
      
    • View accounts (Blade/Livewire/Inertia):
      use AliMarchal\ChartOfAccounts\Facades\ChartOfAccounts;
      
      $accounts = ChartOfAccounts::all()->withBalances();
      
  3. Where to Look First:

    • Config: config/chart-of-accounts.php (currency settings, default tax rules).
    • Seeders: database/seeders/ChartOfAccountsSeeder.php (customize default accounts).
    • Actions: app/Actions/ (pre-built actions like CreateJournalEntry, ReconcileBankStatement).

Implementation Patterns

Core Workflows

  1. Account Management:

    • Hierarchical Accounts: Use Account::create() with parent_id for sub-accounts.
      Account::create([
          'code' => '5000',
          'name' => 'Revenue',
          'type' => 'income',
          'parent_id' => null, // Top-level
      ]);
      
    • Bulk Import: Use the ImportAccounts action with CSV/Excel:
      use App\Actions\ChartOfAccounts\ImportAccounts;
      
      $importer = new ImportAccounts();
      $result = $importer->execute($filePath);
      
  2. Journal Entries:

    • Double-Entry Enforcement: The package auto-balances entries but validates debits = credits.
    • Multi-Currency: Specify currency per line item:
      $entry = JournalEntry::create()
          ->debit('Asset-Cash', 1000, 'USD')
          ->debit('Asset-Cash-EUR', 900, 'EUR') // Separate account for EUR
          ->credit('Liability-AP', 1900, 'USD') // Auto-converts if needed
          ->save();
      
    • Recurring Entries: Use the RecurringEntry model:
      RecurringEntry::create([
          'description' => 'Monthly Rent',
          'frequency' => 'monthly',
          'journal_entry_data' => json_encode([...]), // Serialized entry data
      ]);
      
  3. Financial Reports:

    • Pre-built Reports: Use facades for common reports:
      use AliMarchal\ChartOfAccounts\Facades\Reports;
      
      $trialBalance = Reports::trialBalance()->forPeriod('2023-01-01', '2023-12-31')->get();
      $incomeStatement = Reports::incomeStatement()->forPeriod('2023-01-01', '2023-12-31')->get();
      
    • Custom Reports: Extend the ReportBuilder class or use query scopes:
      $customReport = JournalEntry::query()
          ->with(['debits.account', 'credits.account'])
          ->whereHas('debits.account', fn($q) => $q->where('type', 'income'))
          ->get();
      
  4. Bank Reconciliation:

    • Statement Import: Use the ReconcileBankStatement action:
      use App\Actions\ChartOfAccounts\ReconcileBankStatement;
      
      $reconciler = new Reconciler($statementFile, $accountId);
      $result = $reconciler->execute();
      
    • Manual Reconciliation: Mark entries as reconciled via the UI or API:
      $entry->markAsReconciled($reconciliationNote);
      
  5. Frontend Integration:

    • Livewire: Use the ChartOfAccountsTable component:
      use AliMarchal\ChartOfAccounts\Livewire\ChartOfAccountsTable;
      
      <livewire:chart-of-accounts-table :accounts="$accounts" />
      
    • Inertia/React: Fetch data via API routes (e.g., GET /api/accounts) and use the provided React hooks:
      import { useChartOfAccounts } from '@alimarchal/chart-of-accounts/react';
      
      function AccountsPage() {
        const { accounts, loading } = useChartOfAccounts();
        // Render accounts...
      }
      

Integration Tips

  • Laravel Nova: Publish the Nova resources:
    php artisan vendor:publish --tag="chart-of-accounts-nova"
    
  • Testing: Use the AccountFactory and JournalEntryFactory for unit tests:
    use AliMarchal\ChartOfAccounts\Database\Factories\AccountFactory;
    
    $account = AccountFactory::new()->create(['type' => 'asset']);
    
  • Events: Listen for accounting events (e.g., JournalEntryCreated):
    event(new JournalEntryCreated($entry));
    

Gotchas and Tips

Pitfalls

  1. Currency Conversion:

    • Gotcha: The package uses Laravel’s exchangeRate config but defaults to a fixed rate if not set. Fix: Configure config/chart-of-accounts.php with a service like exchangerate-api:
      'currency' => [
          'default' => 'USD',
          'conversion_service' => 'exchangerate-api',
          'api_key' => env('EXCHANGE_RATE_API_KEY'),
      ],
      
    • Tip: For manual overrides, use the convertCurrency() helper:
      $amountInEUR = JournalEntry::convertCurrency(1000, 'USD', 'EUR');
      
  2. Account Types:

    • Gotcha: Incorrect account types (e.g., asset vs. liability) can break reports. Fix: Validate types during creation:
      $validTypes = ['asset', 'liability', 'equity', 'income', 'expense'];
      if (!in_array($request->type, $validTypes)) {
          throw new \InvalidArgumentException("Invalid account type.");
      }
      
    • Tip: Use the AccountType enum for type safety:
      use AliMarchal\ChartOfAccounts\Enums\AccountType;
      
      $account = Account::create([
          'type' => AccountType::ASSET,
      ]);
      
  3. Journal Entry Validation:

    • Gotcha: Missing or mismatched debits/credits will throw a JournalEntryValidationException. Debug: Check the failed() method on the entry:
      $entry = JournalEntry::create()
          ->debit('Asset-Cash', 1000)
          ->credit('Equity-OwnerCapital', 500); // Will fail (500 != 1000)
      
      if ($entry->fails()) {
          dd($entry->errors());
      }
      
    • Tip: Use the dryRun() method to validate before saving:
      if (!$entry->dryRun()->isValid()) {
          return back()->withErrors($entry->errors());
      }
      
  4. Performance:

    • Gotcha: Large datasets in reports may time out. Fix: Use chunking for exports or add database indexes:
      // Add to JournalEntry model
      public function scopeForPeriod($query, $start, $end) {
          return $query->where('date', '>=', $start)
                       ->where('date', '<=', $end)
                       ->orderBy('date');
      }
      
    • Tip: Cache frequent reports:
      $trialBalance = Cache::remember("trial_balance_{$year}", now()->addHours(1), function () use ($year) {
          return Reports::trialBalance()->forYear($year)->get();
      });
      
  5. Multi-Tenancy:

    • Gotcha: Shared databases may cause account code conflicts. Fix: Scope accounts by tenant:
      // In Account model
      protected static function booted() {
          static::addGlobalScope('tenant', function (Builder $builder) {
              $builder->where('tenant_id', auth()->user()->tenant_id);
          });
      }
      

Debugging

  • Log Entries: Enable debug mode in config:
    'debug' => env('APP_ENV') === 'local',
    
    Logs journal entries and reconciliation steps to `storage
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony