Малый бизнес, а нужен еще один тип цен
Запись от 14.11.2014
Редакция "Малый бизнес" позволяет иметь только один тип цен, но что делать, если нужно два? Вариантов много, начиная со скрещивания демо-версии редакции "Бизнес" с текущей редакцией вплоть до повышения редакции.
Первый вариант мне не очень нравится, есть некоторая вероятность нарваться на проблемы с обновлениями.
Второй вариант кажется неразумным - из-за одного типа цен платить двойную стоимость лицензии, это уж слишком.
Внимание! Использование обработчика onGetOptimalPrice может быть более простым вариантом!
А суть задачи такая - на сайте заведены товары с оптовым типом цен ["BASE"], а теперь понадобилась розница. То есть пользователь регистрируется и видит по умолчанию розничный тип цен, а получив права на доступ к оптовым ценам видит уже их.
Первое что я делаю - завожу группу пользователей "Оптовые цены" и добавляю пользователям параметры ИНН, КПП, название организации - по их заполнению будет приниматься решение администратором о внесении пользователя в группу "Оптовые цены".
Затем в инфоблоке каталога добавляю новое свойство "RETAIL_PRICE".
Далее, что касается отображения цен в каталоге. В моем случае цены можно посмотреть только в карточке товара. Поэтому в result_modifier.php компонента прописываю такой код:
Это позволит нам по ключу "OPT" определить, имеет ли пользователь доступ к оптовым ценам. А в template.php я пишу примерно так:
Цены показываем только авторизованным пользователям.
Второе сложнее - нужно отредактировать компонент корзины (sale.basket.basket), что бы пользователь видел правильные цены. Здесь result_modifier.php получается немного больше, т.к. нужно отменить вывод нового свойства:
А в template.php, точнее basket_items.php (в basket_items_delayed.php делаю тоже самое):
А вот теперь задачка посложнее. Когда пользователь меняет количество товара через AJAX запрашиваются новые данные и обновляются, в конечно итоге внешний вид корзины меняется функцией updateBasketTable из файла script.js шаблона корзины. Я бы предпочел её переписать, но из соображений совместимости просто допишу свой код в конец функции, по счастливому стечению обстоятельств на jQuery просто с BX пока не разобрался... или не разбирался. Итак, вот что я пишу:
Теперь осталось оформить аналогичным образом шаблон компонента sale.order.ajax и в целом готово. Да, заказы на сайте будут собираться с оптовыми ценами. Но мы можем через обработчик дописать в комментарий к заказу, что заказ был сделан по розничным ценам.
Первый вариант мне не очень нравится, есть некоторая вероятность нарваться на проблемы с обновлениями.
Второй вариант кажется неразумным - из-за одного типа цен платить двойную стоимость лицензии, это уж слишком.
Внимание! Использование обработчика onGetOptimalPrice может быть более простым вариантом!
А суть задачи такая - на сайте заведены товары с оптовым типом цен ["BASE"], а теперь понадобилась розница. То есть пользователь регистрируется и видит по умолчанию розничный тип цен, а получив права на доступ к оптовым ценам видит уже их.
Первое что я делаю - завожу группу пользователей "Оптовые цены" и добавляю пользователям параметры ИНН, КПП, название организации - по их заполнению будет приниматься решение администратором о внесении пользователя в группу "Оптовые цены".
Затем в инфоблоке каталога добавляю новое свойство "RETAIL_PRICE".
Далее, что касается отображения цен в каталоге. В моем случае цены можно посмотреть только в карточке товара. Поэтому в result_modifier.php компонента прописываю такой код:
global $USER;
$arGroups = CUser::GetUserGroup($USER->GetID());
$arResult["OPT"] = (in_array(5, $arGroups)) ? true : false;
Это позволит нам по ключу "OPT" определить, имеет ли пользователь доступ к оптовым ценам. А в template.php я пишу примерно так:
<?if($USER->IsAuthorized()):?>
<?if($arResult["OPT"]): // if user has access to opt price?>
<b>Цена за шт.:</b> <?=$arResult["OFFERS"][$keyOff]["PRICES"]["BASE"]["PRINT_VALUE_VAT"];?>
<?elseif($iPrice = $arResult["PROPERTIES"]["RETAIL_PRICE"]["VALUE"]):?>
<b>Цена за шт.:</b> <?=number_format($iPrice, 2, '.', ' ');?> руб.
<?endif;?>
<?endif;?>
Цены показываем только авторизованным пользователям.
Второе сложнее - нужно отредактировать компонент корзины (sale.basket.basket), что бы пользователь видел правильные цены. Здесь result_modifier.php получается немного больше, т.к. нужно отменить вывод нового свойства:
global $USER;
$arGroups = CUser::GetUserGroup($USER->GetID());
$arResult["OPT"] = (in_array(5, $arGroups)) ? true : false;
// Del retail price from headers
foreach($arResult["GRID"]["HEADERS"] as $id => $arHeader) {
if($arHeader["id"] == "PROPERTY_RETAIL_PRICE_VALUE") {
unset($arResult["GRID"]["HEADERS"][$id]);
}
}
// Calc full sum
if(!$arResult["OPT"]) {
$iPriceSum = 0;
foreach($arResult["GRID"]["ROWS"] as $k=>$arItem) {
if($arItem["DELAY"] == "N" && $arItem["CAN_BUY"] == "Y") {
$iPriceSum += $arItem["QUANTITY"] * $arItem["PROPERTY_RETAIL_PRICE_VALUE"];
}
}
}
$arResult["allSum_FORMATED"] = number_format($iPriceSum, 0, '.', ' ')." руб.";
А в template.php, точнее basket_items.php (в basket_items_delayed.php делаю тоже самое):
<?if($arResult["OPT"]):?>
<div class="current_price" id="current_price_<?=$arItem["ID"]?>" data-price="<?=$arItem["PRICE"]?>">
<?=$arItem["PRICE_FORMATED"]?>
</div>
<?if ($bPriceType && strlen($arItem["NOTES"]) > 0):?>
<div class="type_price"><?=GetMessage("SALE_TYPE")?></div>
<div class="type_price_value"><?=$arItem["NOTES"]?></div>
<?endif;?>
<?elseif($arItem["PROPERTY_RETAIL_PRICE_VALUE"]):?>
<div class="current_price" id="current_price_<?=$arItem["ID"]?>" data-price="<?=$arItem["PROPERTY_RETAIL_PRICE_VALUE"]?>">
<?=number_format($arItem["PROPERTY_RETAIL_PRICE_VALUE"]*$arItem["QUANTITY"], 0, '.', ' ');?> руб.
</div>
<?if ($bPriceType && strlen($arItem["NOTES"]) > 0):?>
<div class="type_price"><?=GetMessage("SALE_TYPE")?></div>
<div class="type_price_value">Розничная цена</div>
<?endif;?>
<?endif;?>
А вот теперь задачка посложнее. Когда пользователь меняет количество товара через AJAX запрашиваются новые данные и обновляются, в конечно итоге внешний вид корзины меняется функцией updateBasketTable из файла script.js шаблона корзины. Я бы предпочел её переписать, но из соображений совместимости просто допишу свой код в конец функции, по счастливому стечению обстоятельств на jQuery просто с BX пока не разобрался... или не разбирался. Итак, вот что я пишу:
if (BX('PRICE_WITHOUT_DISCOUNT'))
BX('PRICE_WITHOUT_DISCOUNT').innerHTML = (res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'] != res['BASKET_DATA']['allSum_FORMATED']) ? res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'].replace(/\s/g, ' ') : '';
// For retail updated. My function
var iPriceFull = 0;
$("#basket_items .item-line").each(function() {
var qPrice = $(this).find(".current_price"),
iCount = $(this).find(".counter input").val(),
iPrice = parseFloat(qPrice.attr("data-price")),
iPriceThis = iCount * iPrice,
sPriceThis = String(iPriceThis),
sPriceThisF = sPriceThis.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ') + " руб.";
iPriceFull = iPriceFull + iPriceThis;
$(this).find(".current_price").text(sPriceThisF);
});
var sPriceFull = String(iPriceFull),
sPriceFullF = sPriceFull.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ') + " руб.";
$("#allSum_FORMATED").text(sPriceFullF);
}
Теперь осталось оформить аналогичным образом шаблон компонента sale.order.ajax и в целом готово. Да, заказы на сайте будут собираться с оптовыми ценами. Но мы можем через обработчик дописать в комментарий к заказу, что заказ был сделан по розничным ценам.