Open source
Credits for Laravel
composer require roundly-consulting/credits-for-laravelOverview
Credit and wallet balances for any Eloquent model, kept as an append-only ledger. Every change is its own immutable, time-stamped row — positive to grant, negative to deduct — and the balance is the sum of those rows, so you get the running total, the full history and any past balance without extra work. Named buckets, race-safe overdraft protection, exact fractional display and money-typed currency buckets are built in. MIT-licensed and dependency-light: Laravel plus two small Roundly packages.
What you get
Append-only ledger
Every grant and deduction is its own time-stamped row with a description and metadata. The balance is their sum — never a stored column.
Point-in-time balances
Ask for any balance as it stood at a past moment; the dated ledger reconstructs it exactly, per bucket or in total.
Named buckets
Keep promotional and purchased credit apart on the same owner — isolated balances, with totals across buckets when you want one figure.
Overdraft protection
Deductions below the floor throw by default, and a per-owner lock serialises racing changes on every isolation level — no double spend.
Exact fractional display
Integer minor units with a configurable scale and the native RoundingMode — no float drift, even at PHP_INT_MAX.
Currency-denominated buckets
Map a bucket to an ISO or custom currency and read and write it as Money; the wrong currency is refused before anything is written.
Facade, DI or actions
Credits::for($user) over an injectable CreditsManager and single-purpose actions, a recording fake, CreditsModified events and credits:modify.
Documentation
Installation
Install via Composer, publish and run the publish-only migration, and optionally publish the config and translations.
Configuration
Every config key and its default — model, key types, overdraft policy, default bucket, scale, rounding, currencies and bulk resolvers.
Key types & schema
The credits and credit_locks tables, and how key_type and primary_key_type type the morph column and the ledger’s own id.
Creditable models
Implement Creditable and use HasCredits on any Eloquent model — users, teams, accounts — to give it a ledger and a balance.
The Credits facade
Credits::for($owner) — an immutable scope to add, deduct, set and read credits per bucket, as integers or Money, plus owner-free helpers.
DI and actions
Inject CreditsManager instead of the facade, or call the single-purpose actions from jobs and services — modify, set, balance, total, format.
Granting & deducting
Append grants and deductions with modifyCredits(), attach a description and metadata, and set an exact balance with setCreditsTo().
Overdraft protection
Deductions below the floor throw InsufficientCreditsException by default; allow overdrafts per call or globally, and race-safely.
Reading balances
Read the current or a past balance, check available credits with hasCredits(), and query the ledger relation directly.
Named buckets
Split credit into isolated named pools on one owner, and sum chosen buckets or every bucket when you need a single figure.
Fractional credits & display
Store fractional credits as integer minor units with a scale, and render them as exact, locale-free decimal strings.
Currency-denominated buckets
Map a bucket to an ISO or custom money currency to read its balance as Money and refuse writes in any other currency.
Custom currencies & redemption
Denominate buckets in your own units such as loyalty points, respect the 64-bit precision limit, and redeem points for money.
Query scopes
Report over the ledger with the Credit model’s scopes — grants, deductions, point in time, owner and bucket filters.
Events
React to every recorded change with the CreditsModified event — the owner, the new ledger row and the bucket’s new balance.
Custom model & translations
Swap in your own Credit subclass through credits.model, and publish the exception messages to translate or reword them.
Artisan commands
Apply a credit change in bulk with credits:modify, and inspect the resolved configuration with php artisan about.
Exceptions
The credits exceptions and the money-for-laravel exceptions the package lets through — what throws them and what they carry.
Testing
Credits::fake() records every add, deduct and set without writing; or test balances, the guard and events against a real database.
Requirements
PHP 8.4+ with ext-bcmath, Laravel 12 or 13, and two Roundly packages that Composer installs for you.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.