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