Дано: каталог товаров с розничными и оптовыми ценами.
Задача: изменять тип цен в зависимости от суммы товарных позиций в корзине покупателя. Если сумма больше, либо равна 10 000 руб. - оптовый тип цен, меньше - розничный.
Для работы с ценами товарных позиций в корзине покупателя использовали обработчики событий OnBasketAdd, OnBasketUpdate и OnBasketDelete.
Скрытый текст |
---|
Код |
---|
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;
} |
|
Функция, приводящая цены корзины покупателя к требуемому типу:
Скрытый текст |
---|
Код |
---|
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;
} |
|
Чтобы исключить рекурсию обработчиков при вызове метода CSaleBasket::Update() вместе с валютой и значением "нового" типа цен передаётся параметр "ABORT", проверяя который мы можем прервать дальнейший вызов.
При использовании этих событий возникает собственно две проблемы (возможно и больше):
1. Цены меняются только в корзине. Заказ же пересчитывается с использованием наиболее подходящих цен.
2. Не ясно как применить к новым ценам действующие скидки.
По первому пункту, думаю, возможно использовать обработчик события OnGetOptimalPrice, но пока не найдено примеров его использования.