misaf / vendra-transaction
Wallet and ledger based financial transaction system with multi-gateway support, state-machine lifecycle and per-currency balances
Package info
github.com/misaf/vendra-transaction
Type:vendra-module
pkg:composer/misaf/vendra-transaction
Requires
- php: ^8.4
- flowframe/laravel-trend: ^0.5.0
- lara-zeus/spatie-translatable: ^2.0.1
- misaf/vendra-multimedia: v1.12.3
- misaf/vendra-support: v1.12.3
- spatie/eloquent-sortable: ^5.0.1
- spatie/laravel-activitylog: ^5.0
- spatie/laravel-model-states: ^2.11
- spatie/laravel-package-tools: ^1.93.1
- spatie/laravel-queueable-action: ^2.17
- spatie/laravel-sluggable: ^4.0.2
Requires (Dev)
None
Suggests
- misaf/vendra-currency: Install this in the host application to manage active currencies used by wallet provisioning and transaction forms.
Provides
None
Conflicts
None
Replaces
None
README
Wallet and ledger based financial transactions for Vendra: per-user, per-currency wallet balances, an immutable ledger, a state-machine transaction lifecycle with multi-gateway support, and a Filament admin cluster for transactions, gateways, and wallets.
Features
- Each user holds one
Walletper currency (created on first use viaTransactionService::walletFor()/defaultWalletFor()), with a cachedbalancein the currency's minor units. - The ledger is the single source of balance truth: every movement is an
immutable
LedgerEntry(signed amount,balance_aftersnapshot, polymorphic source) written byPostLedgerEntryActiontogether with the cached wallet balance under a row lock. Overdrafts throwInsufficientBalanceException. - A
Transactionis a gateway-facing money movement created throughCreateTransactionAction::execute(), which enforces per-walletTransactionLimits and attaches optional fee and metadata rows. Itsamountis always absolute; the ledger sign derives from the transaction type (deposit, withdrawal, commission, transfer, bonus). - The lifecycle is a Spatie model-states machine:
Pending → Processing → Review → Approved / Declined / Failed, driven byapprove(),decline(),fail(),markProcessing(), andmarkReview(). Settlement into the ledger happens exactly once, inside the transition toApproved— principal, mirrored transfer credit, and fee commit atomically with the status change. - Gateways are admin-managed labels (translatable name and description, a
scalar
sluglookup key, logo, sortable position); payment-processing logic lives in the host application. Internal movements use theinternal-transactionsgateway.
The module is decoupled from concrete user and currency packages. The wallet
owner model resolves from auth.providers.users.model; currency options resolve
through the provider-neutral capability in misaf/vendra-support.
Requirements
- PHP 8.4+
- Laravel 13
- Filament 5
misaf/vendra-supportmisaf/vendra-multimedia
Optional:
misaf/vendra-currency— supplies managed active/default currency options to the shared Support resolver
Installation
composer require misaf/vendra-transaction php artisan vendor:publish --tag=vendra-transaction-migrations php artisan migrate
Optional translations publish:
php artisan vendor:publish --tag=vendra-transaction-translations
Balance verification
Recompute cached wallet balances from the ledger and report (or repair) drift:
php artisan vendra-transaction:verify-balances php artisan vendra-transaction:verify-balances --repair
Testing
Run the package checks from the project root:
php artisan test --compact --testsuite=vendra-transaction
composer stan
License
MIT. See LICENSE.