From ac5f2ccd96abd48231707f429d900ebe1e5f23bf Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 4 Mar 2014 15:39:33 -0800 Subject: [PATCH] api_v3_SyntaxConformanceTest - Fix hard failure The arbitrarily generated value of "tax_rate" violates the MySQL precision constraints. This commit ensures that the arbitrarily chosen values meet the constraint (while trying to preserve the old series of generated numbers for most use-cases). --- CRM/Core/CodeGen/Specification.php | 1 + CRM/Core/DAO.php | 7 ++- CRM/Utils/Number.php | 40 +++++++++++++++++ tests/phpunit/CRM/Utils/NumberTest.php | 59 ++++++++++++++++++++++++++ xml/templates/dao.tpl | 3 ++ 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 CRM/Utils/Number.php create mode 100644 tests/phpunit/CRM/Utils/NumberTest.php diff --git a/CRM/Core/CodeGen/Specification.php b/CRM/Core/CodeGen/Specification.php index 5ae770a6a9..c66b91df3e 100644 --- a/CRM/Core/CodeGen/Specification.php +++ b/CRM/Core/CodeGen/Specification.php @@ -279,6 +279,7 @@ class CRM_Core_CodeGen_Specification { $field['sqlType'] = 'decimal(' . $length . ')'; $field['phpType'] = 'float'; $field['crmType'] = 'CRM_Utils_Type::T_MONEY'; + $field['precision'] = $length; break; case 'float': diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 87f38e8885..b64a6ef26f 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -1339,7 +1339,12 @@ SELECT contact_id case CRM_Utils_Type::T_INT: case CRM_Utils_Type::T_FLOAT: case CRM_Utils_Type::T_MONEY: - $object->$dbName = $counter; + if (isset($value['precision'])) { + // $object->$dbName = CRM_Utils_Number::createRandomDecimal($value['precision']); + $object->$dbName = CRM_Utils_Number::createTruncatedDecimal($counter, $value['precision']); + } else { + $object->$dbName = $counter; + } break; case CRM_Utils_Type::T_BOOLEAN: diff --git a/CRM/Utils/Number.php b/CRM/Utils/Number.php new file mode 100644 index 0000000000..f971be6a6b --- /dev/null +++ b/CRM/Utils/Number.php @@ -0,0 +1,40 @@ + 123456 + $val = substr($val, 0, $sigFigs); // ex: 123456 => 1234 + + // Move any extra digits after decimal + $extraFigs = strlen($val) - ($sigFigs - $decFigs); + if ($extraFigs > 0) { + return $sign * $val / pow(10, $extraFigs); // ex: 1234 => 1.234 + } + else { + return $sign * $val; + } + } +} \ No newline at end of file diff --git a/tests/phpunit/CRM/Utils/NumberTest.php b/tests/phpunit/CRM/Utils/NumberTest.php new file mode 100644 index 0000000000..b241eb94b4 --- /dev/null +++ b/tests/phpunit/CRM/Utils/NumberTest.php @@ -0,0 +1,59 @@ +assertTrue(($expectedMinInclusive <= $decimal) && ($decimal < $expectedMaxExclusive), "Assert $decimal between $expectedMinInclusive and $expectedMaxExclusive"); + if (strpos($decimal, '.') === FALSE) { + $decimal .= '.'; + } + list ($before, $after) = explode('.', $decimal); + $this->assertTrue(strlen($before) + strlen($after) <= $sigFigs, "Assert $decimal [$before;$after] has <= $sigFigs sigFigs"); + $this->assertTrue(strlen($after) <= $decFigs, "Assert $decimal [$before;$after] has <= $decFigs decFigs"); + } + } + + function truncDecimalCases() { + $cases = array(); + // array($value, $precision, $expectedValue) + $cases[] = array(523, array(1,0), 5); + $cases[] = array(523, array(5,2), 523); + $cases[] = array(523, array(10,8), 52.3); + $cases[] = array(12345, array(3,3), 0.123); + $cases[] = array(0.12345, array(10,0), 12345); + $cases[] = array(-123.45, array(4,2), -12.34); + return $cases; + } + + /** + * @param $value + * @param $precision + * @param $expectedValue + * @dataProvider truncDecimalCases + */ + function testCreateTruncatedDecimal($value, $precision, $expectedValue) { + list ($sigFigs, $decFigs) = $precision; + $this->assertEquals($expectedValue, CRM_Utils_Number::createTruncatedDecimal($value, $precision), + "assert createTruncatedValue($value, ($sigFigs,$decFigs)) == $expectedValue" + ); + } +} \ No newline at end of file diff --git a/xml/templates/dao.tpl b/xml/templates/dao.tpl index 2bb97135ee..f4a5cf1e9e 100644 --- a/xml/templates/dao.tpl +++ b/xml/templates/dao.tpl @@ -183,6 +183,9 @@ class {$table.className} extends CRM_Core_DAO {ldelim} {if $field.length} 'maxlength' => {$field.length}, {/if} {* field.length *} +{if $field.precision} + 'precision' => array({$field.precision}), +{/if} {if $field.size} 'size' => {$field.size}, {/if} {* field.size *} -- 2.25.1