diff --git a/application/Espo/ORM/BaseEntity.php b/application/Espo/ORM/BaseEntity.php index 9ee2cee762..86a325d1c8 100644 --- a/application/Espo/ORM/BaseEntity.php +++ b/application/Espo/ORM/BaseEntity.php @@ -29,6 +29,7 @@ namespace Espo\ORM; +use Doctrine\DBAL\Types\Types; use Espo\ORM\DataLoader\EmptyLoader; use Espo\ORM\DataLoader\Loader; use Espo\ORM\Defs\Params\AttributeParam; @@ -482,6 +483,13 @@ class BaseEntity implements Entity $attributeType = $this->getAttributeType($attribute); + if ( + $attributeType === self::VARCHAR && + $this->getAttributeParam($attribute, AttributeParam::DB_TYPE) === Types::DECIMAL + ) { + return $this->prepareAttributeValueDecimal($attribute, $value); + } + if ($attributeType === self::FOREIGN) { $attributeType = $this->getForeignAttributeType($attribute) ?? $attributeType; } @@ -1165,4 +1173,26 @@ class BaseEntity implements Entity $this->loader->load($this); } + + private function prepareAttributeValueDecimal(string $attribute, mixed $value): ?string + { + if (!is_scalar($value) || !is_numeric($value)) { + return null; + } + + $scale = $this->getAttributeParam($attribute, AttributeParam::SCALE); + + $value = strval($value); + + $parts = explode('.', $value, 2); + + $left = $parts[0]; + $right = $parts[1] ?? ''; + + if (strlen($right) < $scale) { + $value = $left . '.' . str_pad($right, $scale, '0'); + } + + return $value; + } } diff --git a/tests/integration/Espo/Currency/CurrencyTest.php b/tests/integration/Espo/Currency/CurrencyTest.php index dcf35d9cf1..2dcf073506 100644 --- a/tests/integration/Espo/Currency/CurrencyTest.php +++ b/tests/integration/Espo/Currency/CurrencyTest.php @@ -29,6 +29,7 @@ namespace tests\integration\Espo\Currency; +use Espo\Core\Exceptions\Error; use Espo\Core\Formula\Manager as FormulaManager; use Espo\Modules\Crm\Entities\Lead; use Espo\Tools\Currency\RateService; @@ -67,6 +68,9 @@ class CurrencyTest extends \tests\integration\Core\BaseTestCase $this->assertEquals(1.3, $newRates->getRate('EUR')); } + /** + * @throws Error + */ public function testDecimal1(): void { $this->getMetadata()->set('entityDefs', 'Lead', [ @@ -82,12 +86,20 @@ class CurrencyTest extends \tests\integration\Core\BaseTestCase $this->getDataManager()->rebuild(); $this->reCreateApplication(); + $em = $this->getEntityManager(); + $value = Currency::create('10.1', 'USD') ->add(Currency::create('0.1', 'USD')); - /** @var Lead $lead */ - $lead = $this->getEntityManager()->getNewEntity(Lead::ENTITY_TYPE); + $lead = $em->getRDBRepositoryByClass(Lead::class)->getNew(); + $lead->setValueObject('testCurrency', $value); + + $value = $lead->getValueObject('testCurrency'); + $this->assertInstanceOf(Currency::class, $value); + + $this->assertEquals('10.2000', $value->getAmountAsString()); + $this->getEntityManager()->saveEntity($lead); /** @var Lead $lead */ @@ -98,6 +110,29 @@ class CurrencyTest extends \tests\integration\Core\BaseTestCase $this->assertInstanceOf(Currency::class, $value); $this->assertEquals('10.2000', $value->getAmountAsString()); $this->assertEquals(0, $value->compare(Currency::create('10.2', 'USD'))); + + // + + $lead = $em->getRDBRepositoryByClass(Lead::class)->getNew(); + + $value = Currency::create('10', 'USD'); + + $lead->setValueObject('testCurrency', $value); + + $value = $lead->getValueObject('testCurrency'); + $this->assertInstanceOf(Currency::class, $value); + + $this->assertEquals('10.0000', $value->getAmountAsString()); + + // + + $lead = $em->getRDBRepositoryByClass(Lead::class)->getNew(); + + $lead->setValueObject('testCurrency', null); + + $value = $lead->getValueObject('testCurrency'); + + $this->assertEquals(null, $value); } public function testFormulaConvert(): void