При разработке расширений для «1С:Управление торговлей 11.3» программисты часто сталкиваются с ситуацией, когда запрос, прекрасно работающий в основной конфигурации, выдает ошибку в расширении. Особенно это актуально при работе с виртуальными таблицами остатков и оборотов регистров накопления, когда необходимо получить данные через поле Регистратор. Разберем подробно, почему возникает ошибка «Поле не найдено» при обращении к реквизиту ХозяйственнаяОперация и как правильно организовать архитектуру решения.
Рассмотрим типичную ситуацию. В расширении создан веб-сервис или отчет, использующий запрос к виртуальной таблице РегистрНакопления.ПартииТоваровОрганизаций.ОстаткиИОбороты. В тексте запроса мы пытаемся обратиться к реквизиту регистратора напрямую:
|ГДЕ
| НЕ ПартииТоваровОрганизацийОстаткиИОбороты.Регистратор.ХозяйственнаяОперация = ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.ПередачаНаКомиссию)
Конструктор запроса выдает ошибку: «Поле не найдено "ПартииТоваровОрганизацийОстаткиИОбороты.Регистратор.ХозяйственнаяОперация"». Выясним причину этого поведения. Поле Регистратор имеет составной тип данных, включающий десятки различных документов. Когда мы работаем в расширении, платформа накладывает жесткие ограничения на видимость объектов метаданных.
Проанализируем механизмы расширения: для того чтобы разыменовать поле (обратиться через точку) составного типа в расширении, платформа должна «знать» о структуре каждого типа, входящего в этот состав. Если вы добавили в расширение сам регистр накопления, но не добавили в него все документы-регистраторы, конструктор запроса не сможет гарантировать наличие реквизита ХозяйственнаяОперация у каждого возможного типа регистратора.
Это самый очевидный, но трудоемкий путь. Чтобы запрос заработал в расширении через конструктор, выполним следующие шаги:
ПартииТоваровОрганизаций. Посмотрите список его регистраторов. Каждый из этих документов должен быть добавлен в расширение.ХозяйственнаяОперация.ХозяйственныеОперации и его конкретные значения (например, ПередачаНаКомиссию) также перенесены в расширение.Важный нюанс: В УТ 11.3 регистр партий товаров может иметь более 50 типов регистраторов. Проанализируем ситуацию: стоит ли загромождать расширение таким количеством объектов? Если конфигурация не стоит на строгом замке (допускает изменения), возможно, стоит рассмотреть альтернативные варианты.
Если нам нужно проверить хозяйственную операцию только у конкретных типов документов, мы можем помочь платформе определить тип данных. Это снижает требования к количеству объектов в расширении. Рассмотрим пример:
ВЫБОР
КОГДА ПартииТоваровОрганизацийОстаткиИОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ТОГДА ВЫРАЗИТЬ(ПартииТоваровОрганизацийОстаткиИОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг).ХозяйственнаяОперация
ИНАЧЕ ЗНАЧЕНИЕ(Перечисление.ХозяйственныеОперации.ПустаяСсылка)
КОНЕЦ
В этом случае в расширение достаточно добавить только Документ.РеализацияТоваровУслуг с его реквизитом. Однако для фильтрации по всем типам документов в рамках одного запроса этот метод превратит текст в огромную и трудночитаемую конструкцию.
Проанализируем архитектурный подход. Если конфигурация открыта для изменений, самым стабильным и производительным вариантом будет разделение ответственности:
Шаг 1. Создание общего модуля в основной конфигурации. Создадим модуль, например, м_ОбменДаннымиСервер. Установим свойства: «Сервер», «Вызов сервера». В этом модуле мы можем писать любые запросы к любым объектам без ограничений расширений.
Функция ПолучитьДанныеДляСверки(НачалоПериода, КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ИЗ РегистрНакопления.ПартииТоваровОрганизаций.ОстаткиИОбороты(...)";
// Здесь конструктор запроса работает без ошибок
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Шаг 2. Вызов из веб-сервиса в расширении. Теперь наш веб-сервис в расширении просто вызывает функцию основного модуля:
Функция SubmitQuery(TypeOfExchange)
Данные = м_ОбменДаннымиСервер.ПолучитьДанныеДляСверки(Начало, Конец);
// Сериализация и возврат данных
КонецФункции
Этот метод избавляет от необходимости «тащить» в расширение десятки регистраторов и следить за их актуальностью при обновлениях конфигурации.
Выясним причину, по которой даже после добавления всех объектов ошибка может сохраняться. В версиях платформы 8.3.16.1644 и смежных релизах наблюдались особенности кэширования метаданных расширений.
Рекомендации по исправлению кэша:
Мы рассмотрели три пути решения проблемы обращения к реквизитам регистратора. Выбор зависит от ваших целей:
ВЫРАЗИТЬ.Помните, что расширение — это надстройка, и оно всегда «чувствительно» к полноте данных о типах в составных полях. Правильное проектирование связей между расширением и основной базой позволит избежать подобных ошибок в будущем.