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