From what I found the pricing precision is defined by Magento\Framework\Pricing\PriceCurrencyInterface::DEFAULT_PRECISION
and I didn't see any implementing classes that changes this. I was able to accomplish this with of plugins. This should point you down the right path on the backend. The increased precision is visible on the frontend, but on product view pages price-utils.js
formats the price after the page loads and changes the precision back to two even after the Magento\Framework\Locale\Format
plugin updates the frontend precision configurations.
I believe this is caused by this line in Magento/Catalog/view/base/web/js/price-utils.js
around line 73
(precision ? decimalSymbol + am.toFixed(2).replace(/-/, 0).slice(2) : '');
I wound up overriding this file in the module and changing the line to
(precision ? decimalSymbol + am.toFixed(precision).replace(/-/, 0).slice(2) : '');
I'm sure there is a better way to do that, but I had to move on. The code for the plugins is below:
Vendor/Module/etc/di.xml
<?xml version="1.0"?>
<config>
<type name="Magento\Framework\Pricing\Render\Amount">
<plugin name="vendor_module_framework_pricing_render_amount" type="Vendor\Module\Plugin\Framework\Pricing\Render\Amount" />
</type>
<type name="Magento\Directory\Model\PriceCurrency">
<plugin name="vendor_module_directory_model_pricecurrency" type="Vendor\Module\Plugin\Directory\Model\PriceCurrency" />
</type>
<type name="Magento\Framework\Locale\Format">
<plugin name="vendor_module_framework_locale_format" type="Vendor\Module\Plugin\Framework\Locale\Format" />
</type>
</config>
Vendor/Module/Plugin/Framework/Pricing/Render/Amount.php
<?php
namespace Vendor\Module\Plugin\Framework\Pricing\Render;
use Magento\Framework\Pricing\PriceCurrencyInterface;
class Amount
{
public function beforeFormatCurrency(
$subject,
$amount,
$includeContainer = true,
$precision = PriceCurrencyInterface::DEFAULT_PRECISION
) {
return [$amount, $includeContainer, 4];
}
}
Vendor/Module/Plugin/Directory/Model/PriceCurrency.php
<?php
namespace Vendor\Module\Plugin\Directory\Model;
class PriceCurrency
{
public function beforeConvertAndRound(
$subject,
$amount,
$scope = null,
$currency = null,
$precision = \Magento\Directory\Model\PriceCurrency::DEFAULT_PRECISION
) {
return [$amount, $scope, $currency, 4];
}
public function beforeFormat(
$subject,
$amount,
$includeContainer = true,
$precision = \Magento\Directory\Model\PriceCurrency::DEFAULT_PRECISION,
$scope = null,
$currency = null
) {
return [$amount, $includeContainer, 4, $scope, $currency];
}
}
Vendor/Module/Plugin/Framework/Locale/Format.php
<?php
namespace Vendor\Module\Plugin\Framework\Locale;
class Format
{
public function afterGetPriceFormat($subject, $result) {
$result['precision'] = 4;
$result['requiredPrecision'] = 4;
return $result;
}
}