Как рассчитать общий статус заказа в СКД 1С на основе статусов номенклатурных позиций

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда данные в детальных записях (строках) различаются, из-за чего группировка по родительскому объекту (например, по Заказу клиента) начинает «разрываться» или дублироваться. Рассмотрим подробнее, почему это происходит и как правильно реализовать логику вычисления общего статуса заказа, основываясь на состояниях его позиций.

Причина возникновения «разрывов» в группировках СКД

Проанализируем ситуацию: когда мы пишем условие ВЫБОР КОГДА... в Вычисляемом поле, СКД рассчитывает это выражение для каждой строки детальных записей отдельно. Если в одном заказе две позиции, и у одной статус «В резерве», а у другой — «Поставка», то на уровне группировки «Заказ» система видит два разных значения. Поскольку СКД стремится отобразить все уникальные комбинации данных, она выводит строку заказа дважды (для каждого статуса).

Чтобы избежать этого, нам нужно заставить систему «схлопнуть» эти значения в одно по определенному правилу. Разберем основные методы решения этой задачи.

Решение 1: Метод весов (приоритетов) через Ресурсы

Это самый надежный и производительный способ для СКД. Суть метода заключается в том, чтобы присвоить каждому текстовому статусу числовой код (вес) и использовать агрегатную функцию в ресурсах.

Шаг 1. В наборе данных (запросе) или в вычисляемом поле преобразуем текст в число. Выясним причину, какой статус является более важным. Например, если хотя бы одна позиция в заказе находится в статусе «Поставка», то и весь заказ может считаться «В поставке».

Пример кода для Вычисляемого поля СтатусВес:


ВЫБОР 
    КОГДА СтатусТекст ПОДОБНО "%Поставка%" ТОГДА 1
    КОГДА СтатусТекст ПОДОБНО "%В резерве%" ТОГДА 2
    КОГДА СтатусТекст ПОДОБНО "%Готов к отгрузке%" ТОГДА 3
    КОГДА СтатусТекст ПОДОБНО "%Всё отгружено%" ТОГДА 4
    ИНАЧЕ 5
КОНЕЦ

Шаг 2. Перейдем на закладку Ресурсы. Добавим наше поле СтатусВес и в выражении укажем Минимум(СтатусВес) (или Максимум, в зависимости от логики приоритетов). Это позволит получить один единственный код для всей группировки заказа.

Шаг 3. Создадим еще одно вычисляемое поле ОбщийСтатусТекст, которое переведет число обратно в текст, и также добавим его в ресурсы с выражением:


ВЫБОР 
    КОГДА Минимум(СтатусВес) = 1 ТОГДА "Ожидается поставка"
    КОГДА Минимум(СтатусВес) = 2 ТОГДА "Частично в резерве"
    ...
КОНЕЦ

Решение 2: Использование функции СоединитьСтроки

Если нам не нужно выбирать один «главный» статус, а мы хотим видеть все имеющиеся состояния через запятую в строке заказа, проанализируем возможности функций агрегации СКД. Для этого в поле Ресурсы для текстового поля статуса укажем выражение:

СоединитьСтроки(ТаблицаЗначений(Различные СтатусПозиции), ", ")

Это исключит дублирование строк заказа и выведет все уникальные статусы позиций в одну ячейку.

Решение 3: Использование внешнего набора данных (Объект)

В сложных случаях, когда логика определения статуса завязана на тяжелых вычислениях или функциях общих модулей, лучше подготовить таблицу данных в программном коде перед выводом отчета. Рассмотрим пример передачи подготовленной таблицы в СКД:


// В модуле объекта отчета или форме
СтандартнаяОбработка = Ложь;
ТаблицаДанных = ПолучитьТаблицуСоСтатусами(); // Ваша функция подготовки данных

ВнешнийНаборДанных = Новый Структура("Таблица", ТаблицаДанных);
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();

ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных, ДанныеРасшифровки);

ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

В самой схеме СКД при этом должен быть создан Набор данных - объект с именем Таблица и соответствующими полями.

Важное замечание о производительности

Рассмотрим ситуацию с вызовом функций общих модулей (например, ОпределитьСрокПоставки()) непосредственно в выражениях СКД. Посмотрим на это с точки зрения нагрузки на систему: если отчет формируется по 10 000 строк, функция будет вызвана 10 000 раз. Это может привести к значительным задержкам («залипанию» базы).

Рекомендации по оптимизации:

  1. Старайтесь переносить логику вычисления статуса в основной Запрос СКД, используя левые соединения с регистрами (например, РегистрСведений.СостоянияЗаказов в ERP или УТ 11).
  2. Если используется ПОДОБНО, помните, что это ресурсоемкая операция. Если возможно, замените проверку строк на проверку перечислений или булевых флагов (например, Заказ.Проведен, Заказ.Статус).
  3. Используйте временные таблицы в запросе для предварительной группировки состояний, чтобы в итоговую выборку попадал уже готовый агрегированный статус заказа.

Таким образом, для решения проблемы «разрыва» заказа необходимо перенести логику определения статуса из плоскости «строка за строкой» в плоскость агрегированных ресурсов или предварительно подготовленных наборов данных.

← На главную