How To: Округление цен в магазине, форматирование цен
Централизованно округлить цены можно установкой количества десятичных знаков для Shop_Controller. В файл bootstrap.php
, в корне, добавьте для округления до десятых (по умолчанию значение 2):
Shop_Controller::instance()->decimalDigits(1);
До целых:
Shop_Controller::instance()->decimalDigits(0);
Опция decimalDigits() добавлена в версии 6.6.3.
Формат вывода
Для изменения формата вывода цены используйте опцию floatFormat(). В файл bootstrap.php
, в корне, добавьте для вывода только десятых:
Shop_Controller::instance()->floatFormat("%.1f");
или целых:
Shop_Controller::instance()->floatFormat("%.0f");
Различное округление для сайтов
Добавьте в файл bootstrap.php
обработчик события Core_Command_Controller_Default.onBeforeShowAction
с проверкой на текущий сайт, например:
class Core_Command_Controller_Observer
{
static public function onBeforeShowAction($object)
{
switch (CURRENT_SITE)
{
// Округление для сайта 1
case 1:
// до десятых
Shop_Controller::instance()->decimalDigits(1);
Shop_Controller::instance()->floatFormat("%.1f");
break;
// Округление для сайта 3
case 3:
// до целых
Shop_Controller::instance()->decimalDigits(0);
Shop_Controller::instance()->floatFormat("%.0f");
break;
// По умолчанию
default:
// до сотых
Shop_Controller::instance()->floatFormat("%.2f");
// Банковское округление как в 1С
Shop_Controller::instance()->bankersRoundHalfToEven(FALSE);
}
}
}
// Add observer
Core_Event::attach('Core_Command_Controller_Default.onBeforeShowAction', array('Core_Command_Controller_Observer', 'onBeforeShowAction'));
Международное банковское округление
Округление к ближайшему четному или нечетному значительно сокращает вероятность накопления ошибки за счет того, что количество четных и нечетных сумм статистически примерно одинаково.
По умолчанию используется округление к ближайшему четному. Например, налог 63.545 будет преобразован в 63.54, а 63.555 в 63.56.
Допускается включения округления к ближайшему нечетному (1С), тогда налог 63.545 будет преобразован в 63.55, а 63.555 тоже в 63.55.
Для переключения банковского округления к ближайшему нечетному (как в 1С) в bootstrap.php
внесите
Shop_Controller::instance()->bankersRoundHalfToEven(FALSE);
Для отключения банковского округления в bootstrap.php
внесите
Shop_Controller::instance()->bankersRounding(FALSE);
Округление до тысяч, сотен, десятков
Чтобы цена товара в интернет-магазине не была отпугивающей, иногда нужно округлить её до целых десятков. Округление осуществляется с помощью хука на событие Shop_Item_Controller.onAfterCalculatePrice
, вносимого в bootstrap.php или с помощью опции decimalDigits(), описанной в начале статьи.
class Shop_Price_Observer
{
static public function round($price)
{
/*
-3 — до тысяч
-2 — до сотен
-1 — до десятков
*/
return round($price, -3);
}
static public function onAfterCalculatePrice($object, $args)
{
$aPrice = $object->getAPrice();
$aPrice['price_discount'] = self::round($aPrice['price_discount']);
$object->setAPrice($aPrice);
}
}
Core_Event::attach('Shop_Item_Controller.onAfterCalculatePrice', array('Shop_Price_Observer', 'onAfterCalculatePrice'));
Форматирование цен в XSL
Создайте собственный формат, дайте ему наименование, например, my. Опишите формат, указав разделитель дробной части и групп. При выводе чисел используйте свой формат:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:hostcms="https://www.hostcms.ru/"
exclude-result-prefixes="hostcms">
<xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="utf-8" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>
<!-- Определяем собственный формат "my" -->
<xsl:decimal-format name="my" decimal-separator="," grouping-separator=" "/>
<xsl:template match="/shop">
...
</xsl:template>
<xsl:template match="shop_item">
...
Вариант 1:
<xsl:value-of select="format-number(price, '# ###', 'my')" />
Вариант 2:
<xsl:value-of select="format-number(price, '### ##0,00', 'my')" />
...
</xsl:template>
</xsl:stylesheet>
В шаблоне формата поддерживаются следующие символы:
- «.» и «,» — используются для описания расположения и типа пунктуации;
- «#» — используется для описания целых чисел;
- «0» — используется для расположения 0 до и после символа в случае, если позиция не покажет цифру. При усечении чисел справа от десятичного разделителя значение округляется (значение слева от десятичного разделителя не округляется);
- «%» и «‰».
Хранение цен в базе данных
Цены для товаров хранятся в поле price
таблицы shop_items
, данное поле имеет формат DECIMAL(12,2)
, где первое число (точность) представляет собой общее количество значащих десятичных знаков, с которыми будет храниться данная величина, а вторая цифра (масштаб) задает количество десятичных знаков после запятой.
Пример SQL-запроса для изменения формата поля:
ALTER TABLE `shop_items` CHANGE `price` `price` DECIMAL( 14, 4 ) NOT NULL DEFAULT '0.00';
Комментарии
-
Без темы
везде - на всех сайтах на одной установке?
как сделать, чтобы округление было только для конкретного сайта?
-
Без темы
А если мне нужно до десятков, то соответственно:
Shop_Controller::instance()->floatFormat("%.-1f");
или как?16.04.2015 01:50:38Без темы
Все варианты описаны на странице http://php.net/manual/ru/function.sprintf.php
-
Без темы
А это округление если сделать то везде будет округлять или только на некоторых шагах? Ибо сейчас у нас и так округляет но в админке в истории заказов все ровно пишет с копейками и в робокассы тоже все ровно выдает с копейками
22.03.2015 11:32:45