Как в запросе 1С определить статус отгрузки заказа (полностью, частично или не отгружен)?

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

При подготовке к экзамену «1С:Специалист по платформе» или при разработке реальных отчетов по складской логистике часто возникает задача: классифицировать документы по степени выполнения отгрузки. Обычно требуется выделить три состояния: товар не отгружен, отгружен частично или полностью выполнен. Рассмотрим, как правильно построить логику запроса, чтобы избежать типичных ошибок с вложенными условиями и некорректной обработкой пустых значений.

Анализ исходной проблемы и типичной ошибки

Разберем ситуацию, с которой столкнулся автор темы. В его запросе использовалась следующая конструкция:


ВЫБОР
    КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) <> 0
        ТОГДА ВЫБОР
                КОГДА ОстаткиЗаказовКлиента.ЗаказаноОстаток = КоличествоТоваровИтог.Количество
                    ТОГДА 1
                КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) = 0
                    ТОГДА -1
                ИНАЧЕ 0
            КОНЕЦ
КОНЕЦ

Проанализируем, почему этот код не работает. Основная проблема здесь заключается во вложенности условий. Внешнее условие КОГДА ... <> 0 жестко отсекает все ситуации, когда остаток равен нулю. Следовательно, внутреннее условие КОГДА ... = 0 (которое должно было вернуть -1) никогда не будет выполнено. Кроме того, использование функции ЕСТЬNULL внутри условий без четкой последовательности часто приводит к логическим тупикам.

Шаг 1: Правильная подготовка данных в запросе

Прежде чем писать условия ВЫБОР, мы должны получить две ключевые цифры для каждого заказа:

  1. Общее количество по заказу: сумма из табличной части Товары документа ЗаказКлиента.
  2. Текущий остаток к отгрузке: данные из виртуальной таблицы Остатки регистра накопления (например, ЗаказыКлиентов).

Важно помнить, что при ЛЕВОМ СОЕДИНЕНИИ с таблицей остатков, если товар полностью отгружен, записи в регистре может просто не быть. В этом случае поле остатка примет значение NULL, которое функция ЕСТЬNULL превратит в 0.

Шаг 2: Реализация корректной логики условий

Чтобы классификация работала безотказно, логику нужно выстраивать от простого к сложному, избегая лишней вложенности. Рассмотрим оптимальный порядок проверки условий:


ВЫБОР
    // 1. Проверяем полную отгрузку (остатка нет)
    КОГДА ЕСТЬNULL(ОстаткиЗаказовКлиента.ЗаказаноОстаток, 0) = 0
        ТОГДА 3 // Полностью отгружен

    // 2. Проверяем отсутствие отгрузки (остаток равен исходному количеству)
    КОГДА ОстаткиЗаказовКлиента.ЗаказаноОстаток = КоличествоТоваровИтог.Количество
        ТОГДА 1 // Не отгружен

    // 3. Во всех остальных случаях считаем, что отгрузка частичная
    ИНАЧЕ 2 // Отгружена часть
КОНЕЦ КАК ПризнакОтгруженности

Разберем, почему такой порядок эффективен. Мы сначала обрабатываем ситуацию с нулевым остатком (включая NULL). Затем мы сравниваем физический остаток с исходным планом. Если они равны — значит, движений по отгрузке не было. Любое значение между нулем и полным количеством автоматически попадает в категорию «Частично» через блок ИНАЧЕ.

Шаг 3: Полная структура запроса с учетом оптимизации

Для корректной работы в рамках аттестации «1С:Специалист» или в высоконагруженных системах, не рекомендуется накладывать фильтры в блоке ГДЕ по полям через точку (например, ЗаказКлиента.Товары.Склад). Это вызывает неявные соединения таблиц. Правильнее подготовить данные заранее. Посмотрим на пример оптимизированного запроса:


ВЫБРАТЬ
    Заказ.Ссылка КАК Ссылка,
    ЕСТЬNULL(Остатки.ЗаказаноОстаток, 0) КАК Остаток,
    ЕСТЬNULL(ИтогиДокумента.Количество, 0) КАК ВсегоПоЗаказу,
    ВЫБОР
        КОГДА ЕСТЬNULL(Остатки.ЗаказаноОстаток, 0) = 0
            ТОГДА 3
        КОГДА Остатки.ЗаказаноОстаток = ИтогиДокумента.Количество
            ТОГДА 1
        ИНАЧЕ 2
    КОНЕЦ КАК СтатусОтгрузки
ИЗ
    Документ.ЗаказКлиента КАК Заказ
    // Соединяем с итогами по табличной части
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            ТЧ.Ссылка КАК Ссылка,
            СУММА(ТЧ.Количество) КАК Количество
        ИЗ
            Документ.ЗаказКлиента.Товары КАК ТЧ
        ГРУППИРОВАТЬ ПО
            ТЧ.Ссылка
    ) КАК ИтогиДокумента ПО Заказ.Ссылка = ИтогиДокумента.Ссылка
    // Соединяем с остатками регистра
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыКлиентов.Остатки(&МоментВремени, ) КАК Остатки
    ПО Заказ.Ссылка = Остатки.ЗаказКлиента
ГДЕ
    Заказ.Проведен
    И Заказ.Дата МЕЖДУ &ДатаНачала И &ДатаКонец

Важные рекомендации для разработчика

При использовании данной логики следует учитывать несколько технических нюансов:

  1. Момент времени: Всегда передавайте в виртуальную таблицу остатков параметр Период. Если вы формируете отчет, это может быть КонецПериода. Если это оперативная работа — Граница или МоментВремени.
  2. Характеристики товара: Если в ваших заказах используется номенклатура с характеристиками, группировку в подзапросах и соединение с регистром нужно выполнять не только по заказу, но и в разрезе пары Номенклатура + Характеристика. В противном случае, если один товар в заказе отгружен, а другой — нет, общая сумма по документу может дать ложноположительный результат.
  3. Отмена строк: В типовых конфигурациях (УТ 11, ERP) существует статус строки «Отменено». Если это ваш случай, то при расчете КоличествоТоваровИтог необходимо исключать отмененные строки, иначе остаток в регистре (который списывается при отмене) никогда не совпадет с итогом по документу.
  4. Точность сравнения: При сравнении дробных чисел (количества) в редких случаях могут возникать погрешности округления. Хотя для 1С это не характерно, полезно помнить о приведении типов, если данные поступают из внешних источников.

Таким образом, мы выяснили, что ключ к решению задачи — в линейной структуре ВЫБОР и правильной последовательности проверок от «пустого» (отгруженного) значения к «полному» (не тронутому). Проанализировав эти шаги, вы сможете строить надежные отчеты по выполнению заказов любой сложности.

← На главную