Добрый день!
На одном проекте потребовалось вывести на определенной странице все товары со скидкой, проставленной в Правилах работой с корзиной.
К сожалению, в данный момент для этого нет готового решения. Т.е. нельзя например в фильтре компонента или GetList-а задать определенный параметр и таким образом получить все нужные товары.
Погуляв по форумам в поисках готового решения не нашел ничего подходящего для меня, пришлось делать всё ручками с нуля :)
Сразу скажу, что не претендую на звание лучшего решения данного вопроса, но для моей задачи этого вполне хватило. Если будут какие-либо предложения по улучшению логики работы, буду только рад.
Как будем реализовывать: создаем скрипт, который будет проходится по всем товарам, смотреть есть ли у них скидка и если есть, проставлять специальное свойство. По этому свойству уже мы сможем фильтровать нужные нам товары. Скрипт ставим на крон с нужной периодичностью или запускаем руками при необходимости.
Почему не используем метод "на лету" - из-за потенциальных проблем с производительностью такого способа.
Итак, что делаем:
Заводим для нашего основного инфоблока свойство типа Список (можно и простую строку, у меня просто оно уже было). Ставим там одно единственное возможное значение (у меня это "yes"). У меня свойство имеет код SPECIALOFFER.

Далее в какой-нибудь служебной папочке добавляем скрипт следующего содержания, где меняем входные параметры на свои, а именно: код инфоблока, значение свойства, сам код свойства (если у вас он другой)
require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php");
CModule::IncludeModule("iblock");
CModule::IncludeModule("catalog");
// меняем под себя эти значения
$iblock_id = 10; // основной инфоблок
$idPropSale = 22; // ID значения свойства отвечающего за Акцию
$oldPropsSale = $arNewSale = array();
// перебираем все активные элементы нашего инфоблока
$resItem = CIBlockElement::GetList(
array("ID"=>"asc"),
array( "ACTIVE"=>"Y", "IBLOCK_ID"=>$iblock_id),
false,
false,
array("ID", "IBLOCK_ID", "PROPERTY_SPECIALOFFER")
);
while($arItem = $resItem->Fetch())
{
// запишем текущее значение свойства скидки
$oldPropsSale[$arItem["ID"]] = $arItem["PROPERTY_SPECIALOFFER_VALUE"];
// смотрим есть ли у нашего товара SKU
$offersExist = CCatalogSKU::getExistOffers($arItem["ID"], $arItem["IBLOCK_ID"]);
// для товаров с SKU
if($offersExist[$arItem["ID"]] == 1)
{
// получим все SKU
$resSku = CCatalogSKU::getOffersList(
$arItem["ID"],
$arItem["IBLOCK_ID"],
array("ACTIVE"=>"Y") // дополнительный фильтр предложений. по умолчанию пуст.
);
// Если нашли SKU
if(!empty($resSku[$arItem["ID"]]))
{
// Перебираем их
foreach($resSku[$arItem["ID"]] as $sku)
{
// смотрим есть ли для текущего предложения скидка
$arDiscounts = CCatalogDiscount::GetDiscountByProduct($sku["ID"], array(2), "N", 1, SITE_ID);// ID, группа пользователей, пр.подписки, Группа цены, сайт
// если нашлась скидка
if(!empty($arDiscounts))
{
// ставим для родителя флаг наличия скидки
$arNewSale[$sku["PARENT_ID"]] = "Y";
// если нашли останавливаем цикл
break;
}
}
}
}
else // для простых товаров
{
// смотрим есть ли для текущего предложения скидка
$arDiscounts = CCatalogDiscount::GetDiscountByProduct($arItem["ID"], array(2), "N", 1, SITE_ID);// ID, группа пользователей, пр.подписки, Группа цены, сайт
// если нашлась скидка
if(!empty($arDiscounts))
{
// ставим для родителя флаг наличия скидки
$arNewSale[$arItem["ID"]] = "Y";
}
}
}
// теперь проставляем свойство где нужно
foreach($arNewSale as $prodId => $propVal)
{
// ставим значение только если оно уже не установлено
if($oldPropsSale[$prodId] != "yes" && $propVal == "Y")
{
//echo "Значение для товара $prodId добавлено \r\n";
CIBlockElement::SetPropertyValuesEx($prodId, $iblock_id, array("SPECIALOFFER" => $idPropSale));
}
}
// теперь очистим устаревшие значения свойства Акция
foreach($oldPropsSale as $prodId => $propVal)
{
// ставим значение только если оно уже не установлено
if($oldPropsSale[$prodId] == "yes" && $arNewSale[$prodId] != "Y")
{
//echo "Значение у товара $prodId удалено \r\n";
CIBlockElement::SetPropertyValuesEx($prodId, $iblock_id, array("SPECIALOFFER" => false));
}
}
Всё, теперь нам только остается добавить фильтрацию по нашему свойству где это необходимо.
Предупреждение!! Если каталог у вас довольно большой - скрипт лучше повесить на крон во время наименьшей нагрузки, т.к. выполнятся он может долгое время.
Надеюсь кому-нибудь будет полезно.