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