Обнулить все остатки для товаров определенных разделов
Если вы хотите вывести из каталога определенные товары, но так, чтобы они остались доступными по ссылкам (для SEO) без возможности заказа. То вам нужно обнулить остатки для таких товаров. И проверить их активность. Данный скрипт позволяет это сделать в один проход. Укажите правильный id инфоблока каталога, а также id нужных разделов, которые планируете отключать. При необходимости можно перенастроить логику работы скрипта, чтобы выбирать товары по каким-то еще критериям.
Отдельно в настройках модуля "интернет-магазина" можно включить подписку на такие товары (недоступные к заказу), чтобы анализировать спрос на них
Также ранее уже выкладывали сниппет, как найти на сайте все товары с нулевыми остатками: https://wpso.ru/snip--19537
// Настройки
$sectionIds = [260, 253, 208]; // Массив ID разделов для обработки
$iblockId = 22; // ID инфоблока каталога
$activateElements = true; // Активировать товары (true/false)
$setZeroQuantity = true; // Обнулять остатки (true/false)
// Увеличиваем лимиты
set_time_limit(0);
ini_set('memory_limit', '2048M');
// Проверяем модули
if (!CModule::IncludeModule('catalog') || !CModule::IncludeModule('iblock')) {
die("Не удалось подключить модули catalog или iblock\n");
}
// Функция для получения всех подразделов
function getAllSubsections($iblockId, $parentIds) {
$all = [];
foreach ($parentIds as $parentId) {
$res = CIBlockSection::GetList(
['LEFT_MARGIN' => 'ASC'],
['IBLOCK_ID' => $iblockId, 'SECTION_ID' => $parentId],
false,
['ID']
);
while ($section = $res->Fetch()) {
$all[] = $section['ID'];
$all = array_merge($all, getAllSubsections($iblockId, $section['ID']));
}
}
return array_unique($all);
}
// Получаем все разделы для обработки
$allSectionIds = array_merge($sectionIds, getAllSubsections($iblockId, $sectionIds));
echo "Обрабатываем разделы: ".implode(', ', $allSectionIds)."\n";
// Фильтр для товаров
$filter = [
'IBLOCK_ID' => $iblockId,
'SECTION_ID' => $allSectionIds,
'INCLUDE_SUBSECTIONS' => 'Y',
'CHECK_PERMISSIONS' => 'N'
];
// Подсчет товаров
$totalProducts = CIBlockElement::GetList([], $filter, []);
echo "Всего товаров для обработки: {$totalProducts}\n\n";
// Обработка товаров
$pageSize = 500;
$pages = ceil($totalProducts / $pageSize);
$processed = 0;
for ($page = 1; $page <= $pages; $page++) {
$rsElements = CIBlockElement::GetList(
['ID' => 'ASC'],
$filter,
false,
['nPageSize' => $pageSize, 'iNumPage' => $page],
['ID', 'ACTIVE']
);
echo "Страница {$page}/{$pages}: ";
$cnt = 0;
while ($element = $rsElements->Fetch()) {
$cnt++;
$elementId = $element['ID'];
// Активация товара
if ($activateElements && $element['ACTIVE'] != 'Y') {
$el = new CIBlockElement;
$el->Update($elementId, ['ACTIVE' => 'Y']);
}
// Обновление остатков
if ($setZeroQuantity) {
$productInfo = CCatalogProduct::GetByID($elementId);
if ($productInfo) {
CCatalogProduct::Update($elementId, [
'QUANTITY' => 0,
'QUANTITY_TRACE' => 'Y',
'CAN_BUY_ZERO' => 'N'
]);
} else {
CCatalogProduct::Add([
'ID' => $elementId,
'QUANTITY' => 0,
'QUANTITY_TRACE' => 'Y',
'CAN_BUY_ZERO' => 'N'
]);
}
}
}
$processed += $cnt;
echo "обработано {$cnt} товаров\n";
}
// Обновление кешей
if ($setZeroQuantity) {
$iterator = CIBlockElement::GetList([], $filter, false, false, ['ID']);
while ($element = $iterator->Fetch()) {
CPrice::GetBasePrice($element['ID']);
}
}
// Итоги
echo "\nОбработка завершена:\n";
echo "Всего товаров: {$totalProducts}\n";
echo "Обработано: {$processed}\n";
echo "Активировано: ".($activateElements ? $processed : 'N/A')."\n";
echo "Обнулено остатков: ".($setZeroQuantity ? $processed : 'N/A')."\n";

