Нулевые остатки не выгружаются из 1С в Битрикс: почему сайт продолжает продавать закончившийся товар
В 1С товар закончился, а сайт продолжает показывать наличие и принимать заказы. Разбираем, где теряется ноль: в отборе, CommerceML, предложениях, складах или настройках каталога.
В 1С товар закончился, обмен завершился без ошибки, но интернет-магазин продолжает показывать «в наличии» и принимает заказ. Такой сбой часто называют проблемой кеша или карточки товара. На деле это нарушение согласованности данных: сайт сохранил последнее положительное количество, потому что явный ноль не прошёл один из этапов обмена либо был записан не в ту сущность.
Диагностировать ситуацию лучше на одном товаре по контролируемой последовательности 5 → 1 → 0. Она позволяет увидеть точку, в которой перестаёт меняться значение: в самой 1С, в отборе объектов, в CommerceML, в каталоге Битрикса или уже на публичной странице.

Сначала зафиксируйте симптом
До изменения настроек выберите один проблемный товар и запишите факты. Нужны внешний код товара или предложения, артикул, склад, остаток в 1С, количество в административной части Битрикса, признак доступности на витрине и точное время последнего обмена. Для товара с характеристиками фиксируют конкретное предложение, например «размер M, белый», а не только название родительской карточки.
Эта фиксация отделяет разные симптомы, которые внешне выглядят одинаково:
- в 1С уже ноль, но объект вообще не вошёл в пакет обмена;
- в XML передан ноль, но импорт не обновил запись каталога;
- ноль записан в родительский товар, а покупается торговое предложение;
- в административной части количество равно нулю, но покупка при отсутствии разрешена;
- данные в каталоге верны, а компонент или кеш показывает прошлое состояние.
Не начинайте с прямой правки базы, массового обнуления и бесконечной очистки кеша. Эти действия могут временно скрыть проявление, но уничтожат данные, по которым определяется причина. Если обмен в целом нестабилен, сначала полезно пройти общий разбор ошибок обмена товарами между 1С и Битрикс, а затем сузить проверку до остатка.
Как нулевой остаток доходит до витрины
Количество проходит не один импорт, а цепочку решений. В 1С рассчитывается показатель, который считается доступным для сайта: фактический, свободный или другой проектный остаток. Затем правила обмена выбирают изменённые объекты. CommerceML передаёт товар, предложение и количество. Импорт сопоставляет внешний код с элементом каталога, записывает значение, пересчитывает доступность. Наконец, компонент каталога решает, какой вариант показать и можно ли добавить его в корзину.

Ключевое различие — отсутствие объекта в пакете и явное количество 0. Если товар при положительном остатке был выгружен со значением 5, а после продажи последней единицы исключён условием «остаток больше нуля», Битрикс не получает команды заменить 5 на 0. Для импортёра ничего не изменилось, и старое число остаётся допустимым состоянием.
Где чаще всего пропадает ноль
Товар исключается условием отбора
Самая характерная причина — фильтр, который разрешает выгружать только позиции с положительным количеством. Пока остаток равен 5 или 1, товар присутствует в обмене. После перехода к нулю он исчезает из выборки. Такое правило может находиться в настройках узла обмена, в пользовательском расширении, в коде обработки или в логике формирования регистрационных изменений.
Удалять фильтр вслепую не стоит: он мог сдерживать объём каталога или исключать архивные позиции. Нужно отдельно определить правило для уже известных сайту товаров: как передать им ноль, деактивировать или оставить доступными под заказ.
Изменение остатка не попадает в инкрементальную выгрузку
В режиме «только изменения» объект должен зарегистрироваться для обмена после движения товара, пересчёта регистра или изменения документа. Если регистрация настроена не на тот источник либо пользовательская логика её снимает, полная выгрузка может обновить количество, а короткая — нет. Это важный диагностический признак, но не готовое решение: постоянный полный обмен увеличивает время и нагрузку, не исправляя регистрацию изменений.
Проверяется родитель, хотя покупается предложение
У товара с цветом, размером или комплектацией реальными покупаемыми позициями обычно являются торговые предложения. Родитель объединяет их в карточку, но его собственное количество может не использоваться. Поэтому ноль у родителя не доказывает, что все варианты закончились, а положительное количество у одного предложения может сохранять доступность всей карточки.

Сопоставлять нужно по внешнему коду предложения, а не по названию карточки. Полезно также проверить привязку предложения к родителю: после изменения структуры характеристик импорт может создать новую запись, а шаблон продолжит показывать старую.
Смешиваются общий остаток и остатки по складам
Проект может хранить общее количество товара, отдельные значения по складам или использовать складской учёт. Ошибка возникает, когда 1С передаёт один показатель, импорт обновляет другой, а публичный компонент читает третий. Например, общий остаток стал нулевым, но в записи одного склада осталось старое значение; либо складские строки обновились, а пользовательский шаблон проверяет только поле общего количества.
Здесь нельзя механически суммировать все склады. Часть из них может быть закрыта для интернет-заказов, относиться к другому региону или хранить резерв. Сначала документируют бизнес-правило: какие склады участвуют в продаже и что именно означает доступное количество.
Резерв и свободный остаток трактуются по-разному
Физически на складе может быть две единицы, но обе зарезервированы заказами. Для сайта это ноль свободного остатка, хотя фактическое количество положительное. Обратная ситуация появляется после отмены или непроведённого документа. Если стороны используют разные формулы, обмен технически передаёт число корректно, но оно не соответствует ожидаемому смыслу.
Пользовательский обработчик игнорирует ноль
В собственном импорте встречается условие вида if ($quantity) { ... }. Для PHP ноль является ложным значением, поэтому ветка обновления не выполняется. Подобная ошибка может быть в обработчике события, промежуточном массиве, REST-интеграции или очереди. Проверка должна отличать «поле отсутствует» от «поле присутствует и равно 0» — например, через явную проверку ключа и числового значения.
Проверьте CommerceML до Битрикса
Лучший способ разделить ответственность — сохранить пакет обмена или выполнить выгрузку в файл на тестовой копии. В файлах ищут не видимое название, а внешний идентификатор выбранного товара или предложения. Названия могут повторяться и меняться, тогда как внешний код используется для сопоставления.
Сравните два пакета: когда у тестовой позиции была единица и когда стало ноль. Проверьте, присутствует ли объект во втором пакете, есть ли узел количества, к какому предложению он относится и передаются ли складские значения. Формат и набор узлов зависят от версии CommerceML и настроек обмена, поэтому надёжнее сравнивать фактические файлы одного проекта, а не искать универсальную строку из чужой инструкции.
Если во втором пакете объект отсутствует, исправление ищут на стороне отбора и регистрации изменений. Если объект и явный ноль присутствуют, переходят к журналу импорта и обработчикам Битрикса. Сам по себе статус «обмен завершён» означает, что протокол выполнился, но не подтверждает изменение каждой позиции.
Почему товар с количеством 0 остаётся доступным
В Битриксе число и возможность покупки — связанные, но не одинаковые параметры. В официальной документации ProductTable::calculateAvailable указано, что флаг доступности рассчитывается с учётом QUANTITY, QUANTITY_TRACE и CAN_BUY_ZERO. Поэтому количество 0 не запрещает заказ автоматически, если количественный учёт выключен или разрешена покупка при отсутствии.
Проверяйте фактические значения у покупаемой сущности:
QUANTITY— записанное количество;QUANTITY_TRACE— участвует ли количество в ограничении покупки;CAN_BUY_ZERO— разрешён ли заказ при нуле;AVAILABLE— рассчитанный признак доступности.
Значение «по умолчанию» может наследовать общую настройку модуля, поэтому визуальная проверка одной карточки не всегда достаточна. Официальное описание доступности товара и возможности покупки также разделяет простые товары, предложения и родительские SKU. После корректного изменения параметров система должна пересчитать доступность штатным API; прямое обновление таблицы этого не гарантирует.
Безопасная диагностика по сценарию 5 → 1 → 0
Создайте отдельный тестовый SKU или выберите позицию, которую нельзя случайно купить. Проведите три последовательных состояния и после каждого запустите тот же тип обмена, который работает по расписанию. На каждом этапе запишите время и значения в пяти контрольных точках.

- 1С: внешний код, характеристика, склад, фактический и свободный остаток.
- CommerceML: наличие объекта, переданное количество и складские узлы.
- Каталог: найденный по внешнему коду товар или предложение, количество, склады и доступность.
- Публичная карточка: текст наличия, список вариантов и кнопка покупки в анонимном режиме.
- Корзина: серверный результат добавления конкретного SKU, а не только состояние кнопки.
После каждого шага меняйте только один фактор. Если одновременно снять фильтр, включить количественный учёт и очистить все кеши, результат может стать правильным, но причина останется неизвестной. При следующем обновлении или новом складе ошибка вернётся.
Как обнаруживать зависшие остатки автоматически
Ручной прогон нужен для расследования, но рабочий магазин не должен ждать жалобы покупателя. В обмене полезно журналировать не весь XML целиком, а контрольные показатели каждой сессии: идентификатор запуска, тип пакета, время начала и завершения, число обработанных товаров и предложений, количество записей с явным нулём, число ошибок и внешние коды отклонённых объектов. Такой журнал компактнее архива всех файлов и сразу показывает аномалию: например, вчера передавались десятки обнулений, а сегодня при сопоставимом объёме — ни одного.
Дополнительная проверка сравнивает данные по нескольким выбранным SKU после завершения импорта. Для каждого хранится ожидаемое состояние из пакета и фактическое состояние каталога. Если пакет содержал количество 0, а через несколько минут у предложения всё ещё положительный QUANTITY или разрешена покупка, мониторинг создаёт техническое событие. Важно проверять именно серверную возможность покупки: надпись «нет в наличии» может быть верной, пока старый URL добавления в корзину продолжает принимать товар.
Полезна и периодическая сверка «долго не менявшихся» остатков. Она ищет позиции, у которых дата последнего успешного обмена заметно старше обычного интервала, хотя продажи или движения в 1С продолжались. Это не означает, что все такие товары ошибочны, но даёт короткий список для проверки вместо просмотра всего каталога.
Хранить журналы нужно ограниченное время и без персональных данных заказов. Для расследования остатка достаточно технических идентификаторов, количества, результата шага и времени. Если обмены критичны для продаж, мониторинг включают в регламент поддержки интернет-магазина: проверяют не только факт запуска задания, но и содержательный результат импорта.
Что исправлять в зависимости от результата
- Ноль не рассчитан в 1С. Уточнить формулу доступного остатка, проведение документов и учёт резервов.
- Ноль есть в 1С, но объекта нет в XML. Проверить отбор положительных остатков и регистрацию изменений.
- Ноль есть в XML, но не в каталоге. Изучить журнал импорта, сопоставление внешнего кода и пользовательские обработчики.
- Обновлён родитель, предложения не изменились. Исправить выгрузку характеристик и связь товара с предложениями.
- Складские остатки верны, общее количество нет. Согласовать режим складского учёта и источник, который читает витрина.
- В каталоге ноль, но заказ разрешён. Проверить количественный учёт, покупку при отсутствии и пересчёт
AVAILABLE. - Административные данные верны, витрина старая. Проверить кеш компонента, шаблон и выбор конкретного предложения.
Если требуется правка интеграции, безопаснее вынести её в расширение или локальный обработчик и покрыть контрольным сценарием. Не стоит изменять модуль обмена 1С или ядро Битрикса: обновление перезапишет правку, а расследовать повторный сбой будет сложнее. Для проектов с несколькими каналами продаж полезна отдельная настройка и сопровождение интеграций с журналированием ключевых этапов.
Чего не делать
- не обнулять
b_catalog_productпрямым SQL-запросом; - не считать отсутствие товара в частичном пакете командой деактивации;
- не отключать все товары, которые не встретились в одном обмене;
- не править код штатного модуля обмена без проверки версии и обновлений;
- не очищать весь кеш как основное решение;
- не тестировать на популярном товаре рабочего магазина.
Особенно опасно деактивировать всё отсутствующее в пакете. Частичная выгрузка по определению может содержать только изменённые позиции. Такое «исправление» превратит один неверный остаток в массовое исчезновение каталога. Перед любым автоматическим правилом нужны признак полного пакета и понятная политика жизненного цикла товара.
Когда нужен разработчик
Разработчик нужен, если ноль присутствует в CommerceML, но не записывается; полная и частичная выгрузки ведут себя по-разному; остатки зависят от нескольких складов и резервов; используются собственные обработчики; проблема появляется только у части предложений или возвращается после обновления.
Работа начинается с воспроизводимого примера и трассировки одного внешнего кода. Затем проверяются пакет, импорт, события, модель товара и серверная попытка добавления в корзину. Такой технический аудит 1С-Битрикс быстрее случайной замены настроек. Если ошибка уже мешает продажам, подходит диагностика и исправление ошибок; для регулярного контроля обменов — поддержка интернет-магазина на 1С-Битрикс.
FAQ
Полная выгрузка решит проблему нулевого остатка?
Она может временно обновить количество и подтвердить, что импорт умеет принимать ноль. Но если причина в регистрации изменений, следующий частичный обмен снова оставит старое значение. Полную выгрузку используют как диагностический тест, а не как постоянную замену исправлению.
Можно ли считать отсутствующий в XML товар нулевым?
Только если протокол проекта явно помечает пакет как полный и стороны заранее согласовали такое правило. В частичном обмене отсутствие обычно означает «данные об этом объекте не передавались», поэтому автоматически обнулять или деактивировать его опасно.
Нужно ли деактивировать товар при нулевом остатке?
Не обязательно. Товар можно оставить для SEO, подписки о поступлении или заказа под поставку. Важно отдельно настроить видимость карточки и возможность покупки. Политика должна быть единой для простых товаров и предложений.
Почему в административной части ноль, а карточка пишет «в наличии»?
Проверьте, у какой сущности открыт остаток, разрешена ли покупка при отсутствии, включён ли количественный учёт, какой вариант выбрал компонент и не отдаётся ли старый кеш. Для SKU ноль у родителя не равен нулю у всех предложений.
Как найти нужную позицию в CommerceML?
Используйте внешний код товара или предложения и сравнивайте пакеты для положительного и нулевого состояния. Поиск по названию ненадёжен: одинаковые названия встречаются у разных вариантов, а текст может измениться между выгрузками.
Могут ли заказы и резервы создавать расхождение?
Да. Физический, свободный и доступный для сайта остатки — разные показатели. Нужно проверить момент резервирования, отмену заказа, проведение документов и формулу, которую выгружает 1С. Иначе обе системы могут хранить корректные, но разные числа.
Вывод
Сайт продолжает продавать закончившийся товар не потому, что «Битрикс не понимает ноль», а потому, что ноль не дошёл до правильной покупаемой сущности либо правила каталога всё ещё разрешают заказ. Самый быстрый путь к причине — один внешний код, последовательность 5 → 1 → 0 и проверка каждой точки: 1С, CommerceML, каталог, карточка и корзина.
После исправления сохраните этот прогон как регрессионный сценарий и выполняйте его после обновления модуля обмена, изменения складов или доработки каталога. Тогда проблема обнаружится на тестовом SKU до того, как магазин начнёт принимать заказы на отсутствующий товар.
Нужно оценить задачу по сайту?
Опишите, что нужно изменить, приложите ссылку на страницу и удобный способ связи. Я посмотрю задачу и подскажу, с чего лучше начать.