При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда параметры, заданные в тексте запроса внутри фигурных скобок {}, ведут себя непредсказуемо. Особенно остро проблема проявляется при попытке программно ограничить данные в зависимости от прав доступа текущего пользователя. Рассмотрим ситуацию, когда код написан, значения присвоены, но отчет продолжает выводить данные без ограничений, и разберем, как решить эту задачу правильно.
Рассмотрим типичный запрос, использующий виртуальную таблицу оборотов регистра накопления. В параметрах виртуальной таблицы мы часто указываем условия в фигурных скобках. Это делает их необязательными: если параметр не заполнен или его использование отключено в настройках, СКД просто игнорирует этот фрагмент и не включает его в итоговый запрос к базе данных.
Пример проблемного запроса:
ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.Регистратор,
ПродажиОбороты.КоличествоОборот,
ПродажиОбороты.СтоимостьОборот,
ПродажиОбороты.Контрагент
ИЗ
РегистрНакопления.Продажи.Обороты(
&НачалоПериода,
&КонецПериода,
Регистратор,
НЕ Номенклатура.Услуга
{Контрагент В ИЕРАРХИИ (&ОптоваяТорговля)}
{Контрагент.ОсновнойМенеджерПокупателя = &ОсновнойМенеджерПокупателя}
) КАК ПродажиОбороты
Проанализируем ситуацию: здесь параметры &ОптоваяТорговля и &ОсновнойМенеджерПокупателя заключены в фигурные скобки. Это означает, что СКД применит эти фильтры только в том случае, если они будут "включены" в компоновщике настроек. Если вы просто установите значение параметра, но не активируете флаг его использования, условие в итоговый SQL-запрос не попадет.
Для реализации логики прав доступа (например, когда рядовой менеджер видит только свои продажи, а администратор — всё), код обычно размещают в модуле объекта отчета в процедуре ПриКомпоновкеРезультата. Выясним, как выглядит правильная установка значений:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Проверяем роли и устанавливаем фильтры
Если НЕ РольДоступна("ПолныеПрава") Тогда
// Установка группы контрагентов
ГруппаОпт = Справочники.Контрагенты.НайтиПоКоду("00001");
Если НЕ ГруппаОпт.Пустая() Тогда
КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ОптоваяТорговля", ГруппаОпт);
КонецЕсли;
// Если нет прав на просмотр всех, ограничиваем текущим пользователем
Если НЕ РольДоступна("ОтчетПоПродажамПоВсемКонтрагентам") Тогда
КомпоновщикНастроек.Настройки.ParaметрыДанных.УстановитьЗначениеПараметра("ОсновнойМенеджерПокупателя", ПараметрыСеанса.ТекущийПользователь);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Однако даже такой код часто "не срабатывает". Проанализируем основные причины этой "мистики".
Это самая распространенная ловушка в СКД. В системе существует три уровня настроек:
КомпоновщикНастроек.Настройки.Важный нюанс: Если параметр вынесен в состав "Пользовательских настроек" (флажок "Включать в пользовательские настройки" в СКД), то значения из КомпоновщикНастроек.Настройки будут полностью проигнорированы платформой. Система всегда отдает приоритет тому, что находится в коллекции КомпоновщикНастроек.ПользовательскиеНастройки.
Чтобы гарантированно изменить параметр, который доступен пользователю, мы должны найти его по идентификатору в пользовательских настройках:
// Пример поиска параметра в пользовательских настройках
ПараметрСКД = Новый ПараметрКомпоновкиДанных("ОсновнойМенеджерПокупателя");
ЗначениеПараметра = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(ПараметрСКД);
Если ЗначениеПараметра <> Неопределено Тогда
Идентификатор = ЗначениеПараметра.ИдентификаторПользовательскойНастройки;
ЭлементПользовательскойНастройки = КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Найти(Идентификатор);
Если ЭлементПользовательскойНастройки <> Неопределено Тогда
ЭлементПользовательскойНастройки.Значение = ПараметрыСеанса.ТекущийПользователь;
ЭлементПользовательскойНастройки.Использование = Истина;
КонецЕсли;
КонецЕсли;
Для параметров, находящихся в фигурных скобках, критически важен флаг Использование. Простой установки значения недостаточно. Посмотрим на примере:
Когда вы вызываете УстановитьЗначениеПараметра(), платформа автоматически пытается взвести флаг использования. Однако, если параметр является частью сложной структуры или виртуальной таблицы, рекомендуется явно проверять это состояние. Если в Настройках использование стоит в Ложь, СКД вырежет условие из запроса, и вы получите данные без фильтрации.
Часто программист вносит изменения в код, запускает отчет, а "ничего не изменилось". Рассмотрим, почему так происходит. 1С сохраняет настройки отчетов для каждого пользователя в системных хранилищах. При открытии отчета система пытается восстановить последнее состояние настроек.
Если пользователь ранее открывал отчет, когда параметров еще не было или они были настроены иначе, старые настройки из хранилища могут перекрыть логику ПриКомпоновкеРезультата. Самый простой способ проверить это — нажать в отчете кнопку "Установить стандартные настройки". Это сбросит кэш и заставит систему применить актуальный программный код.
Разберем, как сделать ваши отчеты более надежными:
КомпоновщикНастроек.Настройки будет работать без конфликтов с пользовательским интерфейсом.В ИЕРАРХИИ убедитесь, что ссылка не является пустой. Использование пустой ссылки в иерархическом фильтре может привести к получению пустого результата вместо ожидаемых данных.ГДЕ.Проанализировав все вышеперечисленные факторы, мы видим, что "мистика" в СКД обычно объясняется строгой иерархией настроек. Для стабильной работы всегда проверяйте, не перекрывается ли ваш программный код пользовательскими значениями, и не забывайте про управление флагом использования параметров.