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