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