Добрый день!
На одном проекте потребовалось вывести на определенной странице все товары со скидкой, проставленной в Правилах работой с корзиной.
К сожалению, в данный момент для этого нет готового решения. Т.е. нельзя например в фильтре компонента или 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)); } }
Всё, теперь нам только остается добавить фильтрацию по нашему свойству где это необходимо.
Предупреждение!! Если каталог у вас довольно большой - скрипт лучше повесить на крон во время наименьшей нагрузки, т.к. выполнятся он может долгое время.
Надеюсь кому-нибудь будет полезно.