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