Сортировка товаров по наличию при вкл. опции "Разрешить покупку при отсутствии товара (включая разрешение отрицательного количества товара)"
ПРОБЛЕМА:
При установке в настройках модуля торгового каталога, флага "Разрешить покупку при отсутствии товара (включая разрешение отрицательного количества товара)",
перестает работать настройка компонента каталога "Источник данных"-Товары, которых нет на складах: "показывать в конце" и "не отображать".
Поиски решения:
Поиски решения были начаты с самого компонента bitrix.catalog который собственно и выводить товары. По логике я ожидал найти в нем ту часть кода которая отвечала бы за выборку (какой то GetList допустим), и которую можно было бы изменить, полностью кастомизировав компонент вынеся его в пространство имен. Но не тут то было... Опять пресловутая "гибкость" сделала свое дело...
Ответ ТП Битрикс: ID 2669755
Выборка происходит в \Bitrix\Iblock\Component\Base::getSeparateList.
Что касается сортировки в целом, то при включении настройки Разрешить покупку при отсутствии товара (включая разрешение отрицательного количества товара),
недоступных товаров нет в принципе и стандартная сортировка по доступности работать не будет.
РЕШЕНИЕ:
1) добавляем в ИБ товара св-во SORTAVAIL тип число, в него будет записываться сумма "CATALOG_QUANTITY" всех его ТП или в случае если их нет то значение из этого же поля товара (простой товар).
2) Пишем обработчик, на событие обновления элемента каталога "OnProductUpdate" (событие "OnAfterIBlockElementUpdate" не подходит!).
Который после изменения параметров товара\его тп, получает товар и все его ТП, и в цикле суммирует все значения "CATALOG_QUANTITY" его ТП.
Если товар простой и у него нет ТП то берет его значение "CATALOG_QUANTITY" и также записывает в св-во SORTAVAIL товара
----------- init.php -----------
----------- CRON /local/updProdSortavail/index.php -----------
ТП был задан вопрос для чего нас лишили такой необходимой возможности (в крайнем случае, а этот случай именно такой...) изменять выборку так как нужно клиенту, с просьбой создать обращение в отдел разработки.
Кто что думает по этому поводу отпишитесь плз!
ПРОБЛЕМА:
При установке в настройках модуля торгового каталога, флага "Разрешить покупку при отсутствии товара (включая разрешение отрицательного количества товара)",
перестает работать настройка компонента каталога "Источник данных"-Товары, которых нет на складах: "показывать в конце" и "не отображать".
Поиски решения:
Поиски решения были начаты с самого компонента bitrix.catalog который собственно и выводить товары. По логике я ожидал найти в нем ту часть кода которая отвечала бы за выборку (какой то GetList допустим), и которую можно было бы изменить, полностью кастомизировав компонент вынеся его в пространство имен. Но не тут то было... Опять пресловутая "гибкость" сделала свое дело...
Ответ ТП Битрикс: ID 2669755
Выборка происходит в \Bitrix\Iblock\Component\Base::getSeparateList.
Что касается сортировки в целом, то при включении настройки Разрешить покупку при отсутствии товара (включая разрешение отрицательного количества товара),
недоступных товаров нет в принципе и стандартная сортировка по доступности работать не будет.
РЕШЕНИЕ:
1) добавляем в ИБ товара св-во SORTAVAIL тип число, в него будет записываться сумма "CATALOG_QUANTITY" всех его ТП или в случае если их нет то значение из этого же поля товара (простой товар).
2) Пишем обработчик, на событие обновления элемента каталога "OnProductUpdate" (событие "OnAfterIBlockElementUpdate" не подходит!).
Который после изменения параметров товара\его тп, получает товар и все его ТП, и в цикле суммирует все значения "CATALOG_QUANTITY" его ТП.
Если товар простой и у него нет ТП то берет его значение "CATALOG_QUANTITY" и также записывает в св-во SORTAVAIL товара
----------- init.php -----------
AddEventHandler("catalog", "OnProductUpdate", array("IBlockHandler", "DoOnProductUpdateHandler")); class IBlockHandler { protected static $handlerDisallow = false; function DoOnProductUpdateHandler($id, &$arFields) { //\Bitrix\Main\Diag\Debug::writeToFile($id); //\Bitrix\Main\Diag\Debug::writeToFile($arFields); /* проверяем, что обработчик уже запущен */ if (self::$handlerDisallow) return; /* взводим флаг запуска */ self::$handlerDisallow = true; //Updating PRODUCT prop SORTAVAIL if($arFields['IBLOCK_ID']==IBLOCK_ID_PRODUCTS_OFFERS){ //offer self::updateProductSortAvail(IBLOCK_ID_PRODUCTS_OFFERS, $id); }elseif ($arFields['IBLOCK_ID']==IBLOCK_ID_PRODUCTS){ //product self::updateProductSortAvail(IBLOCK_ID_PRODUCTS_OFFERS, null, $id); } /* вновь разрешаем запускать обработчик */ self::$handlerDisallow = false; } /** * Update product property SORTAVAIL sort * @param null $product_id */ function updateProductSortAvail($iblock_id, $offer_id=null, $product_id=null) { if(CModule::IncludeModule("iblock") && CModule::IncludeModule("catalog")) { $quantity_summ = 0; if(!$product_id) { $product = CCatalogSku::GetProductInfo($offer_id, $iblock_id); Bitrix\Main\Diag\Debug::writeToFile($product); $product_id = $product['ID']; } //If isset offers if(CCatalogSKU::IsExistOffers($product_id)) { Bitrix\Main\Diag\Debug::writeToFile('Product #'.$product_id.' isset offers!'); //Get offers $obOffersList = \CIBlockElement::GetList( array(), array( 'IBLOCK_ID' => $iblock_id, "PROPERTY_CML2_LINK" => $product_id, //'CATALOG_AVAILABLE' => 'Y' ), false, false, array("ID", "CATALOG_QUANTITY") ); while ($arOffers = $obOffersList->Fetch()) { Bitrix\Main\Diag\Debug::writeToFile(array("OFFER_ID"=>$arOffers['ID'], "CATALOG_QUANTITY"=>$arOffers['CATALOG_QUANTITY'])); $quantity_summ += $arOffers['CATALOG_QUANTITY']; } }else{//If is not isset offers Bitrix\Main\Diag\Debug::writeToFile('Product #'.$product_id.' is not offers!'); //Get product $obProductsList = \CIBlockElement::GetList( array(), array( 'IBLOCK_ID' => IBLOCK_ID_PRODUCTS, "ID" => $product_id, ), false, false, array("ID", "CATALOG_QUANTITY") ); while ($arProduct = $obProductsList->Fetch()) { Bitrix\Main\Diag\Debug::writeToFile(array("PRODUCT_ID"=>$arProduct['ID'], "CATALOG_QUANTITY"=>$arProduct['CATALOG_QUANTITY'])); $quantity_summ += $arProduct['CATALOG_QUANTITY']; } } \CIBlockElement::SetPropertyValuesEx($product_id, false, array('SORTAVAIL' => $quantity_summ)); Bitrix\Main\Diag\Debug::writeToFile(['PRODUCT_ID'=>$product_id, 'SORTAVAIL'=> $quantity_summ]); }else{ return false; } } } |
----------- CRON /local/updProdSortavail/index.php -----------
<?php if (php_sapi_name() !== 'cli') { header('HTTP/1.1 404 Not Found'); echo '404 Not Found.'; exit; } error_reporting(E_ALL); $_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/. ./.."); $DOCUMENT_ROOT = realpath(dirname(__FILE__)."/. ./.."); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php"); @set_time_limit(0); @ignore_user_abort(true); Bitrix\Main\Diag\Debug::writeToFile(date('Y.m.d mm:ss:hh').' Update product prop SORTAVAIL cron:'); if(CModule::IncludeModule("iblock")) { $arFilter = array( 'IBLOCK_ID' => IBLOCK_ID_PRODUCTS, 'ACTIVE' => 'Y', //'=PROPERTY_SORTAVAIL_VALUE' => false //'ID' => 34419 //38774 //простой 34419 ); $obProducts = \CIBlockElement::GetList( array(), $arFilter, false, array("nTopCount"=>100), array("ID", "PROPERTY_SORTAVAIL") ); while ($arProduct = $obProducts->Fetch()) { $product_id = $arProduct['ID']; $IBlockHandler = new IBlockHandler; $IBlockHandler->updateProductSortAvail(IBLOCK_ID_PRODUCTS_OFFERS, null, $product_id); } } ?> |
Кто что думает по этому поводу отпишитесь плз!