issue 1522
authorJaap Jansma <jaap.jansma@civicoop.org>
Mon, 27 Jan 2020 15:19:48 +0000 (16:19 +0100)
committerJaap Jansma <jaap.jansma@civicoop.org>
Mon, 27 Jan 2020 15:19:48 +0000 (16:19 +0100)
CRM/Utils/Rule.php
tests/phpunit/CRM/Utils/RuleTest.php
tests/phpunit/CiviTest/CiviUnitTestCase.php
tests/phpunit/api/v3/ContributionTest.php

index bb8be3aa21f310aac092a355a97531ebc570e06a..e7f890b3efe690d69c66c84d3d5b98e9c6e698e8 100644 (file)
@@ -596,19 +596,6 @@ class CRM_Utils_Rule {
    * @return bool
    */
   public static function money($value) {
-    $config = CRM_Core_Config::singleton();
-
-    // only edge case when we have a decimal point in the input money
-    // field and not defined in the decimal Point in config settings
-    if ($config->monetaryDecimalPoint &&
-      $config->monetaryDecimalPoint != '.' &&
-      // CRM-7122 also check for Thousands Separator in config settings
-      $config->monetaryThousandSeparator != '.' &&
-      substr_count($value, '.')
-    ) {
-      return FALSE;
-    }
-
     $value = self::cleanMoney($value);
 
     if (self::integer($value)) {
index cb047d79a96b3ed252b0f6f4efde4caf3353517d..7236c278a8b521c8a9d707fa3648ecfd8a93830f 100644 (file)
@@ -84,7 +84,10 @@ class CRM_Utils_RuleTest extends CiviUnitTestCase {
    * @param $inputData
    * @param $expectedResult
    */
-  public function testMoney($inputData, $expectedResult) {
+  public function testMoney($inputData, $decimalPoint, $thousandSeparator, $currency, $expectedResult) {
+    $this->setDefaultCurrency($currency);
+    $this->setMonetaryDecimalPoint($decimalPoint);
+    $this->setMonetaryThousandSeparator($thousandSeparator);
     $this->assertEquals($expectedResult, CRM_Utils_Rule::money($inputData));
   }
 
@@ -93,22 +96,56 @@ class CRM_Utils_RuleTest extends CiviUnitTestCase {
    */
   public function moneyDataProvider() {
     return [
-      [10, TRUE],
-      ['145.0E+3', FALSE],
-      ['10', TRUE],
-      [-10, TRUE],
-      ['-10', TRUE],
-      ['-10foo', FALSE],
-      ['-10.0345619', TRUE],
-      ['-10.010,4345619', TRUE],
-      ['10.0104345619', TRUE],
-      ['-0', TRUE],
-      ['-.1', TRUE],
-      ['.1', TRUE],
+      [10, '.', ',', 'USD', TRUE],
+      ['145.0E+3', '.', ',', 'USD', FALSE],
+      ['10', '.', ',', 'USD', TRUE],
+      [-10, '.', ',', 'USD', TRUE],
+      ['-10', '.', ',', 'USD', TRUE],
+      ['-10foo', '.', ',', 'USD', FALSE],
+      ['-10.0345619', '.', ',', 'USD', TRUE],
+      ['-10.010,4345619', '.', ',', 'USD', TRUE],
+      ['10.0104345619', '.', ',', 'USD', TRUE],
+      ['-0', '.', ',', 'USD', TRUE],
+      ['-.1', '.', ',', 'USD', TRUE],
+      ['.1', '.', ',', 'USD', TRUE],
       // Test currency symbols too, default locale uses $, so if we wanted to test others we'd need to reconfigure locale
-      ['$500.3333', TRUE],
-      ['-$500.3333', TRUE],
-      ['$-500.3333', TRUE],
+      ['$1,234,567.89', '.', ',', 'USD', TRUE],
+      ['-$1,234,567.89', '.', ',', 'USD', TRUE],
+      ['$-1,234,567.89', '.', ',', 'USD', TRUE],
+      ['1234567.89', '.', ',', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'USD', TRUE], // This is the float format.
+      // Test EURO currency
+      ['€1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['-€1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['€-1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['1234567.89', '.', ',', 'EUR', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'EUR', TRUE], // This is the float format.
+      // Test Norwegian KR currency
+      ['kr1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr 1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['-kr1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['-kr 1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr-1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr -1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['1234567.89', '.', ',', 'NOK', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'NOK', TRUE], // This is the float format.
+      // Test different localization options: , as decimal separator and dot as thousand separator
+      ['$1.234.567,89', ',', '.', 'USD', TRUE],
+      ['-$1.234.567,89', ',', '.', 'USD', TRUE],
+      ['$-1.234.567,89', ',', '.', 'USD', TRUE],
+      ['1.234.567,89', ',', '.', 'USD', TRUE],
+      ['1234567.89', ',', '.', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, ',', '.', 'USD', TRUE], // This is the float format.
+      ['$1,234,567.89', ',', '.', 'USD', FALSE],
+      ['-$1,234,567.89', ',', '.', 'USD', FALSE],
+      ['$-1,234,567.89', ',', '.', 'USD', FALSE],
+      // Now with a space as thousand separator
+      ['$1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['-$1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['$-1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['1234567.89', ',', ' ', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, ',', ' ', 'USD', TRUE], // This is the float format.
     ];
   }
 
index 27808ed1096682da5fbd675efb2a076afd4b3feb..02346b4897a330bf7c2d133239a4d48781a8c95a 100644 (file)
@@ -3247,14 +3247,52 @@ VALUES
   /**
    * Set the separators for thousands and decimal points.
    *
+   * Use setMonetaryDecimalPoint and setMonetaryThousandSeparator instead
+   *
    * @param string $thousandSeparator
+   * @deprecated
    */
   protected function setCurrencySeparators($thousandSeparator) {
+    // Jaap Jansma: I do think the code below is a bit useless. It does an assumption
+    // that when the thousand separator is a comma, the decimal is point. It
+    // does not cater for a situation where the thousand separator is a [space]
+    // Latter is the Norwegian localization.
     Civi::settings()->set('monetaryThousandSeparator', $thousandSeparator);
     Civi::settings()
       ->set('monetaryDecimalPoint', ($thousandSeparator === ',' ? '.' : ','));
   }
 
+  /**
+   * Sets the thousand separator.
+   *
+   * If you use this function also set the decimal separator: setMonetaryDecimalSeparator
+   *
+   * @param $thousandSeparator
+   */
+  protected function setMonetaryThousandSeparator($thousandSeparator) {
+    Civi::settings()->set('monetaryThousandSeparator', $thousandSeparator);
+  }
+
+  /**
+   * Sets the decimal separator.
+   *
+   * If you use this function also set the thousand separator setMonetaryDecimalPoint
+   *
+   * @param $thousandSeparator
+   */
+  protected function setMonetaryDecimalPoint($decimalPoint) {
+    Civi::settings()->set('monetaryDecimalPoint', $decimalPoint);
+  }
+
+  /**
+   * Sets the default currency.
+   *
+   * @param $currency
+   */
+  protected function setDefaultCurrency($currency) {
+    Civi::settings()->set('defaultCurrency', $currency);
+  }
+
   /**
    * Format money as it would be input.
    *
index 1e71806386870e158e6ee0b7c4aa0c82102d073c..8a86f1233e12d0aedd96867648af5639563d826a 100644 (file)
@@ -705,6 +705,93 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->callAPISuccessGetCount('Contribution', [], 2);
   }
 
+  /**
+   * @dataProvider createLocalizedContributionDataProvider
+   * @param $inputData
+   * @param $decimalPoint
+   * @param $thousandSeparator
+   * @param $currency
+   * @param $expectedResult
+   * @throws \Exception
+   */
+  public function testCreateLocalizedContribution($totalAmount, $decimalPoint, $thousandSeparator, $currency, $expectedResult) {
+    $this->setDefaultCurrency($currency);
+    $this->setMonetaryDecimalPoint($decimalPoint);
+    $this->setMonetaryThousandSeparator($thousandSeparator);
+
+    $_params = [
+      'contact_id' => $this->_individualId,
+      'receive_date' => '20120511',
+      'total_amount' => $totalAmount,
+      'financial_type_id' => $this->_financialTypeId,
+      'contribution_status_id' => 1,
+    ];
+
+    if ($expectedResult) {
+      $this->callAPISuccess('Contribution', 'create', $_params);
+    } else {
+      $this->callAPIFailure('Contribution', 'create', $_params);
+    }
+  }
+
+  /**
+   * @return array
+   */
+  public function createLocalizedContributionDataProvider() {
+    return [
+      [10, '.', ',', 'USD', TRUE],
+      ['145.0E+3', '.', ',', 'USD', FALSE],
+      ['10', '.', ',', 'USD', TRUE],
+      [-10, '.', ',', 'USD', TRUE],
+      ['-10', '.', ',', 'USD', TRUE],
+      ['-10foo', '.', ',', 'USD', FALSE],
+      ['-10.0345619', '.', ',', 'USD', TRUE],
+      ['-10.010,4345619', '.', ',', 'USD', TRUE],
+      ['10.0104345619', '.', ',', 'USD', TRUE],
+      ['-0', '.', ',', 'USD', TRUE],
+      ['-.1', '.', ',', 'USD', TRUE],
+      ['.1', '.', ',', 'USD', TRUE],
+      // Test currency symbols too, default locale uses $, so if we wanted to test others we'd need to reconfigure locale
+      ['$1,234,567.89', '.', ',', 'USD', TRUE],
+      ['-$1,234,567.89', '.', ',', 'USD', TRUE],
+      ['$-1,234,567.89', '.', ',', 'USD', TRUE],
+      ['1234567.89', '.', ',', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'USD', TRUE], // This is the float format.
+      // Test EURO currency
+      ['€1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['-€1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['€-1,234,567.89', '.', ',', 'EUR', TRUE],
+      ['1234567.89', '.', ',', 'EUR', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'EUR', TRUE], // This is the float format.
+      // Test Norwegian KR currency
+      ['kr1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr 1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['-kr1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['-kr 1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr-1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['kr -1,234,567.89', '.', ',', 'NOK', TRUE],
+      ['1234567.89', '.', ',', 'NOK', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, '.', ',', 'NOK', TRUE], // This is the float format.
+      // Test different localization options: , as decimal separator and dot as thousand separator
+      ['$1.234.567,89', ',', '.', 'USD', TRUE],
+      ['-$1.234.567,89', ',', '.', 'USD', TRUE],
+      ['$-1.234.567,89', ',', '.', 'USD', TRUE],
+      ['1.234.567,89', ',', '.', 'USD', TRUE],
+      ['1234567.89', ',', '.', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, ',', '.', 'USD', TRUE], // This is the float format.
+      ['$1,234,567.89', ',', '.', 'USD', FALSE],
+      ['-$1,234,567.89', ',', '.', 'USD', FALSE],
+      ['$-1,234,567.89', ',', '.', 'USD', FALSE],
+      // Now with a space as thousand separator
+      ['$1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['-$1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['$-1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['1 234 567,89', ',', ' ', 'USD', TRUE],
+      ['1234567.89', ',', ' ', 'USD', TRUE], // This is the float format. Encapsulated in strings
+      [1234567.89, ',', ' ', 'USD', TRUE], // This is the float format.
+    ];
+  }
+
   /**
    * Create test with unique field name on source.
    */