Редакция "Малый бизнес" позволяет иметь только один тип цен, но что делать, если нужно два? Вариантов много, начиная со скрещивания демо-версии редакции "Бизнес" с текущей редакцией вплоть до повышения редакции. Первый вариант мне не очень нравится, есть некоторая вероятность нарваться на проблемы с обновлениями. Второй вариант кажется неразумным - из-за одного типа цен платить двойную стоимость лицензии, это уж слишком. А суть задачи такая - на сайте заведены товары с оптовым типом цен ["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 и в целом готово. Да, заказы на сайте будут собираться с оптовыми ценами. Но мы можем через обработчик дописать в комментарий к заказу, что заказ был сделан по розничным ценам
Компания АКРИТ
Малый бизнес, а нужен еще один тип цен
Редакция "Малый бизнес" позволяет иметь только один тип цен, но что делать, если нужно два? Вариантов много, начиная со скрещивания демо-версии редакции "Бизнес" с текущей редакцией вплоть до повышения редакции.
Первый вариант мне не очень нравится, есть некоторая вероятность нарваться на проблемы с обновлениями.
Второй вариант кажется неразумным - из-за одного типа цен платить двойную стоимость лицензии, это уж слишком.
А суть задачи такая - на сайте заведены товары с оптовым типом цен ["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 и в целом готово. Да, заказы на сайте будут собираться с оптовыми ценами. Но мы можем через обработчик дописать в комментарий к заказу, что заказ был сделан по розничным ценам