События отчёта остатков по складам
На более ранних версиях события не вызываются: запрос отчёта строится только настройками модуля, а строки отчёта, кроме товаров и модификаций, пропускаются без сигнала.
Агент «Остатки по складам» забирает из МойСклад отчёт /report/stock/bystore постранично и раскладывает его строки по товарам и модификациям каталога. Два события дают встроиться в этот путь:
- OnBuildStocksReportParams — изменить параметры запроса отчёта, например включить группировку по партиям;
- OnStocksRowSkipped — получить строку отчёта, которую модуль сам не разбирает, например остаток партии.
Вместе они позволяют разобрать остатки партий своим кодом, не запрашивая тот же отчёт у МойСклад второй раз.
Оба события срабатывают при работе агента «Остатки по складам» и при разовом импорте остатков по складам. Быстрые (текущие) остатки и импорт по веб-хуку их не вызывают.
[OnBuildStocksReportParams] Параметры запроса отчёта остатков
Событие вызывается перед каждым запросом страницы отчёта. Обработчик получает параметры, которые модуль собрал сам, и может добавить свои или заменить значения.
Без обработчиков запрос уходит ровно таким, каким его собрал модуль, — без groupBy.
Ответы обработчиков применяются по очереди регистрации, ключ за ключом: два обработчика, трогающие разные параметры, не затирают друг друга. Обратная сторона — снять параметр, поставленный модулем или другим обработчиком, ответом нельзя.
limit, offset и groupByОбработчик может переписать любой параметр, включая пагинацию агента. Постоянное значение offset заставит агент бесконечно читать одну и ту же страницу.
groupBy тоже меняет то, что увидит модуль:
| Значение | Что вернёт МойСклад | Что это значит для модуля |
|---|---|---|
не задан (по умолчанию) или variant | товары и модификации | штатная работа |
product | только товары | остатки модификаций перестанут обновляться |
consignment | товары, модификации и партии | партии уходят в OnStocksRowSkipped; строк в отчёте больше, поэтому страниц у агента тоже больше |
- Описание события
- Пример вызова события
Параметры события
| Параметр | Тип | Описание |
|---|---|---|
params | array | Параметры запроса /report/stock/bystore, собранные модулем: limit, offset, filter |
Возвращаемое значение
EventResult::SUCCESS с ключом params — параметрами, которые нужно добавить или заменить:
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'params' => ['groupBy' => 'consignment'],
]);
Возвращать все параметры не обязательно — достаточно тех, что меняете.
Когда ответ не применяется
Ответ отбрасывается целиком, и параметры остаются прежними, если:
- тип результата не
EventResult::SUCCESS; - нет ключа
paramsили в нём не массив; - хотя бы один ключ в
paramsне непустая строка или хотя бы одно значение не скаляр (массив, объект).
Исключение из обработчика модуль перехватывает молча: ответы обработчиков, зарегистрированных до него, применяются, обработчики после него не вызываются, агент продолжает работу.
//Пример кода нужно вставить в файл init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'rbs.moyskladstocks',
'OnBuildStocksReportParams',
'OnBuildStocksReportParamsHandler'
);
function OnBuildStocksReportParamsHandler(\Bitrix\Main\Event $event)
{
// $params — то, что модуль отправит в /report/stock/bystore:
// [
// 'limit' => 500,
// 'offset' => 0,
// 'filter' => 'stockMode=all;productFolder=https://api.moysklad.ru/api/remap/1.2/entity/productfolder/...',
// ]
// Фильтр по группе и по доп. полю добавляются, только если включены в настройках остатков.
// Меняя filter, возвращайте строку целиком: значение заменяется, а не дописывается.
$params = $event->getParameter('params');
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'params' => [
'groupBy' => 'consignment',
],
]);
}
[OnStocksRowSkipped] Строка отчёта, которую модуль не разбирает
Модуль раскладывает по каталогу только строки отчёта с типом product и variant. Строка любого другого типа — например партия (consignment), которая появляется в отчёте только при groupBy=consignment, — не импортируется, как и раньше, но теперь отдаётся вашему коду событием OnStocksRowSkipped.
Событие вызывается на каждую такую строку каждой страницы отчёта. Держите обработчик лёгким: при группировке по партиям строк может быть много.
Событие информационное: результат обработчика не читается. Исключение из обработчика модуль перехватывает молча, и разбор отчёта продолжается.
В каталог пропущенная строка не импортируется, но в HL-кеш остатков модуля она записывается, как и все строки страницы: кеш обновляется до разбора строк по типам и до вызова события. При группировке по партиям в кеше появятся записи с href партий — учитывайте это, если читаете кеш своим кодом.
- Описание события
- Пример вызова события
- Примеры использования
Параметры события
| Параметр | Тип | Описание |
|---|---|---|
row | object | Строка отчёта целиком — так, как её вернул МойСклад |
type | string | Тип строки из row->meta->type, например consignment. Пустая строка, если тип не указан |
Структура строки — по документации отчёта «Остатки по складам» МойСклад:
$row->meta->href // ссылка на сущность: партию, товар, модификацию
$row->meta->type // 'consignment'
$row->stockByStore // массив остатков по складам:
// [
// (object)[
// 'meta' => (object)['href' => '.../entity/store/...'],
// 'name' => 'Основной склад',
// 'stock' => 10,
// 'reserve' => 2,
// 'inTransit' => 0,
// ],
// ]
Возвращаемое значение
Ничего возвращать не нужно.
//Пример кода нужно вставить в файл init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'rbs.moyskladstocks',
'OnStocksRowSkipped',
'OnStocksRowSkippedHandler'
);
function OnStocksRowSkippedHandler(\Bitrix\Main\Event $event)
{
$type = $event->getParameter('type'); // тип строки отчёта
$row = $event->getParameter('row'); // строка отчёта МойСклад
if ($type !== 'consignment') {
return;
}
#WORK_AREA#
}
Остатки партий в свою таблицу
Первый обработчик включает группировку по партиям, второй складывает остатки партий к себе. Товары и модификации модуль при этом обновляет как обычно.
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->addEventHandler('rbs.moyskladstocks', 'OnBuildStocksReportParams', static function () {
return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS, [
'params' => ['groupBy' => 'consignment'],
]);
});
$eventManager->addEventHandler('rbs.moyskladstocks', 'OnStocksRowSkipped', static function (\Bitrix\Main\Event $event) {
if ($event->getParameter('type') !== 'consignment') {
return;
}
$row = $event->getParameter('row');
foreach ((array)($row->stockByStore ?? []) as $storeStock) {
// Хранение — на стороне разработчика
YourConsignmentStocks::save(
(string)$row->meta->href,
(string)$storeStock->meta->href,
(float)$storeStock->stock
);
}
});