Почему при обмене с сайтом выгружаются товары с нулевым остатком, несмотря на установленные отборы?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Проблема некорректной выгрузки остатков при обмене 1С с интернет-магазином (чаще всего на базе Bitrix) является классической задачей для разработчика. Часто возникает ситуация: в настройках обмена или в коде установлен отбор «Остаток > 0», но на сайт все равно попадают позиции, которых давно нет в наличии. В этой статье мы подробно разберем, почему стандартные фильтры могут не срабатывать, как устроена внутренняя логика формирования пакетов import.xml и offers.xml, и как правильно модифицировать код, чтобы добиться желаемого результата.

Анализируем архитектуру обмена CommerceML

Для начала нам необходимо понять, как именно данные уходят из 1С. Стандартный обмен по протоколу CommerceML разделен на два ключевых этапа (два пакета данных):

  1. Пакет каталога (import.xml): Здесь передается информация о самой номенклатуре: наименования, свойства, иерархия групп, описания и картинки.
  2. Пакет предложений (offers.xml): В этом файле передаются коммерческие условия: цены и остатки в разрезе складов и характеристик.

Проблема автора темы заключается в том, что он пытается наложить фильтр по количеству только в процедуре ПолучитьДанныеДляВыгрузкиПакетаПредложений. Рассмотрим, к чему это приводит: товар проходит через фильтры каталога и попадает в import.xml. Сайт создает карточку товара. Затем, при формировании offers.xml, срабатывает фильтр «Количество > 0», и данные об остатках для этого товара просто не попадают в файл. Сайт, не получив новых данных о количестве, может либо оставить старое значение, либо отобразить товар с «пустым» остатком, но сама карточка товара останется активной. Чтобы товар исчез с сайта, его нужно либо исключить из обоих пакетов, либо выгрузить с остатком 0 и настроить сайт на скрытие таких позиций.

Разбор программного формирования СКД для выгрузки

Проанализируем код из первого сообщения, где используется схема компоновки данных (СКД) для получения данных. Разработчик программно создает наборы данных и связи между ними. Рассмотрим этот фрагмент подробнее:


// Создание программной связи наборов данных
СвязиНаборов = СхемаКомпоновкиДанных.СвязиНаборовДанных;

НоваяСвязь = СвязиНаборов.Добавить();
НоваяСвязь.НаборДанныхИсточник  = "Цены";
НоваяСвязь.НаборДанныхПриемник  = "Остатки";
НоваяСвязь.ВыражениеИсточник    = "Номенклатура";
НоваяСвязь.ВыражениеПриемник    = "Номенклатура";

Здесь кроется важный нюанс: при программном объединении таблиц «Цены» и «Остатки» через СКД часто используется механизм, аналогичный ЛЕВОМУ СОЕДИНЕНИЮ. Если в таблице цен номенклатура есть, а в таблице остатков ее нет (остаток равен нулю и запись в регистре отсутствует), компоновщик все равно выведет строку с номенклатурой, но с пустым значением количества. Если отбор накладывается на результат этой компоновки, он может игнорироваться, если само поле количества не выбрано в итоговые поля или если логика компоновщика настроена на обязательный вывод родительских записей (номенклатуры).

Чтобы решить эту проблему на уровне запроса, нам нужно убедиться, что отбор по количеству применяется к основному набору данных. Если мы используем внешние наборы данных (Таблицы Значений), как в примере, то перед передачей их в ПроцессорКомпоновкиДанных следует предварительно очистить их от строк с нулевыми остатками.

Проблема фильтрации в цикле формирования XDTO

Рассмотрим попытку решения проблемы через модификацию цикла формирования XML-пакета (сообщение №7). Автор пытается использовать оператор Продолжить, если остаток меньше или равен нулю:


Для Каждого СтрокаОстаткиПоСкладам Из ТекСтрока.Остатки Цикл
    Если СтрокаОстаткиПоСкладам.ОстатокНаСкладе <= 0 ТОгда
        Продолжить;
    КонецЕсли;
    
    // Формирование XDTO объекта склада...
КонецЦикла;

Это критическая ошибка логики обмена. Рассмотрим ситуацию: вчера у товара был остаток 5, и он был выгружен на сайт. Сегодня товар продали, остаток стал 0. При запуске обмена (особенно в режиме «Выгружать только изменения») система видит, что товар изменился. Если в коде сработает Продолжить, то в файле выгрузки вообще не будет упоминания об этом товаре или его складах. Сайт, не найдя информации о складе в новом файле, просто ничего не изменит в своей базе и оставит остаток 5.

Правильное решение: Для корректного обнуления данных на стороне сайта 1С ОБЯЗАНА отправить запись о товаре с количеством 0. Только тогда CMS сайта поймет, что товара нет в наличии, и скроет его (при соответствующих настройках со стороны сайта).

Регистрация изменений и полная выгрузка

Разберем разницу между режимами обмена, так как это напрямую влияет на работу отборов. В планах обмена 1С регистрируются ссылки на объекты, которые были изменены.

Для того чтобы «вычистить» сайт от старого мусора, необходимо один раз запустить полную выгрузку после внесения правок в код. Однако помните: если вы полностью исключите товар из выгрузки (через фильтр в СКД), сайт может не удалить его автоматически, так как он просто не увидит его в файле. В настройках модуля обмена на стороне сайта (Bitrix) нужно найти параметр: «Что делать с товарами, отсутствующими в файле импорта?». Установите значение «Деактивировать» или «Удалять».

Пошаговое решение проблемы

Проанализировав ситуацию, мы можем составить алгоритм правильной настройки исключения товаров с нулевым остатком:

  1. Фильтрация в Каталоге (import.xml): Если мы не хотим, чтобы товар вообще присутствовал на сайте, его нужно отсечь на этапе формирования ТаблицаЦены в процедуре ПолучитьДанныеДляВыгрузкиПакетаПредложений. Это делается либо через настройки типового отбора в узле обмена, либо через модификацию текста запроса.
  2. Передача нулевых остатков: Не используйте Продолжить при нулевом остатке в цикле формирования XDTO. Вместо этого позволяйте системе выгрузить Количество = 0. Это гарантирует актуализацию данных на сайте.
  3. Очистка Плана Обмена: Если вы изменили логику отбора, рекомендуется сбросить регистрацию изменений для узла обмена, чтобы при следующем сеансе «только изменений» система не тянула хвосты старых данных. Для этого используйте типовую обработку «Регистрация изменений для обмена».
  4. Настройка СКД: Проверьте тип соединения в вашей схеме компоновки. Если вы используете программную схему, убедитесь, что отбор по полю ОстатокНаСкладе наложен корректно и поле доступно для обработки процессором компоновки.

Рассмотрим пример правильной настройки условия в запросе для получения данных остатков:


ВЫБРАТЬ
    Остатки.Номенклатура,
    Остатки.КоличествоОстаток КАК ОстатокНаСкладе,
    Остатки.Склад
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&МоментВремени, ) КАК Остатки
ГДЕ
    Остатки.КоличествоОстаток > 0

Использование ГДЕ Остаток > 0 непосредственно в запросе к регистру является наиболее эффективным способом, так как это уменьшает объем передаваемых данных еще до этапа компоновки и формирования XML. Однако помните о необходимости выгрузки «нулей» для тех товаров, которые стали нулевыми недавно.

Выясняем причины, почему «отбор работает только если установить конкретную номенклатуру»

В Сообщении 0 автор упоминает, что отбор по конкретной номенклатуре работает, а по остатку — нет. Это происходит потому, что отбор по ссылке (Номенклатура) является жестким и понятным для СКД на любом этапе. Отбор же по ресурсу (Остаток) в виртуальных таблицах или связанных наборах данных может вести себя иначе. Если Остаток является вычисляемым полем или ресурсом в СКД, то фильтр может применяться уже ПОСЛЕ того, как выборка сформирована (в процессе вывода), что при определенных настройках группировок выдает неверный результат.

Подводя итог, можно сказать: для корректного обмена с сайтом важно синхронизировать настройки отборов в 1С и логику обработки отсутствующих товаров на стороне CMS. Использование программных фильтров в коде Продолжить; чаще всего вредит обмену, «замораживая» неактуальные остатки на сайте.

← На главную