Событие подстановки элементов для цен и остатков
[OnAfterFindElementsForStocks] Свои элементы каталога для цен и остатков
На более ранних версиях событие не вызывается: цены и остатки записываются только в элементы, которые модуль нашёл сам.
Перед записью цен и остатков модуль ищет элементы каталога по внешним кодам сущностей МойСклад (XML_ID). Событие OnAfterFindElementsForStocks вызывается сразу после этого поиска и позволяет дописать к найденному свои элементы: из другого инфоблока, с другим форматом XML_ID, несколько элементов на одну сущность МойСклад — например, когда товар МойСклад на сайте представлен торговыми предложениями.
Добавленные элементы модуль не выделяет особо: для него это дубли — несколько элементов за одним внешним кодом. Куда в итоге запишутся цены и остатки, решает настройка «Тип обработки дублей».
Настройка «Тип обработки дублей» задаётся отдельно для каждого пайплайна:
- вкладка «Цены» — в блоке каждой сущности (товары, модификации, услуги, комплекты);
- вкладка «Остатки» — для товаров, модификаций и комплектов;
- вкладка «Быстрые остатки» — одна на вкладку.
Как значения настройки обходятся с набором элементов:
| Значение | Что получит значение из МойСклад |
|---|---|
[ASC] Импортировать в первый по ID товар (по умолчанию) / [DESC] Импортировать в последний по ID товар | Только первый элемент набора. Найденные модулем идут первыми (по возрастанию или убыванию ID), добавленные — после них. Если модуль нашёл хоть что-то, добавленные элементы игнорируются; если не нашёл ничего — значение получит только первый из добавленных |
[ALL] Импортировать во все товары | Все элементы набора — и найденные модулем, и добавленные |
[SKIP] Пропускать дубли при импорте | Внешний код отбрасывается целиком, если за ним больше одного элемента — не получит значение даже элемент, найденный модулем |
Чтобы событие работало, выставьте [ALL] Импортировать во все товары в тех пайплайнах, где вы добавляете элементы. Учтите, что режим распространяется и на настоящие дубли в каталоге: значение получат все элементы с одинаковым внешним кодом.
Предупреждение о дублях в логе импорта считает и добавленные элементы — при работе события оно ожидаемо.
В каких пайплайнах срабатывает
| Пайплайн | Значение target |
|---|---|
| Запись цен — агент цен, разовый импорт, цены при импорте товаров и по веб-хуку | prices |
| Остатки по складам — агент, разовый импорт, обновление по веб-хуку | stocks |
| Быстрые (текущие) остатки — агент, разовый импорт, обновление по веб-хуку | current_stocks |
Событие приходит и тогда, когда модуль не нашёл ничего: found в этом случае пустой массив.
Всё, что нашёл модуль, остаётся в наборе при любом ответе обработчика. Пропущенный в ответе внешний код, пропущенный элемент внутри кода, пустой found — ничего из найденного модулем не убирают. Исключить элемент из импорта цен и остатков через это событие нельзя.
- Описание события
- Пример вызова события
- Примеры использования
Параметры события
| Параметр | Тип | Описание |
|---|---|---|
entity | string | Сущность МойСклад: product, variant, bundle, service |
target | string | Пайплайн: prices, stocks, current_stocks |
xmlIds | array | Внешние коды, которые искал модуль |
found | array | Что модуль нашёл: [внешний код => [ID элемента => '', ...], ...] |
Структура found
[
'abc123externalcode' => [
1234 => '', // ID элемента инфоблока — в ключе, значение не используется
1240 => '', // дубль с тем же внешним кодом
],
// ...
]
Возвращаемое значение
EventResult::SUCCESS с ключом found в той же форме. Возвращать весь набор не обязательно — достаточно того, что добавляете:
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'found' => [
'abc123externalcode' => [5678 => '', 5679 => ''],
],
]);
Ключи found берите из xmlIds: цены и остатки модуль знает только для тех сущностей, которые искал.
Что отбрасывается
- ответ с типом, отличным от
EventResult::SUCCESS, и ответ без массива вfound; - внешний код с пустым именем или с не-массивом вместо списка элементов;
- ID элемента, который не целое число или не больше нуля.
Для остатков (stocks) и быстрых остатков (current_stocks) элемент должен быть товаром каталога — иметь запись в b_catalog_product. Добавленные элементы без неё отбрасываются уже после события; в логе об этом только общее предупреждение о расхождении числа товаров и элементов инфоблока, без ID.
Исключение из обработчика модуль перехватывает молча: ответы обработчиков, зарегистрированных до него, применяются, обработчики после него не вызываются, импорт продолжается.
//Пример кода нужно вставить в файл init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'rbs.moyskladstocks',
'OnAfterFindElementsForStocks',
'OnAfterFindElementsForStocksHandler'
);
function OnAfterFindElementsForStocksHandler(\Bitrix\Main\Event $event)
{
$entity = $event->getParameter('entity'); // product / variant / bundle / service
$target = $event->getParameter('target'); // prices / stocks / current_stocks
$xmlIds = $event->getParameter('xmlIds'); // что искал модуль
$found = $event->getParameter('found'); // что модуль нашёл
$add = [];
#WORK_AREA#
// $add['abc123externalcode'][5678] = '';
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'found' => $add,
]);
}
Цены товара — во все его торговые предложения на сайте
Товар МойСклад на сайте разложен на несколько торговых предложений со своими XML_ID вида <внешний код>#<суффикс>. Модуль находит только элемент с точным XML_ID, а обработчик дописывает к нему предложения. Чтобы цены получили и предложения, на вкладке «Цены» для товаров должен стоять тип обработки дублей [ALL] Импортировать во все товары.
function OnAfterFindElementsForStocksHandler(\Bitrix\Main\Event $event)
{
if ($event->getParameter('entity') !== 'product') {
return;
}
$add = [];
foreach ($event->getParameter('xmlIds') as $xmlId) {
$rsOffers = \Bitrix\Iblock\ElementTable::getList([
'filter' => [
'=IBLOCK_ID' => YOUR_OFFERS_IBLOCK_ID,
'XML_ID' => $xmlId . '#%',
],
'select' => ['ID'],
]);
while ($offer = $rsOffers->fetch()) {
$add[$xmlId][(int)$offer['ID']] = '';
}
}
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'found' => $add,
]);
}
Обработчик вызывается на каждую порцию импорта. Собирайте элементы одним запросом на порцию, а не запросом на каждый внешний код, если каталог большой.