From 1d1e0129917a3101caf4885d4b0817c1d435732c Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 27 Nov 2025 10:34:13 +0200 Subject: [PATCH] htmlizer: currency format --- .../Espo/Core/Currency/PrecisionProvider.php | 53 +++++++++++++++++++ application/Espo/Core/Htmlizer/Htmlizer.php | 29 +++++++++- .../Espo/Resources/metadata/app/currency.json | 33 +++++++++++- schema/metadata/app/currency.json | 10 ++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 application/Espo/Core/Currency/PrecisionProvider.php diff --git a/application/Espo/Core/Currency/PrecisionProvider.php b/application/Espo/Core/Currency/PrecisionProvider.php new file mode 100644 index 0000000000..7ac3ca5f7e --- /dev/null +++ b/application/Espo/Core/Currency/PrecisionProvider.php @@ -0,0 +1,53 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Core\Currency; + +use Espo\Core\Utils\Metadata; + +/** + * @since 9.3.0 + */ +class PrecisionProvider +{ + private const int DEFAULT_PRECISION = 2; + + public function __construct( + private Metadata $metadata, + ) {} + + public function get(?string $code): int + { + if (!$code) { + return self::DEFAULT_PRECISION; + } + + return $this->metadata->get("app.currency.precisionMap.$code") ?? self::DEFAULT_PRECISION; + } +} diff --git a/application/Espo/Core/Htmlizer/Htmlizer.php b/application/Espo/Core/Htmlizer/Htmlizer.php index 5c192b5fe3..39e4815215 100644 --- a/application/Espo/Core/Htmlizer/Htmlizer.php +++ b/application/Espo/Core/Htmlizer/Htmlizer.php @@ -34,6 +34,7 @@ use DOMDocument; use DOMElement; use DOMException; use DOMXPath; +use Espo\Core\Currency\PrecisionProvider; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Forbidden; use Espo\Core\ORM\Entity as CoreEntity; @@ -73,7 +74,7 @@ use const JSON_PRESERVE_ZERO_FRACTION; */ class Htmlizer { - private const LINK_LIMIT = 100; + private const int LINK_LIMIT = 100; public function __construct( private DateTime $dateTime, @@ -86,6 +87,7 @@ class Htmlizer private Config $config, private Log $log, private InjectableFactory $injectableFactory, + private PrecisionProvider $precisionProvider, private ?Acl $acl = null, private ?ServiceFactory $serviceFactory = null, ) {} @@ -1061,6 +1063,16 @@ class Htmlizer } } + if ($fieldType === FieldType::CURRENCY) { + $code = $data[$attribute . 'Currency'] ?? null; + + if (!is_string($code)) { + $code = null; + } + + $data[$attribute] = $this->formatCurrencyValue($data[$attribute], $code); + } + $data[$attribute] = $this->format($data[$attribute]); } } @@ -1107,4 +1119,19 @@ class Htmlizer return $data; } + + private function formatCurrencyValue(mixed $value, ?string $code): ?string + { + if (!is_string($value) && !is_int($value) && !is_float($value)) { + return null; + } + + if (is_string($value) && !is_numeric($value)) { + return null; + } + + $precision = $this->precisionProvider->get($code); + + return $this->number->format($value, $precision); + } } diff --git a/application/Espo/Resources/metadata/app/currency.json b/application/Espo/Resources/metadata/app/currency.json index f61ef0048f..18859eb94f 100644 --- a/application/Espo/Resources/metadata/app/currency.json +++ b/application/Espo/Resources/metadata/app/currency.json @@ -265,5 +265,36 @@ "ZAR", "ZMW", "ZWL" - ] + ], + "precisionMap": { + "BHD": 3, + "BIF": 0, + "CLP": 0, + "DJF": 0, + "GNF": 0, + "ISK": 0, + "IQD": 3, + "JOD": 3, + "JPY": 0, + "KMF": 0, + "KRW": 0, + "KWD": 3, + "LYD": 3, + "OMR": 3, + "PYG": 0, + "RWF": 0, + "TND": 3, + "UGX": 0, + "UYI": 0, + "VND": 0, + "VUV": 0, + "XAF": 0, + "XAU": 0, + "XBA": 0, + "XBB": 0, + "XBC": 0, + "XDR": 0, + "XOF": 0, + "XPF": 0 + } } diff --git a/schema/metadata/app/currency.json b/schema/metadata/app/currency.json index bffed8463e..6ec152b252 100644 --- a/schema/metadata/app/currency.json +++ b/schema/metadata/app/currency.json @@ -13,6 +13,16 @@ "description": "A 3-letter ISO 4217 currency code." } }, + "precisionMap": { + "type": "object", + "description": "A currency-code => precision mapping.", + "additionalProperties": { + "type": "number", + "description": "Number of decimal places.", + "minimum": 0, + "maximum": 4 + } + }, "list": { "type": "array", "description": "A list of currencies available in the system. Values defined as 3-letter currency codes in ISO 4217 standard. Use __APPEND__ to add new currencies w/o deleting existing.",