feat: currency field display consistency and constraint improvements#119
feat: currency field display consistency and constraint improvements#119ManukMinasyan merged 18 commits into3.xfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves how the currency custom field type is presented across Filament surfaces (table, infolist, form) and adds CSV-safe export formatting, aiming for consistent currency display and better alignment with the validation capability system.
Changes:
- Introduces dedicated
CurrencyColumn(tables) andCurrencyEntry(infolists) using numeric formatting with a$prefix. - Updates
CurrencyComponent(forms) to remove hardcoded defaults/constraints and to better handle null + configurable decimal places. - Adds an export transformer to format currency values as CSV-safe strings with fixed 2-decimal precision.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Feature/Filament/Components/CurrencyFieldComponentsTest.php | Adds feature tests covering the new column/entry/component behavior and export transformer formatting. |
| src/Filament/Integration/Components/Tables/Columns/CurrencyColumn.php | New dedicated table column for currency with numeric formatting + $ prefix. |
| src/Filament/Integration/Components/Infolists/CurrencyEntry.php | New dedicated infolist entry for currency with numeric formatting + $ prefix. |
| src/Filament/Integration/Components/Forms/CurrencyComponent.php | Updates currency form input to respect decimal places and handle null without hardcoded min/default/rules. |
| src/FieldTypeSystem/Definitions/CurrencyFieldType.php | Switches currency field type to the new Filament components and adds a CSV-safe export transformer. |
src/Filament/Integration/Components/Tables/Columns/CurrencyColumn.php
Outdated
Show resolved
Hide resolved
src/Filament/Integration/Components/Infolists/CurrencyEntry.php
Outdated
Show resolved
Hide resolved
validation_rules is nullable in the database. When a custom field has null validation_rules, calling ->get() on null crashes. The nullsafe operator ?-> was incorrectly removed by a PHPStan "fix".
Replace hardcoded $ prefix and validation_rules-based decimal places
with proper type-specific settings using the withSettings() API.
Currency fields now have 4 configurable settings:
- Currency code (50+ ISO 4217 currencies with searchable dropdown)
- Display type (symbol, narrow symbol, code, name)
- Decimal places (0 or 2 with live preview)
- Grouping (default thousands separator or none)
Display components use Filament's ->money() method instead of
->numeric()->prefix('$'). Form component derives the currency
symbol dynamically via NumberFormatter.
Backward compatible: getDecimalPlaces() falls back to
validation_rules then default, getCurrencyCode() falls back to
config default.
…selects default() doesn't reliably hydrate existing records. afterStateHydrated ensures correct values on both create and edit forms. Cast decimal_places options to strings for select component compatibility.
the visibility check wrapper was overwriting any formatStateUsing set by the column type (e.g. CurrencyColumn). now captures and re-evaluates the existing formatter when the field is visible.
apply LocallyCalledStaticMethodToNonStaticRector, EncapsedStringsToSprintfRector, and NewlineBeforeNewAssignSetRector fixes flagged by CI.
- Use CurrencyFieldSettingsData with camelCase props and MapName mapper consistent with other data classes - Hydrate settings via data class instead of raw array access - Remove dead grouping setting (collected but never consumed) - Reduce display_type to symbol/code (the two actually implemented) - Remove obsolete HRK currency (replaced by EUR in 2023) - Add 3 decimal places option for BHD/KWD/OMR currencies - Stop hardcoding 2 decimal places in import/export transformers
There was a problem hiding this comment.
Pull request overview
This PR introduces a dedicated Currency field presentation across Filament tables, infolists, and forms, and centralizes currency-related constraints (decimal places, currency code, display type) via per-field settings and validation.
Changes:
- Added
CurrencyColumnandCurrencyEntryusing Filament money formatting for consistent display. - Updated
CurrencyComponentto remove hardcoded defaults/constraints and to respect configured decimal places and null values. - Added currency settings DTO +
CustomFieldhelpers, plus currency-specific validation rules and export transformer behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Feature/Filament/Components/CurrencyFieldComponentsTest.php | Adds feature coverage for currency column/entry/component/export behavior. |
| src/Services/ValidationService.php | Enforces currency decimal-places validation based on field settings. |
| src/Models/CustomField.php | Adds currency helper accessors and legacy fallback handling. |
| src/Filament/Integration/Components/Tables/Columns/CurrencyColumn.php | New table column for currency formatting. |
| src/Filament/Integration/Components/Infolists/CurrencyEntry.php | New infolist entry for currency formatting. |
| src/Filament/Integration/Components/Forms/CurrencyComponent.php | Updates form component formatting/dehydration and currency prefix logic. |
| src/Filament/Integration/Builders/TableBuilder.php | Preserves existing column formatter when applying visibility wrapper. |
| src/FieldTypeSystem/Definitions/CurrencyFieldType.php | Switches currency type to dedicated components and adds settings schema + import/export transformers. |
| src/Data/Settings/CurrencyFieldSettingsData.php | New DTO for currency-specific settings hydration. |
| config/custom-fields.php | Adds default currency code configuration. |
src/Filament/Integration/Components/Tables/Columns/CurrencyColumn.php
Outdated
Show resolved
Hide resolved
tests/Feature/Filament/Components/CurrencyFieldComponentsTest.php
Outdated
Show resolved
Hide resolved
src/Filament/Integration/Components/Infolists/CurrencyEntry.php
Outdated
Show resolved
Hide resolved
tests/Feature/Filament/Components/CurrencyFieldComponentsTest.php
Outdated
Show resolved
Hide resolved
- Use PHP intl ResourceBundle for dynamic, translatable currency list - Auto-detect decimal places per currency from NumberFormatter (JPY=0, BHD=3) - Filter historical/obsolete currencies automatically - Locale-aware: currency names translate with app()->getLocale() - Config override via custom-fields.currency.currencies for custom lists - Remove 50-currency hardcoded array from CurrencyFieldType
- Honor display_type setting in CurrencyColumn and CurrencyEntry (symbol uses ->money(), code uses ->numeric() with code prefix) - Guard NumberFormatter with class_exists() in CurrencyComponent and settings schema for environments without ext-intl - Pass $record and $column context to existing formatter in TableBuilder - Use $default parameter in CustomField::getDecimalPlaces() - Add 4 decimal places option to settings UI - Strengthen tests with isMoney/isNumeric/getPrefix assertions
- Replace static property caching with once() in CurrencyProvider for Octane/Swoole safety (no stale data across requests) - Use Str::length() instead of strlen() for UTF-8 consistency - Change $guarded from [] to ['id'] on CustomField model - Extract duplicated display_type branching into ConfiguresCurrencyFormatting trait shared by CurrencyColumn and CurrencyEntry
Summary
$1,200.50or codeUSD 1,200.50)minValue(0),default(0), andrules(['numeric', 'min:0'])— lets the capability system (MinValueCapability) handle these.formatStateUsinganddehydrateStateUsingnow handle null and respect configured decimal places.NumberFormatterguarded withclass_exists()for environments without ext-intl.Behavior changes
1234.56$1,234.561234.56USD 1,234.561234.56$1,234.561234.56USD 1,234.56$0.00min:0100.00100.0001234.567891234.56789(preserves precision)Test plan