formatBalance('SYP') → "150,000.00 SYP" */ trait HasMinorUnits { /** * Convert display amount (e.g., 1500.00) to minor units (150000). * Uses string math to avoid float precision issues. */ public static function toMinor(string|int|float $amount, int $decimals = 2): int { return (int) round((float) $amount * (10 ** $decimals)); } /** * Convert minor units back to display amount string. * Returns a string to preserve precision (e.g., "1500.00"). */ public static function fromMinor(int $minor, int $decimals = 2): string { return number_format($minor / (10 ** $decimals), $decimals, '.', ''); } /** * Format a minor-unit value for user display. * e.g., formatMoney(150000, 'SYP', 2) → "150,000.00 SYP" */ public static function formatMoney( int $minor, string $currency = 'SYP', ?int $decimals = null ): string { $decimals = $decimals ?? config("wasl.wallet.minor_unit_decimals.{$currency}", 2); $amount = self::fromMinor($minor, $decimals); return number_format((float) $amount, $decimals, '.', ',') . ' ' . $currency; } }