При разработке расширений для типовых конфигураций (таких как ERP, УТ 11 или КА) программисты часто сталкиваются с необходимостью вывести на форму документа данные, которые физически находятся в связанных справочниках. Типичный пример: в документе ЗаказПоставщику нужно отобразить организацию, которая указана в выбранном договоре. Несмотря на кажущуюся простоту, здесь возникают нюансы, связанные с работой тонкого клиента, составом расширения и функциональными опциями. Разберем подробно, как решить эту задачу правильно.
Рассмотрим ситуацию: вы добавили документ и его форму в расширение, перенесли туда же справочник ДоговорыКонтрагентов и реквизит Организация. Однако при попытке программного обращения Объект.Договор.Организация в клиентском коде (например, в обработчике ПриИзменении) система выдает ошибку или показывает отсутствие данных в отладчике. Проанализируем, почему так происходит.
Основная причина заключается в архитектуре Тонкого клиента. На клиенте переменная Объект.Договор — это всего лишь ссылка (уникальный идентификатор). Сами данные объекта (включая реквизит Организация внутри договора) в оперативной памяти клиента отсутствуют. Когда код пытается обратиться «через точку», платформа ищет это поле в кэше формы. Если поле не выведено на форму как элемент или не включено в состав реквизитов формы специальным образом, платформа не может «прыгнуть» в базу данных прямо из клиентского контекста.
Если ваша задача — просто показать организацию на форме без необходимости её сложной обработки в коде, мы можем воспользоваться стандартным механизмом платформы. Разберем по шагам, как это сделать в расширении:
Объект, раскройте его, найдите Договор.Организация справочника Договоры в расширение, вы увидите его в дереве реквизитов формы.Объект.Договор.Организация на дерево элементов формы.В этом случае платформа сама обеспечит подкачку данных с сервера при отрисовке формы. В поле ПутьКДанным у элемента формы будет прописано Объект.Договор.Организация. Это самый экономный и правильный способ визуализации вложенных данных.
Если же вам нужно не просто показать значение, а записать его в какой-то другой реквизит документа при смене договора, нам потребуется написать код. Посмотрим на пример правильной реализации в обработчике события ДоговорПриИзменении.
Поскольку обращение «через точку» на клиенте невозможно, мы должны создать серверную функцию или воспользоваться общими модулями. Проанализируем пример кода в расширении:
&НаКлиенте
Процедура Расш1_ДоговорПриИзмененииПосле(Элемент)
// Мы находимся на клиенте.
// Напрямую обратиться Объект.Договор.Организация нельзя.
// Вызываем серверный контекст для получения данных.
ОрганизацияДоговора = ПолучитьОрганизациюДоговораНаСервере(Объект.Договор);
Если ЗначениеЗаполнено(ОрганизацияДоговора) Тогда
Объект.Организация = ОрганизацияДоговора;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьОрганизациюДоговораНаСервере(Знач СсылкаНаДоговор)
// Используем эффективный метод получения реквизита без чтения всего объекта
Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаДоговор, "Организация");
КонецФункции
Важный момент: использование функции ОбщегоНазначения.ЗначениеРеквизитаОбъекта предпочтительнее, чем СсылкаНаДоговор.Организация на сервере, так как это выполняет легкий SQL-запрос только к одной колонке таблицы, не загружая в память весь объект договора.
Для того чтобы код и форма работали корректно, необходимо соблюсти правила включения объектов в расширение. Проверьте следующие пункты:
Организация имеет тип СправочникСсылка.Организации, то сам справочник Организации обязан быть добавлен в расширение (хотя бы пустой оболочкой).Договоры обязательно должен быть отмечен реквизит Организация. Если вы добавили только сам справочник, но не отметили галочкой реквизит внутри него, точка .Организация не будет доступна даже на сервере в контексте расширения.Иногда программист делает всё правильно: добавляет реквизит на форму, настраивает путь к данным, но в режиме «1С:Предприятие» поле всё равно не отображается. Выясним причину этой ситуации.
В типовых конфигурациях реквизит Организация почти всегда связан с функциональной опцией ИспользоватьНесколькоОрганизаций. Если в базе заведена только одна организация, платформа автоматически скрывает это поле, считая его лишним для интерфейса. Чтобы принудительно отобразить поле через расширение, можно:
Истина.ПриСозданииНаСервере в основной конфигурации. Если там жестко прописано Элементы.Организация.Видимость = Ложь, вам придется перекрыть это поведение в расширении, создав обработчик После для этой процедуры.Рассмотрим ситуацию, когда изменения нужны конкретному пользователю или группе, а конфигурация не должна меняться. Как было замечено в обсуждении, можно обойтись без расширения. В режиме предприятия через меню Еще — Изменить форму можно встать на поле договора, нажать Добавить поля и выбрать Организация. Однако этот метод имеет минус: настройку придется повторять для каждого пользователя или копировать её административно, что не всегда удобно при массовом внедрении функционала.
Таким образом, для надежного и автоматического вывода вложенного реквизита оптимальным является использование расширения с корректно прописанным ПутьКДанным и серверным получением значений в коде при необходимости их инициализации.