Почему в 1С:ERP 2.5 при отборе по подразделению в «Управлении очередью заказов» обнуляются добавленные поля и как это исправить?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Промышленность, строительство и АПК
← На главную

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

В этой статье мы подробно разберем, почему платформа 1С ведет себя таким образом, проанализируем внутренние механизмы работы динамических списков и найдем элегантное решение проблемы с помощью расширений языка запросов СКД.

Анализ проблемы: почему «пропадают» данные

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


// Фрагмент запроса динамического списка
ВЫБРАТЬ
    Таблица.Ссылка КАК Ссылка,
    Таблица.Подразделение КАК Подразделение,
    // Наши расчетные данные
    ВЫБОР
        КОГДА ЕСТЬNULL(ОбеспечениеПроцессов.ТребуетсяОборот, 0) <> 0
            ТОГДА ЕСТЬNULL(ОбеспечениеПроцессов.ПроизведеноОборот, 0) / ОбеспечениеПроцессов.ТребуетсяОборот * 100
        ИНАЧЕ 0
    КОНЕЦ КАК ПроцентВыполнения
ИЗ
    Документ.ЗаказНаПроизводство2_2 КАК Таблица
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОбеспечениеПроизводственныхПроцессов.Обороты(, , , Склад.СкладГотовойПродукции = ИСТИНА) КАК ОбеспечениеПроцессов
    ПО (ОбеспечениеПроцессов.Распоряжение = Таблица.Ссылка)
ГДЕ
    Таблица.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовНаПроизводство2_2.КПроизводству)

Проблема заключается в том, что когда пользователь устанавливает отбор по полю Подразделение, система компоновки данных (СКД), на которой базируется динамический список, пытается оптимизировать запрос. Выясним основные причины обнуления поля ПроцентВыполнения:

  1. Трансформация LEFT JOIN в INNER JOIN. Если СКД посчитает, что условие отбора должно применяться ко всей выборке, она может неявно изменить левое соединение на внутреннее. Если в правой таблице (регистре) нет записей, соответствующих критериям, вся строка (включая данные из левой таблицы) может быть исключена или расчетное поле станет NULL, которое функция ЕСТЬNULL превратит в 0.
  2. Неявный проброс отбора в виртуальную таблицу. Платформа видит, что вы фильтруете список по подразделению. Она «заглядывает» в правую часть соединения (виртуальную таблицу Обороты) и видит, что там тоже есть измерение или реквизит Подразделение. В целях оптимизации СКД накладывает этот же отбор внутрь параметров виртуальной таблицы. Если в регистре подразделение заполнено иначе (например, там указано подразделение-исполнитель, а в заказе — подразделение-диспетчер), данные в правой части просто исчезнут, так как не пройдут фильтр.

Решение проблемы с помощью фигурных скобок {}

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

Нам нужно использовать конструкцию в блоке ГДЕ, которая перехватит стандартный отбор и направит его только на основную таблицу заказа. Разберем по шагам, как модифицировать запрос.

Шаг 1. Определение псевдонима для отбора

В основной части запроса мы оставляем выбор поля Подразделение из таблицы документа. А в секции ГДЕ добавляем специальную инструкцию в фигурных скобках:


ГДЕ
    Таблица.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказовНаПроизводство2_2.КПроизводству)
    И Таблица.Проведен
    {ГДЕ Таблица.Подразделение.* КАК Подразделение}

Здесь конструкция {ГДЕ ...} сообщает СКД: «Если пользователь наложит отбор по полю Подразделение, примени его именно к полю Таблица.Подразделение, и не пытайся накладывать его на другие таблицы соединения».

Шаг 2. Использование псевдонимов для исключения конфликтов

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


// В блоке ВЫБРАТЬ
Таблица.Подразделение КАК Подразделение,

// В блоке ГДЕ
{ГДЕ Таблица.Подразделение.* КАК ПодразделениеДляОтбора}

В настройках динамического списка (на вкладке «Настройки» в конфигураторе или программно) теперь можно будет использовать поле ПодразделениеДляОтбора. Это гарантирует, что фильтрация затронет только левую (основную) таблицу запроса.

Почему это работает?

Использование фигурных скобок — это способ «ручного управления» поведением СКД. Когда мы пишем обычный запрос, платформа обладает большой свободой в его интерпретации для оптимизации скорости выполнения. Левое соединение в динамических списках — зона повышенного риска, так как логика фильтрации может нарушить целостность этого соединения.

Основные преимущества этого метода:

Дополнительные рекомендации при работе с ERP 2.5

Проанализируем еще несколько нюансов, которые могут влиять на результат в данном конкретном рабочем месте:

  1. Склад готовой продукции: Обратите внимание на условие в соединении: Склад.СкладГотовойПродукции = ИСТИНА. Если при наложении отбора по определенному подразделению выяснится, что оно выпускает продукцию на склады, где этот признак не установлен, данные также будут обнуляться. Проверьте настройки складов в вашей базе.
  2. Механизм RLS (Record Level Security): Если у пользователя ограничены права на просмотр регистра Обеспечение производственных процессов по конкретным подразделениям, то при включении фильтра данные могут скрываться механизмом прав доступа. Убедитесь, что проблема не связана с ограничениями профиля безопасности.
  3. Виртуальные таблицы и параметры: При использовании .Обороты всегда старайтесь передавать параметры начала и окончания периода, если это возможно, чтобы не замедлять работу динамического списка при росте базы.

Таким образом, мы выяснили причину «полтергейста» в динамических списках 1С:ERP. Проблема кроется в излишней «интеллектуальности» СКД при работе с левыми соединениями. Использование расширений языка запросов с применением фигурных скобок { } позволяет четко разграничить логику отбора и гарантировать корректное отображение добавленных расчетных полей.

← На главную