Money Cast (currency)

Hello. I need to manage many money fields (usually Euros only) and I have a app\Casts\MoneyCast.php working fine with this content:
<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;

class MoneyCast implements CastsAttributes
{
/**
* Cast the given value.
*
* @param array<string, mixed> $attributes
*/
public function get(Model $model, string $key, mixed $value, array $attributes): mixed
{
return round(floatval($value) / 100, precision: 2);
}

/**
* Prepare the given value for storage.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model, string $key, mixed $value, array $attributes): mixed
{
return round(floatval($value) * 100);
}
}
<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;

class MoneyCast implements CastsAttributes
{
/**
* Cast the given value.
*
* @param array<string, mixed> $attributes
*/
public function get(Model $model, string $key, mixed $value, array $attributes): mixed
{
return round(floatval($value) / 100, precision: 2);
}

/**
* Prepare the given value for storage.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model, string $key, mixed $value, array $attributes): mixed
{
return round(floatval($value) * 100);
}
}
And then, in the different Models I have:
protected $casts = [
'previous_economic_assets' => MoneyCast::class,
];
protected $casts = [
'previous_economic_assets' => MoneyCast::class,
];
With as many fields as I need to be casted. The field in the table is storing the data in and integer field. The problem is that user can type more than 2 decimals. The problem is that I would like to use a mask (thousandseparator = . and decimalseparator , limit decimals to 2 and add € symbol at the end). I have seen other people have tried to create a customized MoneyInputField but I do not know where to begin. Any ideas of how can I customize my Money Cast to implement the Mask and suffix? Or, should it be better to create a custom input field for forms? I must consider that I do not want to repeat masking in every money input field I use in forms (they are really a big bunch) and I would like to have something more "automatic" if possible. Tks. By the way, if possible, users here type . or , for the decimal places (should admit both) although VISUALLY only comma is accepted for decimals.
9 Replies
Albert Lens
Albert LensOP15mo ago
Yes but not in FilamentPHP. You mean implementing money_format() inside the app\Casts\MoneyCast.php file? If so, I'll take a look though I thought it was not for masking.
alexanderkroneis
alexanderkroneis15mo ago
Ah sorry, I meant format_money from Filament\Support\format_money. It's format_money(100, 'EUR').
josef
josef15mo ago
Filament
Currency by AriaieBOY - Filament
Bring back laravel-money formatter for Filament Text Column.
Albert Lens
Albert LensOP15mo ago
No yet. I was just looking at it right now. You red my mind. I'll check this option and be back. Thank you. I have installed the plugin but: For the input it is OK, but only one key, in this case a dot (.) can be used for typing decimals. I would need it to accept both comma and dot. Also, when you go to the view page, it show the number without dividing by 100, that is, it eliminates the CAST instruction of $get, so user sees a wrong number. He sees it like One hundred and ninety-nine (199) when it is supposed to be one point ninety nine (1,99€) in Euros with a comma for the decimals. I do not know how to combine both methods, this plugin and the CAST which divides or multiplies by 100
josef
josef15mo ago
You can change the mask depending on the current currency also the decimal separator see also: https://discord.com/channels/883083792112300104/883084832387760148/1150770815017685065
Albert Lens
Albert LensOP15mo ago
Yes. Tks. I have run through it. But the problem with the cast part is critical. It cannot show 100 times the value. Also, here in Euros, users type decimals using dot or comma, whatever they like. for example, in Excel you can type 1.99 or 1,99 and system understand that is one point 99. I would need something like this. With this plugin ONLY ONE decimal separator can be used, which is the logical thing for SHOWING money fields, but in our case not for TYPING money fields.
josef
josef15mo ago
You have to decide on some variant at some point, giving total freedom to the user won't work as you can't infer, what they mean I for example decided to just use dot as separator and allow two decimals No fancy mask (as it destroyed the value when currency was changed) Then I cast to get the cents value and save as integer when I get the data from the db, I cast as Money and show in the correct currency format but input is always 'XXXn.YY' You either decide on one separator and enforce it, which users are used to, as it is a problem everyone has to tackle when doing currencies, or you allow free input and have the very hard problem of figuring out what the user meant
Albert Lens
Albert LensOP15mo ago
I see. Thank you. But the fact is that now with the cast part only, my app users can type 1.99 or 1,99 and with both ways it understands ONE POING NINETY-NINE. The only problem is it lets them type more than two decimal places, though finally it rounds it to two. So I prefer the part I have now because lets my users work as they usually do. In fact the perfect solution would be: a different mask for input and a different one for swhowing info after input. Tks anyway to everybody.
Want results from more Discord servers?
Add your server