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