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