Дано: каталог товаров с розничными и оптовыми ценами.
Задача: изменять тип цен в зависимости от суммы товарных позиций в корзине покупателя. Если сумма больше, либо равна 10 000 руб. - оптовый тип цен, меньше - розничный.
Для работы с ценами товарных позиций в корзине покупателя использовали обработчики событий OnBasketAdd, OnBasketUpdate и OnBasketDelete.
Скрытый текст |
|---|
[CODE]AddEventHandler("sale", "OnBasketAdd", "OnBasketAddHandler"); AddEventHandler("sale", "OnBasketUpdate", "OnBasketUpdateHandler"); AddEventHandler("sale", "OnBasketDelete", "OnBasketDeleteHandler");
function OnBasketAddHandler($ID, $arFields) { $sEvents = ''; updateBasketType(); if (strlen($sEvents) > 0) AddMessage2Log("\n" . $sEvents); return; }
function OnBasketUpdateHandler($ID, $arFields) { $sEvents = ''; if (isset($arFields['ABORT']) && ($arFields['ABORT'] == 'Y')) return; updateBasketType(); if (strlen($sEvents) > 0) AddMessage2Log("\n" . $sEvents); return; }
function OnBasketDeleteHandler($ID) { $sEvents = ''; updateBasketType(); if (strlen($sEvents) > 0) AddMessage2Log("\n" . $sEvents); return; } [/CODE] |
Функция, приводящая цены корзины покупателя к требуемому типу:
Скрытый текст |
|---|
[CODE]function updateBasketType() { $sEvents = ''; if (!CModule::IncludeModule("iblock")) return; if (!CModule::IncludeModule("catalog")) return; if (!CModule::IncludeModule("sale")) return; $iRetailPriceType = 3; $iWholesalePriceType = 2; $iMaxSum = 10000; $arID = array(); $arBasketItems = array(); $arQuantities = array(); $dbBasketItems = CSaleBasket::GetList( array( "NAME" => "ASC", "ID" => "ASC" ), array( "FUSER_ID" => CSaleBasket::GetBasketUserID(), "LID" => SITE_ID, "ORDER_ID" => "NULL" ), false, false, array( "ID", "CALLBACK_FUNC", "MODULE", "PRODUCT_ID", "QUANTITY", "PRODUCT_PROVIDER_CLASS" ) ); while ($arItem = $dbBasketItems->Fetch()) { if ('' != $arItem['PRODUCT_PROVIDER_CLASS'] || '' != $arItem["CALLBACK_FUNC"]) { $arID[] = $arItem["ID"]; } } if (!empty($arID)) { $dbBasketItems = CSaleBasket::GetList( array( "NAME" => "ASC", "ID" => "ASC" ), array( "ID" => $arID, "ORDER_ID" => "NULL" ), false, false ); while ($arItem = $dbBasketItems->Fetch()) { $arBasketItems[] = $arItem; if (isset($arQuantities[$arItem['PRODUCT_ID']])) $arQuantities[$arItem['PRODUCT_ID']] += $arItem['QUANTITY']; else $arQuantities[$arItem['PRODUCT_ID']] = $arItem['QUANTITY']; } } // $sEvents .= var_export($arBasketItems, true) . "\n"; $arElements = array(); $arOffers = array(); $arID = array(); $fSum = 0; if (!empty($arBasketItems)) { foreach ($arBasketItems as $arItem) { $arID[] = $arItem["PRODUCT_ID"]; } $dbElements = CIBlockElement::GetList( array( "SORT" => "ASC" ), array( "ID" => $arID ), false, false, array( "ID", "CATALOG_GROUP_" . $iRetailPriceType, "CATALOG_GROUP_" . $iWholesalePriceType ) ); while ($arElement = $dbElements->GetNext()) { $arElements[$arElement['ID']] = $arElement; if (isset($arQuantities[$arElement['ID']])) $fSum += $arElement["CATALOG_PRICE_" . $iRetailPriceType] * $arQuantities[$arElement['ID']]; else $fSum += $arElement["CATALOG_PRICE_" . $iRetailPriceType]; } // $sEvents .= var_export($arElements, true) . "\n"; if ($fSum >= $iMaxSum) { //Устанавливаем для товарных позиций оптовый тип цен foreach ($arBasketItems as $arItem) { if (isset($arElements[$arItem['PRODUCT_ID']])) { $fPrice = $arElements[$arItem['PRODUCT_ID']]['CATALOG_PRICE_' . $iWholesalePriceType]; $arFields = array( "ABORT" => "Y", "CURRENCY" => $arElements[$arItem['PRODUCT_ID']]['CATALOG_CURRENCY_' . $iWholesalePriceType], "PRICE" => $fPrice, ); CSaleBasket::Update($arItem['ID'], $arFields); } } } else { //Устанавливаем для товарных позиций розничный тип цен foreach ($arBasketItems as $arItem) { if (isset($arElements[$arItem['PRODUCT_ID']])) { $fPrice = $arElements[$arItem['PRODUCT_ID']]['CATALOG_PRICE_' . $iRetailPriceType]; $arFields = array( "ABORT" => "Y", "CURRENCY" => $arElements[$arItem['PRODUCT_ID']]['CATALOG_CURRENCY_' . $iRetailPriceType], "PRICE" => $fPrice, ); CSaleBasket::Update($arItem['ID'], $arFields); } } } } if (strlen($sEvents) > 0) AddMessage2Log("\n" . $sEvents);
return true; }[/CODE] |
Чтобы исключить рекурсию обработчиков при вызове метода CSaleBasket::Update() вместе с валютой и значением "нового" типа цен передаётся параметр "ABORT", проверяя который мы можем прервать дальнейший вызов.
При использовании этих событий возникает собственно две проблемы (возможно и больше):
1. Цены меняются только в корзине. Заказ же пересчитывается с использованием наиболее подходящих цен.
2. Не ясно как применить к новым ценам действующие скидки.
По первому пункту, думаю, возможно использовать обработчик события OnGetOptimalPrice, но пока не найдено примеров его использования.