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

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

При разработке тиражных решений и общей функциональности для различных конфигураций 1С (например, 1С:Управление торговлей и 1С:Бухгалтерия предприятия) разработчики часто стремятся создать единый файл расширения (.cfe). Однако при попытке подключить такое расширение к базе возникает критическая ошибка: "(Критичная) Не найден объект метаданных...". Разберем причины такого поведения платформы и практические способы решения этой задачи.

Почему возникает критическая ошибка при подключении расширения?

Выясним причину ошибки валидации. Механизм расширений конфигурации в платформе 1С:Предприятие 8.3 выполняет строгую проверку соответствия метаданных перед применением расширения:

  1. Если в структуру расширения был заимствован объект, существующий только в одной конфигурации (например, Документ.ЗаказКлиента из УТ или Документ.СчетНаОплатуПокупателю из БП), платформа проверяет его наличие в целевой базе.
  2. Если объект в основной конфигурации отсутствует, расширение признается несовместимым и блокируется платформой с критической ошибкой.
  3. Отключить или проигнорировать эту проверку на уровне платформы для заимствованных объектов невозможно.

Следовательно, чтобы файл расширения оставался универсальным и успешно подключался к любой базе, в нем не должно быть заимствованных объектов, специфичных только для конкретной конфигурации. Вся логика взаимодействия с метаданными должна строиться динамически.

Способ 1. Отказ от жесткой типизации и динамическая работа в коде

Рассмотрим, как реализовать логику без заимствования документов в расширение. Для этого создаются собственные объекты расширения (обработки, общие модули, формы), а обращение к объектам целевой конфигурации выполняется во время исполнения (в рантайме).

Разберем по шагам правила построения универсального кода:

  1. Проверка наличия объекта метаданных. Перед обращением к документу проверяем его существование в коллекции конфигурации через метод Найти():

ИмяДокумента = "СчетНаОплатуПокупателю";
Если Метаданные.Документы.Найти(ИмяДокумента) <> Неопределено Тогда
    Менеджер = Документы[ИмяДокумента];
    // Выполнение логики для БП
ИначеЕсли Метаданные.Документы.Найти("ЗаказКлиента") <> Неопределено Тогда
    Менеджер = Документы["ЗаказКлиента"];
    // Выполнение логики для УТ
КонецЕсли;
  1. Обобщенные типы реквизитов на формах. В реквизитах собственных форм расширения нельзя задавать тип конкретного отсутствующего документа (например, ДокументСсылка.СчетНаОплатуПокупателю). Используем базовые составные типы: ДокументСсылка, ЛюбаяСсылка или Произвольный.
  2. Программное ограничение типов выбора. Чтобы ограничить выбор пользователя конкретным документом конфигурации, настраиваем элемент формы программно в событии ПриСозданииНаСервере:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    МассивТипов = Новый Массив;
    Если Метаданные.Документы.Найти("СчетНаОплатуПокупателю") <> Неопределено Тогда
        МассивТипов.Добавить(Тип("ДокументСсылка.СчетНаОплатуПокупателю"));
    ИначеЕсли Метаданные.Документы.Найти("ЗаказКлиента") <> Неопределено Тогда
        МассивТипов.Добавить(Тип("ДокументСсылка.ЗаказКлиента"));
    КонецЕсли;
    
    Элементы.ПолеДокумент.ОграничениеТипа = Новый ОписаниеТипов(МассивТипов);
    
КонецПроцедуры
  1. Динамическое формирование запросов. Тексты запросов к специфичным таблицам формируются путем конкатенации имени таблицы:

ИмяТаблицы = ?(Метаданные.Документы.Найти("ЗаказКлиента") <> Неопределено, "ЗаказКлиента", "СчетНаОплатуПокупателю");

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Док.Ссылка КАК Ссылка,
    |	Док.Номер КАК Номер,
    |	Док.Дата КАК Дата
    |ИЗ
    |	Документ." + ИмяТаблицы + " КАК Док
    |ГДЕ
    |	Док.Проведен = ИСТИНА";

Результат = Запрос.Выполнить();

Способ 2. Архитектура «Ядро + Адаптеры»

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

Для таких задач применяется модульная архитектура:

  1. Базовое расширение (Ядро): содержит общий интерфейс, алгоритмы обработки данных, универсальные формы и API. Не содержит заимствованных объектов, специфичных для конкретных конфигураций, и подключается во все базы без ошибок.
  2. Расширение-адаптер: отдельный компактный файл расширения, созданный специально под целевую конфигурацию (например, «Адаптер для УТ» или «Адаптер для БП»). В нем заимствуются нужные документы и методы, а управление передается в базовое ядро.

Способ 3. Использование внешних обработок (БСП)

Если задача заключается исключительно в предоставлении общего интерфейса и добавлении функционала без перехвата типовых процедур конфигурации, целесообразно использовать механизм Дополнительных отчетов и обработок.

Внешние обработки (.epf) не проходят предварительную жесткую валидацию метаданных платформой при загрузке. Это позволяет разместить внутри одной обработки логику как для 1С:Бухгалтерии, так и для 1С:Управления торговлей, используя программную проверку состава конфигурации.

← На главную