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