liberusoftware/currency-context-filament
Filament integration for liberusoftware/currency-context, adding admin UI components to view and manage currency contexts in your Laravel panels.
This is a presentation adapter: it does not implement currency logic itself, it wires an underlying currency-context domain module into Filament panels. That distinction drives everything below — expect it to ship Filament resources/pages/widgets/columns and a panel plugin class, not exchange-rate or formatting engines. Before installing, confirm you actually have the domain module (liberusoftware/module-currency-context or equivalent) available, since the adapter will assume its contracts, migrations, and service bindings exist.
Minimal steps:
NOASSERTION license, and a release date in the future, treat this as an internal/vendor package first and a public one second. Run composer show -a liberusoftware/currency-context-filament and confirm the version constraints and license before it enters a composer.json you intend to ship.composer require "liberusoftware/currency-context-filament:^1.0" --prefer-dist
Pin a specific minor; you have no community signal to catch a broken tag for you.vendor/liberusoftware/currency-context-filament/src/ and locate the provider plus any Plugin class. In a package this size, the source is the documentation — note the publish tags, config keys, migration paths, and whether the plugin is Filament\Contracts\Plugin.php artisan vendor:publish --provider="Liberu\CurrencyContextFilament\...ServiceProvider"
php artisan migrate
Then check config/currency-context.php (or equivalent) for the default/fallback currency and the table prefix.public function panel(Panel $panel): Panel
{
return $panel
->plugin(CurrencyContextPlugin::make());
}
First use case to prove out: open the panel and set a currency context (via whatever page/resource the adapter exposes), then confirm a Filament TextColumn renders money in that currency instead of the app default. If that round-trip works, the adapter is bound correctly to the domain module; if it doesn't, the problem is almost always registration order or a missing domain binding, not the column.
Where to look first, in order: the plugin class → the config file → the List/Create pages the package registers → the underlying domain service it injects. That last hop tells you what the adapter is actually a view over.
Scope the plugin per panel. The single most common mistake is registering a currency plugin on every panel. Currency context is usually audience-specific — an admin panel manages rates and defaults, a customer/tenant panel only reads the active context. Register the management surface on admin, and expose read-only consumers (a select, a formatted column) on the others.
Treat the context as a request-scoped resolver, not a global config value. In application code, resolve the context through the domain module's contract or facade rather than reading the config directly:
// good: respects whatever the Filament UI just set
$currency = app(CurrencyContext::class)->current();
// bad: ignores the adapter entirely
$currency = config('currency-context.default');
Formatting vs storage. Keep money in the database as integer minor units plus an explicit currency code. Use the adapter for display in Filament columns and for setting the active context; never let a presentation-layer currency change rewrite stored amounts. A currency-context adapter that silently reinterprets stored values is how you get 100x bugs in finance screens.
Wire it into your own resources, not just the package's. The adapter is most valuable when its context feeds your existing Filament resources:
Select::make('currency')
->options(fn () => app(CurrencyContext::class)->available())
->default(fn () => app(CurrencyContext::class)->current()->code)
->required()
->live();
Pair a ->live() selector with a MoneyColumn (or TextColumn::formatStateUsing(fn ($state) => ...)) so changing context re-renders amounts in the table without a full page reload.
Integration with tenancy and multi-panel setups. If the domain module supports per-tenant context, set it in middleware after tenant resolution but before the Livewire component mounts, so both HTTP and Livewire requests see the same context. For Livewire, prefer an event/$listener on context change over re-resolving in every mount().
Actions and bulk operations. Anything that creates financial records should stamp the currency at creation time from the context, then store it immutably. Use Filament ->action() closures that capture the currency once, not per-row, so a bulk operation can't half-succeed under a context that changed mid-flight.
Testing pattern. Bind a fake/known context in setUp() or use the domain module's test helpers, and add one test asserting that a context change actually changes rendered output — that is the integration seam most likely to break on a Filament upgrade.
NOASSERTION means you cannot assume MIT. Get written clarification from the maintainer before shipping this in a distributed or client product; it may be fine internally and not fine as a dependency of an open-source project.composer.json require) before upgrading Filament; a currency adapter that touches MoneyColumn-style formatting is exactly the kind of thing that breaks silently.composer show and diff against the repository's tags. Don't let a confusing date cause you to assume the package is abandoned — or current.migrate, and prefer publishing migrations over relying on package load order.->form(), ->table(), resource getPages()) where the package exposes them. If it doesn't expose them, fork and pin — an in-place edit to vendor/ will be lost on the next composer update.bootstrap/providers.php or config/app.php → plugin added to the correct panel → config published (not just read from defaults) → domain module bound in the container → cache cleared → Livewire asset/version refreshed. Nine times out of ten it's steps two or four.How can I help you explore Laravel packages today?