Take a look at following files:
vendor/magento/module-catalog/view/base/web/js/price-utils.js
(controls the price rendering on product view pages)
vendor/magento/framework/Pricing/Render/Amount.php
(controls rendering of blocks throughout)
In the Amount.php file you'll find this function:
public function formatCurrency(
$amount,
$includeContainer = true,
$precision = PriceCurrencyInterface::DEFAULT_PRECISION
) {
return $this->priceCurrency->format($amount, $includeContainer, $precision);
}
We need to write a plugin to override this function:
- your custom module etc/di.xml
Vendor\Module\Pricing\Amount.php
/**
* @param PriceCurrencyInterface $priceCurrency
*/
public function __construct(
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
) {
$this->priceCurrency = $priceCurrency;
}
/**
* Format price value
*
* @param float $amount
* @param bool $includeContainer
* @param int $precision
* @return float
*/
public function afterFormatCurrency(\Magento\Framework\Pricing\Render\Amount $subject, $result)
{
$amount = $subject->getAmount()->getValue();
$includeContainer = true;
$precision = null;
if (floor($amount) == $amount) {
return $this->priceCurrency->format($amount, $includeContainer, $precision = 0);
}
return $result;
}
This should change price block output throughout (category, related, etc).
But, back to the first file - this will change the product view page back to a format with .00, so we also need to update this file too.
In function formatPrice of price-utils.js you will find below line
precision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;
Update this to
if (Number.isInteger(amount)) {
precision = 0;
} else {
precision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;
}
We can make this change using mixin.
view/frontend/requirejs-config.js
config: {
mixins: {
'Magento_Catalog/js/price-utils': {
'Vendor_Module/js/price-utils': true
}
}
}
view/frontend/web/js/price-utils.js
define([
'jquery',
'underscore'
],
function ($, _) {
'use strict';
var globalPriceFormat = {
requiredPrecision: 2,
integerRequired: 1,
decimalSymbol: ',',
groupSymbol: ',',
groupLength: ','
};
return function (target) {
function stringPad(string, times) {
return (new Array(times + 1)).join(string);
}
target.formatPrice = function formatPrice(amount, format, isShowSign) {
var s = '',
precision, integerRequired, decimalSymbol, groupSymbol, groupLength, pattern, i, pad, j, re, r, am;
format = _.extend(globalPriceFormat, format);
// copied from price-option.js | Could be refactored with varien/js.js
if (Number.isInteger(amount)) {
precision = 0;
} else {
precision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;
}
integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired;
decimalSymbol = format.decimalSymbol === undefined ? ',' : format.decimalSymbol;
groupSymbol = format.groupSymbol === undefined ? '.' : format.groupSymbol;
groupLength = format.groupLength === undefined ? 3 : format.groupLength;
pattern = format.pattern || '%s';
if (isShowSign === undefined || isShowSign === true) {
s = amount < 0 ? '-' : isShowSign ? '+' : '';
} else if (isShowSign === false) {
s = '';
}
pattern = pattern.indexOf('{sign}') < 0 ? s + pattern : pattern.replace('{sign}', s);
// we're avoiding the usage of to fixed, and using round instead with the e representation to address
// numbers like 1.005 = 1.01. Using ToFixed to only provide trailing zeroes in case we have a whole number
i = parseInt(
amount = Number(Math.round(Math.abs(+amount || 0) + 'e+' + precision) + ('e-' + precision)),
10
) + '';
pad = i.length < integerRequired ? integerRequired - i.length : 0;
i = stringPad('0', pad) + i;
j = i.length > groupLength ? i.length % groupLength : 0;
re = new RegExp('(\\d{' + groupLength + '})(?=\\d)', 'g');
// replace(/-/, 0) is only for fixing Safari bug which appears
// when Math.abs(0).toFixed() executed on '0' number.
// Result is '0.-0' :(
am = Number(Math.round(Math.abs(amount - i) + 'e+' + precision) + ('e-' + precision));
r = (j ? i.substr(0, j) + groupSymbol : '') +
i.substr(j).replace(re, '$1' + groupSymbol) +
(precision ? decimalSymbol + am.toFixed(precision).replace(/-/, 0).slice(2) : '');
return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
};
return target;
};
});