Как разработать одно расширение 1С для работы в разных конфигурациях

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработка универсальных расширений, которые можно было бы подключить одновременно к Бухгалтерии предприятия (БП), Зарплате и управлению персоналом (ЗУП) или Управлению торговлей (УТ), является заманчивой идеей для многих разработчиков. Это позволяет централизованно обновлять общую логику (например, интеграции, дополнительные отчеты или сервисные функции). Однако при попытке реализовать такой подход программисты часто сталкиваются с ошибками сопоставления метаданных. В этой статье мы подробно разберем, как преодолеть эти трудности и заставить одно расширение работать в разных средах.

Анализируем проблему: ошибка сопоставления UUID

Типичная ситуация: вы создали расширение в БП, заимствовав в него какой-либо объект (например, язык Русский, роль или общий модуль), написали свой код и попытались подключить это же расширение к ЗУП. Платформа выдает ошибку:

"Значение контролируемого свойства ОбъектРасширяемойКонфигурации у объекта Язык.Русский не совпадает со значением в расширяемой конфигурации".

Разберем причину этого явления. Когда мы заимствуем объект из основной конфигурации в расширение, платформа 1С:Предприятие сохраняет не только имя объекта, но и его внутренний уникальный идентификатор (UUID). Несмотря на то что в обеих конфигурациях объект называется одинаково (например, Язык.Русский), их внутренние идентификаторы в разных типовых решениях различаются. Платформа по умолчанию строго контролирует это соответствие, что и приводит к ошибке при попытке «накатить» расширение на конфигурацию с другим набором UUID.

Решение проблемы через свойства принадлежности объекта

Для того чтобы сделать расширение по-настоящему универсальным, нам нужно изменить механизм сопоставления объектов. Вместо сопоставления по UUID мы перейдем к сопоставлению по имени. Рассмотрим пошагово, как это сделать:

  1. Откроем дерево конфигурации нашего расширения.
  2. Найдем объект, на который ругается система (в нашем примере это Язык.Русский).
  3. Откроем Панель свойств этого объекта.
  4. Найдем раздел Принадлежность объекта.
  5. Снимем флаг (установим в Ложь) у свойства Объект расширяемой конфигурации.

Установив этот флаг в значение "Ложь", мы сообщаем платформе, что данный объект в расширении не должен жестко привязываться к конкретному объекту основной конфигурации по его идентификатору. Платформа попытается найти объект с таким же именем в текущей базе и, если найдет, успешно подключит расширение. Это правило актуально не только для языков, но и для справочников, документов, ролей и других заимствованных объектов.

Настройка режима совместимости

Следующий критический шаг — правильная настройка режима совместимости расширения. Проанализируем ситуацию: если ваша БП работает на версии платформы 8.3.21, а ЗУП — на 8.3.17, расширение с режимом совместимости 8.3.21 просто не запустится в ЗУП.

Правило минимального значения: установите в расширении режим совместимости, который соответствует самой старой версии платформы среди всех ваших целевых конфигураций. Если одна из баз использует режим 8.3.14, то и в расширении должен стоять режим не выше 8.3.14. Также в некоторых случаях помогает полное отключение режима совместимости в расширении, но это требует тщательного тестирования всех механизмов.

Универсальное взаимодействие с БСП

Чаще всего расширения пишутся для конфигураций на базе Библиотеки стандартных подсистем (БСП). Проблема в том, что версии БСП в разных программах могут отличаться. Процедура в общем модуле может иметь разное количество параметров или вообще отсутствовать в старой версии конфигурации. Чтобы код не вызывал критических ошибок, рассмотрим пример безопасного вызова:


Попытка
    // Пытаемся вызвать метод БСП, который может отличаться
    ОбщегоНазначения.СообщитьПользователю("Текст сообщения");
Исключение
    // Если метод недоступен, выполняем альтернативный код
    ЗаписьЖурналаРегистрации("Расширение", УровеньЖурналаРегистрации.Информация, , , "Метод БСП недоступен");
КонецПопытки;

Также рекомендуется проверять наличие метаданных программно, прежде чем к ним обращаться. Выясним, существует ли конкретная функциональная опция или константа, прежде чем считывать ее значение:


Если Метаданные.Константы.Найти("ИспользоватьНесколькоСкладов") <> Неопределено Тогда
    ЗначениеОпции = Константы.ИспользоватьНесколькоСкладов.Получить();
КонецЕсли;

Программное изменение форм вместо заимствования

Заимствование форм в универсальное расширение — это самый сложный путь. Форма Элемент справочника Номенклатура в УТ и БП может радикально отличаться по составу реквизитов. Если вы заимствуете форму из БП, в УТ она может просто "рассыпаться" или выдать ошибку при открытии.

Рекомендуемый подход: используйте программное добавление элементов. Заимствуйте не саму форму, а только модуль формы или обработчик в общем модуле. В событии ПриСозданииНаСервере опишите логику создания кнопок или полей:


&НаСервере
Процедура Расш_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    // Проверяем, нет ли уже нашего элемента на форме
    Если ЭтаФорма.Элементы.Найти("Расш_ДополнительнаяКнопка") = Неопределено Тогда
        // Программно добавляем команду и кнопку
        НоваяКоманда = ЭтаФорма.Команды.Добавить("Расш_СпециальноеДействие");
        НоваяКоманда.Действие = "Расш_СпециальноеДействие";
        
        НовыйЭлемент = ЭтаФорма.Элементы.Добавить("Расш_ДополнительнаяКнопка", Тип("КнопкаФормы"), ЭтаФорма.КоманднаяПанель);
        НовыйЭлемент.ИмяКоманды = "Расш_СпециальноеДействие";
    КонецЕсли;
КонецПроцедуры

Работа с предопределенными данными и ролями

Избегайте прямого заимствования предопределенных элементов справочников или перечислений. В разных конфигурациях их внутренние имена в метаданных могут не совпадать. Вместо обращения Справочники.Валюты.Рубль лучше использовать поиск по коду или коду ISO.

Что касается прав доступа: не пытайтесь модифицировать существующие роли типовой конфигурации в расширении. Вместо этого создайте в расширении свою собственную роль (например, Расш_ОсновнаяРоль), добавьте в неё права на новые объекты вашего расширения и назначьте эту роль пользователям в каждой информационной базе отдельно. Это гарантирует, что отсутствие роли из БП в конфигурации ЗУП не приведет к сбою расширения.

Гигиена расширения: удаляем лишнее

Проанализируем состав вашего расширения перед финальной сборкой. Часто разработчики заимствуют объекты "на всякий случай" или автоматически при копировании кода. Каждый лишний заимствованный объект — это потенциальная точка отказа. Проанализируйте дерево метаданных и удалите все объекты, которые не используются непосредственно в вашем коде. Оставьте только те элементы, где вы действительно меняете логику или свойства. Чем меньше объектов заимствовано, тем выше вероятность, что расширение без проблем "встанет" на любую другую конфигурацию.

Важный совет: всегда используйте функцию "Проверка применимости" в Конфигураторе после внесения изменений. Это поможет заранее увидеть конфликты свойств, которые могут возникнуть при подключении расширения к другой версии программы.

← На главную