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