From: eileen Date: Tue, 8 Sep 2020 19:36:32 +0000 (+1200) Subject: Fix formatLocaleNumericRoundedByCurrency X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=c976334772411df95d0f9be98a31fdc5361c11ec;p=civicrm-core.git Fix formatLocaleNumericRoundedByCurrency The function was rounding by a max of 2 regardless of the number of places passed - it was only tested for 2 so seemed to work --- diff --git a/CRM/Utils/Money.php b/CRM/Utils/Money.php index 9da7a98fe9..45d2d3fd79 100644 --- a/CRM/Utils/Money.php +++ b/CRM/Utils/Money.php @@ -201,7 +201,7 @@ class CRM_Utils_Money { * @return string */ protected static function formatLocaleNumericRounded($amount, $numberOfPlaces) { - return self::formatLocaleNumeric(round($amount, $numberOfPlaces)); + return self::formatNumericByFormat($amount, '%!.' . $numberOfPlaces . 'i'); } /** @@ -216,7 +216,42 @@ class CRM_Utils_Money { * Formatted amount. */ public static function formatLocaleNumericRoundedByCurrency($amount, $currency) { - $amount = self::formatLocaleNumericRounded($amount, self::getCurrencyPrecision($currency)); + return self::formatLocaleNumericRoundedByPrecision($amount, self::getCurrencyPrecision($currency)); + } + + /** + * Format money for display (just numeric part) according to the current locale with rounding to the supplied precision. + * + * This handles both rounding & replacement of the currency separators for the locale. + * + * @param string $amount + * @param int $precision + * + * @return string + * Formatted amount. + */ + public static function formatLocaleNumericRoundedByPrecision($amount, $precision) { + $amount = self::formatLocaleNumericRounded($amount, $precision); + return self::replaceCurrencySeparators($amount); + } + + /** + * Format money for display with rounding to the supplied precision but without padding. + * + * If the string is shorter than the precision trailing zeros are not added to reach the precision + * beyond the 2 required for normally currency formatting. + * + * This handles both rounding & replacement of the currency separators for the locale. + * + * @param string $amount + * @param int $precision + * + * @return string + * Formatted amount. + */ + public static function formatLocaleNumericRoundedByOptionalPrecision($amount, $precision) { + $decimalPlaces = strlen(substr($amount, strpos($amount, '.') + 1)); + $amount = self::formatLocaleNumericRounded($amount, $precision > $decimalPlaces ? $decimalPlaces : $precision); return self::replaceCurrencySeparators($amount); } diff --git a/tests/phpunit/CRM/Utils/MoneyTest.php b/tests/phpunit/CRM/Utils/MoneyTest.php index 7b97b20b2f..82cca12ca8 100644 --- a/tests/phpunit/CRM/Utils/MoneyTest.php +++ b/tests/phpunit/CRM/Utils/MoneyTest.php @@ -72,6 +72,38 @@ class CRM_Utils_MoneyTest extends CiviUnitTestCase { $this->setCurrencySeparators(','); } + /** + * Test rounded by currency function with specified precision. + * + * @param string $thousandSeparator + * + * @dataProvider getThousandSeparators + */ + public function testFormatLocaleNumericRoundedByPrecision($thousandSeparator) { + $this->setCurrencySeparators($thousandSeparator); + $result = CRM_Utils_Money::formatLocaleNumericRoundedByPrecision(8950.3678, 3); + $expected = ($thousandSeparator === ',') ? '8,950.368' : '8.950,368'; + $this->assertEquals($expected, $result); + } + + /** + * Test rounded by currency function with specified precision but without padding to reach it. + * + * @param string $thousandSeparator + * + * @dataProvider getThousandSeparators + */ + public function testFormatLocaleNumericRoundedByOptionalPrecision($thousandSeparator) { + $this->setCurrencySeparators($thousandSeparator); + $result = CRM_Utils_Money::formatLocaleNumericRoundedByOptionalPrecision(8950.3678, 8); + $expected = ($thousandSeparator === ',') ? '8,950.3678' : '8.950,3678'; + $this->assertEquals($expected, $result); + + $result = CRM_Utils_Money::formatLocaleNumericRoundedByOptionalPrecision(123456789.987654321, 9); + $expected = ($thousandSeparator === ',') ? '123,456,789.98765' : '123.456.789,98765'; + $this->assertEquals($result, $expected); + } + /** * Test that using the space character as a currency works */