Хочу поделиться интересным наблюдением поведения простых компонент bitrix:catalog.*. В одном из проектов решили использовать стандартные шаблоны компонентов каталога, хотя и знали о некоторой недоработке их шаблонов.
Одной из задач была возможность управления правами на различные типы цен, в частности "РОЗНИЦА", "ОПТ1" и "ОПТ2". Права выставляются следующие: РОЗНИЦА - права на просмотр/покупку ВСЕМ пользователям, ОПТ1 - права на просмотр ВСЕМ пользователям и покупку группе "Пользователи ОПТ1", ОПТ2 - права на просмотр ВСЕМ пользователям и покупку группе "Пользователи ОПТ2". В такой схеме возникает проблема с минимальной ценой за товарную позицию, а заключается она в том, что компонент выводит минимальную цену без учёта возможности использования её для покупки.
В качестве примера рассмотрим компонент bitrix:catalog.section и стандартный шаблон .default. При наличии у товара значений всех типов цен, компонент выводит в качестве минимального ОПТ2. Значение MIN_PRICE формируется в component.php, а затем используется и выводится в шаблоне.
Собственно в методе CIBlockPriceTools::GetItemPrices присутствует условие CAN_VIEW для типа цен, а вот CAN_BUY отсутствует. Возможно так и было задумано, но нас такое значение не устаивает, поэтому для обновления значения будем использовать result_modifier шаблона и два метода: CIBlockPriceTools::GetCatalogPrices для получения переченя типов цен с параметрами типа и с указанием, возможен ли просмотр и покупка этого типа цен для групп текущего пользователя, а также вышеупомянутый CIBlockPriceTools::GetItemPrices для получения рассчитанных с учетом скидок цен для элемента.
Остаётся лишь в цикле перебрать возвращаемые CIBlockPriceTools::GetCatalogPrices типы цен и выбрать из подходящие под условие задачи, а затем передать оставшиеся в качестве одного из параметров CIBlockPriceTools::GetItemPrices.
Подобным образом в том же result_modifier определяем MIN_PRICE и для торговых предложений, но с учётом итераций по массиву $arItem['OFFERS'].
Одной из задач была возможность управления правами на различные типы цен, в частности "РОЗНИЦА", "ОПТ1" и "ОПТ2". Права выставляются следующие: РОЗНИЦА - права на просмотр/покупку ВСЕМ пользователям, ОПТ1 - права на просмотр ВСЕМ пользователям и покупку группе "Пользователи ОПТ1", ОПТ2 - права на просмотр ВСЕМ пользователям и покупку группе "Пользователи ОПТ2". В такой схеме возникает проблема с минимальной ценой за товарную позицию, а заключается она в том, что компонент выводит минимальную цену без учёта возможности использования её для покупки.
В качестве примера рассмотрим компонент bitrix:catalog.section и стандартный шаблон .default. При наличии у товара значений всех типов цен, компонент выводит в качестве минимального ОПТ2. Значение MIN_PRICE формируется в component.php, а затем используется и выводится в шаблоне.
...
$arItem['MIN_PRICE'] = false;
...
$arItem["PRICES"] = CIBlockPriceTools::GetItemPrices(
$arParams["IBLOCK_ID"],
$arResult["PRICES"],
$arItem,
$arParams['PRICE_VAT_INCLUDE'],
$arConvertParams
);
if (!empty($arItem["PRICES"]))
{
foreach ($arItem['PRICES'] as &$arOnePrice)
{
if ('Y' == $arOnePrice['MIN_PRICE'])
{
$arItem['MIN_PRICE'] = $arOnePrice;
break;
}
}
unset($arOnePrice);
}
...
|
Собственно в методе CIBlockPriceTools::GetItemPrices присутствует условие CAN_VIEW для типа цен, а вот CAN_BUY отсутствует. Возможно так и было задумано, но нас такое значение не устаивает, поэтому для обновления значения будем использовать result_modifier шаблона и два метода: CIBlockPriceTools::GetCatalogPrices для получения переченя типов цен с параметрами типа и с указанием, возможен ли просмотр и покупка этого типа цен для групп текущего пользователя, а также вышеупомянутый CIBlockPriceTools::GetItemPrices для получения рассчитанных с учетом скидок цен для элемента.
Остаётся лишь в цикле перебрать возвращаемые CIBlockPriceTools::GetCatalogPrices типы цен и выбрать из подходящие под условие задачи, а затем передать оставшиеся в качестве одного из параметров CIBlockPriceTools::GetItemPrices.
if (
$arResult['MODULES']['catalog']
&& $arItem['CATALOG']
&&
($arItem['CATALOG_TYPE'] == CCatalogProduct::TYPE_PRODUCT
|| $arItem['CATALOG_TYPE'] == CCatalogProduct::TYPE_SET)
) {
CIBlockPriceTools::setRatioMinPrice($arItem, false);
$arItem['MIN_BASIS_PRICE'] = $arItem['MIN_PRICE'];
/* */
$arPrices = CIBlockPriceTools::GetCatalogPrices($arParams['IBLOCK_ID'], $arParams['PRICE_CODE']);
foreach ($arPrices as $iKey => $arPrice) {
if (!$arPrice['CAN_VIEW'] && !$arPrice['CAN_BUY'])
continue;
$arPriceTypeID[] = $arPrice['ID'];
}
foreach ($arPrices as $iKey => $arPrice) {
if ($arPrice['CAN_VIEW'] && $arPrice['CAN_BUY']);
else unset($arPrices[$iKey]);
}
if (isset($arPrice))
unset($arPrice);
$arItem['PRICES'] = CIBlockPriceTools::GetItemPrices($arParams['IBLOCK_ID'], $arPrices, $arItem, $arParams['PRICE_VAT_INCLUDE'], $arCurrencyParams = array(), $USER_ID = 0, $LID = SITE_ID);
if (!empty($arItem['PRICES'])) {
foreach ($arItem['PRICES'] as $arOnePrice) {
if ($arOnePrice['MIN_PRICE'] == 'Y') {
$arItem['MIN_PRICE'] = $arOnePrice;
break;
}
}
unset($arOnePrice);
}
/* */
}
|
foreach ($arItem['OFFERS'] as $keyOffer => $arOffer) {...}
|