amarenkov / laravel-mutable-content-finance
Personal finance domain for laravel-mutable-content: accounts, operations split by categories, transfers, debts and receipts, with services, without a UI.
Package info
github.com/amarenkov/laravel-mutable-content-finance
pkg:composer/amarenkov/laravel-mutable-content-finance
Requires
- php: ^8.4
- amarenkov/laravel-mutable-content: ^0.7.7
Requires (Dev)
- larastan/larastan: ^3.0
- orchestra/testbench: ^11.0
- phpunit/phpunit: ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-15 19:27:17 UTC
README
Personal finance domain for amarenkov/laravel-mutable-content:
accounts, operations split by categories, transfers between accounts and currencies, debts and
receipts, with services and events to build any interface on.
Scope
- Models with mutable fields, so an application adds its own fields without migrations.
- Amounts are
moneyfields of the core: an amount and a currency of thecurrencyLOV, exact decimal arithmetic, exact sums in SQL. - Services and events: creating and changing operations, transfers, splits. Every change lands in the core change log with its author.
- No user interface. Screens, bots and imports belong to the application.
Model
| Model | What it is |
|---|---|
Account |
A wallet, a card, a bank account of a user; one currency; the balance is the sum of its operations |
Operation |
Money in or out of one account: kind, date, amount (negative when money goes out), counterparty, comment, business flag |
Split |
Part of an operation amount in a category; the parts add up to the amount |
Category |
What money is spent on or comes from; a tree, expense or income |
Counterparty |
Who money goes to or comes from; its business flag is the default of new operations |
Receipt |
The QR code of a receipt of an operation; fiscal() reads a Russian fiscal receipt |
Operation kinds (the operation_kind LOV): income, expense, refund, transfer and debt.
The sign follows the kind: income is positive, expense negative, a refund goes the other way than
the operation it refunds (refund_of_id), a transfer and a debt are not zero. A transfer is two
operations pointing at each other. A debt operation is money lent or borrowed, given back or
returned: its sign tells the direction, Counterparty::debts() sums them by currency.
Requirements
- PHP 8.4
- Laravel 13
- PostgreSQL or MariaDB 10.7+, as required by
amarenkov/laravel-mutable-content
Installation
composer require amarenkov/laravel-mutable-content-finance php artisan vendor:publish --tag=mutable-content-finance-migrations php artisan migrate php artisan db:seed --class="Amarenkov\MutableContent\Database\Seeders\LovsSeeder" php artisan db:seed --class="Amarenkov\MutableContent\Database\Seeders\FieldsSeeder"
Add the currencies you use as items of the currency LOV of the core: it has only USD.
Usage
use Amarenkov\MutableContentFinance\Lovs\OperationKind; use Amarenkov\MutableContentFinance\Services\Operations; Operations::new($card) ->kind(OperationKind::EXPENSE) ->amount('-1250.50') // in the account currency ->at('2026-10-14 13:05') // display timezone; now by default ->counterparty($shop) ->split([[$food, '-1000'], [$home, '-250.50']]) ->receipt($qrText) ->by($request->user()) ->save(); Operations::new($card)->refundOf($purchase)->amount(250)->split([[$food, 250]])->save(); Operations::transfer($rubles, $dollars)->amount(9500, 100)->by($user)->save(); Operations::of($operation)->by($user)->update(['comment' => 'Groceries']); Operations::of($operation)->by($user)->split([[$food, '-1250.50']]); Operations::of($operation)->by($user)->delete(); // with its splits, receipts and transfer pair $card->balance(); // Money $card->balance($endOfMonth); // up to a moment $friend->debts(); // ['USD' => Money, ...], positive when the friend owes
Wrong currencies, a sign not suiting the kind, splits not adding up and a transfer between currencies without both amounts throw
DomainException. Events are dispatched after the transaction commits: OperationCreated,
OperationUpdated (with the changed fields), OperationDeleted.
Translations
Strings are in lang/{en,ru}/finance.php under the mutable-content-finance namespace. Publish
them to override:
php artisan vendor:publish --tag=mutable-content-finance-lang
License
MIT. See LICENSE.