При подготовке к экзамену «1С:Специалист по платформе» или при разработке реальных отчетов по складской логистике часто возникает задача: классифицировать документы по степени выполнения отгрузки. Обычно требуется выделить три состояния: товар не отгружен, отгружен частично или полностью выполнен. Рассмотрим, как правильно построить логику запроса, чтобы избежать типичных ошибок с вложенными условиями и некорректной обработкой пустых значений.
Разберем ситуацию, с которой столкнулся автор темы. В его запросе использовалась следующая конструкция:
ВЫБОР
КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) <> 0
ТОГДА ВЫБОР
КОГДА ОстаткиЗаказовКлиента.ЗаказаноОстаток = КоличествоТоваровИтог.Количество
ТОГДА 1
КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) = 0
ТОГДА -1
ИНАЧЕ 0
КОНЕЦ
КОНЕЦ
Проанализируем, почему этот код не работает. Основная проблема здесь заключается во вложенности условий. Внешнее условие КОГДА ... <> 0 жестко отсекает все ситуации, когда остаток равен нулю. Следовательно, внутреннее условие КОГДА ... = 0 (которое должно было вернуть -1) никогда не будет выполнено. Кроме того, использование функции ЕСТЬNULL внутри условий без четкой последовательности часто приводит к логическим тупикам.
Прежде чем писать условия ВЫБОР, мы должны получить две ключевые цифры для каждого заказа:
Товары документа ЗаказКлиента.Остатки регистра накопления (например, ЗаказыКлиентов).Важно помнить, что при ЛЕВОМ СОЕДИНЕНИИ с таблицей остатков, если товар полностью отгружен, записи в регистре может просто не быть. В этом случае поле остатка примет значение NULL, которое функция ЕСТЬNULL превратит в 0.
Чтобы классификация работала безотказно, логику нужно выстраивать от простого к сложному, избегая лишней вложенности. Рассмотрим оптимальный порядок проверки условий:
ВЫБОР
// 1. Проверяем полную отгрузку (остатка нет)
КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) = 0
ТОГДА 3 // Полностью отгружен
// 2. Проверяем отсутствие отгрузки (остаток равен исходному количеству)
КОГДА ОстаткиЗаказовКлиента.ЗаказаноОстаток = КоличествоТоваровИтог.Количество
ТОГДА 1 // Не отгружен
// 3. Во всех остальных случаях считаем, что отгрузка частичная
ИНАЧЕ 2 // Отгружена часть
КОНЕЦ КАК ПризнакОтгруженности
Разберем, почему такой порядок эффективен. Мы сначала обрабатываем ситуацию с нулевым остатком (включая NULL). Затем мы сравниваем физический остаток с исходным планом. Если они равны — значит, движений по отгрузке не было. Любое значение между нулем и полным количеством автоматически попадает в категорию «Частично» через блок ИНАЧЕ.
Для корректной работы в рамках аттестации «1С:Специалист» или в высоконагруженных системах, не рекомендуется накладывать фильтры в блоке ГДЕ по полям через точку (например, ЗаказКлиента.Товары.Склад). Это вызывает неявные соединения таблиц. Правильнее подготовить данные заранее. Посмотрим на пример оптимизированного запроса:
ВЫБРАТЬ
Заказ.Ссылка КАК Ссылка,
ЕСТЬNULL(Остатки.ЗаказаноОстаток, 0) КАК Остаток,
ЕСТЬNULL(ИтогиДокумента.Количество, 0) КАК ВсегоПоЗаказу,
ВЫБОР
КОГДА ЕСТЬNULL(Остатки.ЗаказаноОстаток, 0) = 0
ТОГДА 3
КОГДА Остатки.ЗаказаноОстаток = ИтогиДокумента.Количество
ТОГДА 1
ИНАЧЕ 2
КОНЕЦ КАК СтатусОтгрузки
ИЗ
Документ.ЗаказКлиента КАК Заказ
// Соединяем с итогами по табличной части
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
ТЧ.Ссылка КАК Ссылка,
СУММА(ТЧ.Количество) КАК Количество
ИЗ
Документ.ЗаказКлиента.Товары КАК ТЧ
ГРУППИРОВАТЬ ПО
ТЧ.Ссылка
) КАК ИтогиДокумента ПО Заказ.Ссылка = ИтогиДокумента.Ссылка
// Соединяем с остатками регистра
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыКлиентов.Остатки(&МоментВремени, ) КАК Остатки
ПО Заказ.Ссылка = Остатки.ЗаказКлиента
ГДЕ
Заказ.Проведен
И Заказ.Дата МЕЖДУ &ДатаНачала И &ДатаКонец
При использовании данной логики следует учитывать несколько технических нюансов:
Период. Если вы формируете отчет, это может быть КонецПериода. Если это оперативная работа — Граница или МоментВремени.Номенклатура + Характеристика. В противном случае, если один товар в заказе отгружен, а другой — нет, общая сумма по документу может дать ложноположительный результат.КоличествоТоваровИтог необходимо исключать отмененные строки, иначе остаток в регистре (который списывается при отмене) никогда не совпадет с итогом по документу.Таким образом, мы выяснили, что ключ к решению задачи — в линейной структуре ВЫБОР и правильной последовательности проверок от «пустого» (отгруженного) значения к «полному» (не тронутому). Проанализировав эти шаги, вы сможете строить надежные отчеты по выполнению заказов любой сложности.