From ca8cdd6008083538c255dd063d198444008f5e4e Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 12 Apr 2022 11:05:16 +0300 Subject: [PATCH] currency compare --- .../Espo/Core/Currency/CalculatorUtil.php | 13 +++++ application/Espo/Core/Field/Currency.php | 24 ++++++++ .../Espo/Core/Field/Currency/CurrencyTest.php | 56 +++++++++++++++---- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/application/Espo/Core/Currency/CalculatorUtil.php b/application/Espo/Core/Currency/CalculatorUtil.php index e925c18646..0080b72b4b 100644 --- a/application/Espo/Core/Currency/CalculatorUtil.php +++ b/application/Espo/Core/Currency/CalculatorUtil.php @@ -119,4 +119,17 @@ class CalculatorUtil $precision ); } + + public static function compare(string $arg1, string $arg2): int + { + if (!function_exists('bccomp')) { + return (float) $arg1 <=> (float) $arg2; + } + + return bccomp( + $arg1, + $arg2, + self::SCALE + ); + } } diff --git a/application/Espo/Core/Field/Currency.php b/application/Espo/Core/Field/Currency.php index 3f8412fa2e..99a6db90fb 100644 --- a/application/Espo/Core/Field/Currency.php +++ b/application/Espo/Core/Field/Currency.php @@ -91,6 +91,8 @@ class Currency /** * Add a currency value. + * + * @throws RuntimeException If currency codes are different. */ public function add(self $value): self { @@ -108,6 +110,8 @@ class Currency /** * Subtract a currency value. + * + * @throws RuntimeException If currency codes are different. */ public function subtract(self $value): self { @@ -159,6 +163,26 @@ class Currency return new self($amount, $this->getCode()); } + /** + * Compare with another currency value. Returns: + * - `1` if greater than the value; + * - `0` if equal to the value; + * - `-1` if less than the value. + * + * @throws RuntimeException If currency codes are different. + */ + public function compare(self $value): int + { + if ($this->getCode() !== $value->getCode()) { + throw new RuntimeException("Can't compare currencies with different codes."); + } + + return CalculatorUtil::compare( + $this->getAmountAsString(), + $value->getAmountAsString() + ); + } + /** * Create from an amount and code. * diff --git a/tests/unit/Espo/Core/Field/Currency/CurrencyTest.php b/tests/unit/Espo/Core/Field/Currency/CurrencyTest.php index 8963663c09..113fbfc72b 100644 --- a/tests/unit/Espo/Core/Field/Currency/CurrencyTest.php +++ b/tests/unit/Espo/Core/Field/Currency/CurrencyTest.php @@ -34,24 +34,17 @@ use Espo\Core\{ Field\Currency\CurrencyFactory, }; -use Espo\{ - ORM\Entity, -}; +use Espo\ORM\Entity; use RuntimeException; class CurrencyTest extends \PHPUnit\Framework\TestCase { - protected function setUp() : void - { - } - public function testValue() { $value = Currency::create(2.0, 'USD'); $this->assertEquals(2.0, $value->getAmount()); - $this->assertEquals('USD', $value->getCode()); } @@ -62,7 +55,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase ); $this->assertEquals(3.0, $value->getAmount()); - $this->assertEquals('USD', $value->getCode()); } @@ -73,7 +65,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase ); $this->assertEquals(-1.0, $value->getAmount()); - $this->assertEquals('USD', $value->getCode()); } @@ -82,7 +73,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase $value = (new Currency(2.0, 'USD'))->multiply(3.0); $this->assertEquals(6.0, $value->getAmount()); - $this->assertEquals('USD', $value->getCode()); } @@ -91,7 +81,6 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase $value = (new Currency(6.0, 'USD'))->divide(3.0); $this->assertEquals(2.0, $value->getAmount()); - $this->assertEquals('USD', $value->getCode()); } @@ -212,4 +201,47 @@ class CurrencyTest extends \PHPUnit\Framework\TestCase $factory->isCreatableFromEntity($entity, 'test') ); } + + public function testCompare1(): void + { + $this->assertEquals( + 1, + Currency::create(2.0, 'USD') + ->compare( + Currency::create(1.0, 'USD') + ) + ); + } + + public function testCompare2(): void + { + $this->assertEquals( + 0, + Currency::create(2.1, 'USD') + ->compare( + Currency::create(2.1, 'USD') + ) + ); + } + + public function testCompare3(): void + { + $this->assertEquals( + -1, + Currency::create(2.1, 'USD') + ->compare( + Currency::create(3.1, 'USD') + ) + ); + } + + public function testCompare4(): void + { + $this->expectException(RuntimeException::class); + + Currency::create(2.1, 'EUR') + ->compare( + Currency::create(2.1, 'USD') + ); + } }