Ошибка при добавлении комплекта в Битрикс

Отчаяние

Многие интересуются, почему стоимость разработки сайта на Битрикс в среднем в два раза выше чем на других CMS, ведь там уже все сделано, надо только настроить. Проблема заключается в том, что Битрикс хорошо работает только с готовыми шаблонными решениями, а бизнес, как правило, в шаблоны не укладывается. Всегда требуются доработки логики и, казалось бы, Битрикс предоставляет разработчику такие возможности, но это как прогулка по минному полю: если повезет, то ты пройдешь, но это не точно.

Яркий пример произошел буквально пару дней назад: Заказчику необходима кастомная реализация добавления комплектов. Идем в документацию и находим:
https://dev.1c-bitrix.ru/api_help/catalog/classes/ccatalogproductset/add.php
CCatalogProductSet::add($arFields);
где arFields - Ассоциативный массив параметров с ключами:

  • ITEM_ID - идентификатор товара-владельца
  • TYPE - комплект/набор
  • ITEMS - массив(массив элементов) Для каждого элемента:
    • ITEM_ID - идентификатор товара входящего в комплект/набор
    • QUANTITY - множитель единицы измерения товара,
    • SORT - сортировка внутри сущности

Вроде, все просто. Создаем товар типа «Комплект», формируем нужный массив и запрашиваем добавление. Вуаля! Получаем ошибку:

Проверяем: родительский товар — комплект, добавляемые товары являются простыми. Бах! Поздравляю: мы подорвались на Битрикс-мине!
Лезем в исходники и начинаем разбираться, что происходит.

Ошибка в функции проверки валидности передаваемых товаров checkFieldsToAdd (файл bitrix\modules\catalog\general\product_set.php:214). На строке 267 в массив проверяемых идентификаторов включается идентификатор родительского товара-комплекта, к которому мы добавляем комплект:
if (0 < $arFields['ITEM_ID']) $arProductInSet[$arFields['ITEM_ID']] = true;

Этот идентификатор не должен проверяться, т.к. это родительский товар, который в CMS обозначен как "Комплект", и на строке 339 того же файла этот идентификатор из проверки исключается. Всё верно, но! Исключается он только для товара вида "Набор":
if ($arFields['TYPE'] == self::TYPE_GROUP)
{
    $checkProductList = $arProductInSet;
    if ($arFields['ITEM_ID'] > 0)
        unset($checkProductList[$arFields['ITEM_ID']]);
    $checkProductList = array_keys($checkProductList);
}

Решение очень простое:

При добавлении товара-родителя не надо указывать для него тип "Комплект" - мы должны добавлять комплект к простому товару, который автоматически после этого станет Комплектом в интерфейсе администратора и на сайте.

Никаких проверок, является ли родительский товар комплектом, Битрикс не производит, поэтому пока что ошибку (фичу?) можно обойти таким образом.

Кстати, при обновлении такой проблемы не возникает, потому что в этом же файле на строке 546 прописано удаление идентификатора родительского товара из списка проверяемых:
if (isset($arProductInSet[$arCurrent['ITEM_ID']]))
    unset($arProductInSet[$arCurrent['ITEM_ID']]);

Как это должно быть сделано и в функции добавления.