whilesmart / eloquent-accounts
Polymorphic financial account records for Laravel: bank accounts, mobile money wallets, card processors, cash registers. Attachable to payments and expenses.
Requires
- php: ^8.2
- laravel/framework: ^11.0|^12.0
- whilesmart/eloquent-owner-access: dev-dev
Requires (Dev)
- fakerphp/faker: ^1.24
- laravel/pint: ^1.22
- orchestra/testbench: ^9.0|^10.0
This package is auto-updated.
Last update: 2026-04-25 13:24:03 UTC
README
Polymorphic financial account records for Laravel. Bank accounts, mobile money wallets, card processors, cash registers, crypto wallets. Attaches on the account side of whilesmart/eloquent-payments and whilesmart/eloquent-expenses.
Why
eloquent-payments and eloquent-expenses both carry a nullable account polymorph. Without a concrete account model those fields go unused; reporting can't answer "what's in the Lagos UBA account right now?" or "how much came in through MTN MoMo this month?"
This package fills that gap. It is optional: if you don't install it, the morph columns on payments / expenses stay null and nothing breaks.
Install
composer require whilesmart/eloquent-accounts
php artisan migrate
Attach HasAccounts to the model that owns accounts (typically a workspace):
use Whilesmart\Accounts\Traits\HasAccounts; class Workspace extends Model { use HasAccounts; }
Data model
One accounts table. Each row belongs polymorphically to an owner and holds:
- Identity:
name,type(bank | mobile_money | card_processor | wallet | cash | crypto | other),status(active | closed | frozen). - Provider:
provider(string, e.g.UBA,MTN MoMo,Stripe),provider_reference,identifier(account number / last 4 / wallet number, safe to display). - Money:
currency,opening_balance_cents,balance_cents. is_primary: default account for its owner + currency. HelperprimaryAccount(string $currency = null)on the owner.metadata: JSON.
type and provider are free-form strings at the DB level so new rails don't need migrations; AccountType enum carries the canonical values.
Balance
Two modes:
- Computed (default,
ACCOUNTS_COMPUTE_BALANCE=true): when you read an account,balance_centsis derived asopening_balance_cents + succeeded inbound payments - succeeded outbound payments - paid expenses. Requireswhilesmart/eloquent-paymentsand/orwhilesmart/eloquent-expenses; gracefully degrades if they are not installed. - Stored (
ACCOUNTS_COMPUTE_BALANCE=false): reads thebalance_centscolumn. Call$account->refreshBalance()(orPOST /api/accounts/{id}/refresh-balance) to recompute and persist.
Routes
GET /api/accounts
POST /api/accounts
GET /api/accounts/{account}
PUT /api/accounts/{account}
DELETE /api/accounts/{account}
POST /api/accounts/{account}/refresh-balance
Index filters: owner_type, owner_id, type, status, currency, q, per_page.
Config
php artisan vendor:publish --tag=accounts-config:
return [ 'register_routes' => env('ACCOUNTS_REGISTER_ROUTES', true), 'route_prefix' => env('ACCOUNTS_ROUTE_PREFIX', 'api'), 'route_middleware' => ['api', 'auth:sanctum'], 'table' => env('ACCOUNTS_TABLE', 'accounts'), 'compute_balance' => env('ACCOUNTS_COMPUTE_BALANCE', true), ];
Siblings
whilesmart/eloquent-payments-- inbound / outbound transfers. Each Payment hasaccount_type+account_id.whilesmart/eloquent-expenses-- expenses, paid from accounts.whilesmart/eloquent-invoices-- invoices (money in). Tracks summary totals on the invoice row; actual payment records live ineloquent-payments, which reference an Account.