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