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