При разработке и внедрении внешних отчетов и обработок в конфигурации на базе 1С:Предприятие 8.3 (особенно в типовые решения вроде 1С:Бухгалтерия, 1С:ERP или 1С:УНФ) мы часто используем механизмы Библиотеки стандартных подсистем (БСП). Внедрение обработки происходит через стандартный справочник ДополнительныеОтчетыИОбработки.
Разработчики создают экспортную функцию СведенияОВнешнейОбработке(), в которой описывают параметры регистрации. Однако многие сталкиваются с неприятным ограничением: БСП не позволяет напрямую через возвращаемую структуру параметров указать разделы командного интерфейса (подсистемы), в которых должна быть опубликована обработка. В результате администраторам приходится вручную заходить в карточку каждой обработки в каждой базе данных и проставлять флажки напротив нужных разделов (например, "Банк и касса", "Продажи", "Покупки").
Если баз много, этот процесс превращается в рутину. В этой статье мы подробно разберем, почему существует это ограничение и как его элегантно обойти с помощью программных методов.
Разработчики фирмы "1С" намеренно исключили возможность жесткого кодирования разделов публикации в структуре функции СведенияОВнешнейОбработке(). Сделано это из соображений универсальности. Внешняя обработка создается как независимый от конкретной конфигурации модуль. В то же время структура разделов командного интерфейса уникальна для каждого прикладного решения. Подсистемы, которые есть в "Бухгалтерии предприятия", могут полностью отсутствовать в "Управлении нашей фирмой" или "ERP".
Предполагается, что окончательное решение о месте размещения команды в интерфейсе должен принимать администратор конкретной информационной базы в момент интерактивного подключения файла.
Тем не менее, если мы разрабатываем тиражируемое решение для группы однотипных баз (например, для десятков филиалов с идентичной конфигурацией "1С:Бухгалтерия"), ручная настройка разделов неэффективна. Нам нужен способ автоматизировать этот процесс.
Рассмотрим подробнее три практических сценария автоматического заполнения разделов.
Суть метода заключается в том, что при первом интерактивном вызове пользователем любой команды нашей обработки выполняется специальный код инициализации. Этот код находит элемент справочника ДополнительныеОтчетыИОбработки, соответствующий текущей обработке, и программно заполняет его табличную часть Разделы.
Давайте разберем по шагам, как реализовать этот алгоритм:
СведенияОВнешнейОбработке() мы обязательно должны отключить безопасный режим. Для этого устанавливаем свойство БезопасныйРежим = Ложь. В противном случае платформа заблокирует попытку записи в базу данных из кода внешней обработки.ИдентификаторыОбъектовМетаданных.Разделы и записываем объект.Посмотрим на пример реализации серверного метода:
Процедура АвтоматическиНастроитьРазделы() Экспорт
// Имя нашей внешней обработки, как оно зарегистрировано в БСП
ИмяОбъектаБСП = "МояВнешняяОбработка";
СсылкаНаОбработку = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоРеквизиту("ИмяОбъекта", ИмяОбъектаБСП);
Если СсылкаНаОбработку.Пустая() Тогда
ВызватьИсключение "Не удалось найти регистрационную запись внешней обработки в справочнике!";
КонецЕсли;
ОбъектДопОбработки = СсылкаНаОбработку.ПолучитьОбъект();
// Проверим, настроены ли разделы ранее.
// Если администратор уже настроил разделы вручную, не будем затирать его настройки.
Если ОбъектДопОбработки.Разделы.Количество() > 0 Тогда
Возврат;
КонецЕсли;
// Определим список системных имен разделов, куда хотим поместить обработку.
// Например, для Бухгалтерии Предприятия 3.0:
МассивИменРазделов = Новый Массив;
МассивИменРазделов.Добавить("Подсистема.БанкИКасса");
МассивИменРазделов.Добавить("Подсистема.Покупки");
МассивИменРазделов.Добавить("Подсистема.Продажи");
Для Каждого ИмяРаздела Из МассивИменРазделов Цикл
// В БСП разделы привязаны к справочнику ИдентификаторыОбъектовМетаданных
СсылкаНаРаздел = Справочники.ИдентификаторыОбъектовМетаданных.НайтиПоРеквизиту("ПолноеИмя", ИмяРаздела);
Если ЗначениеЗаполнено(СсылкаНаРаздел) Тогда
НоваяСтрока = ОбъектДопОбработки.Разделы.Добавить();
НоваяСтрока.Раздел = СсылкаНаРаздел;
КонецЕсли;
КонецЦикла;
Если ОбъектДопОбработки.Модифицирован() Тогда
Попытка
ОбъектДопОбработки.Записать();
ЗаписьЖурналаРегистрации("РегистрацияОбработки", УровеньЖурналаРегистрации.Информация,,,
"Автоматически заполнены разделы для обработки " + ИмяОбъектаБСП);
Исключение
ЗаписьЖурналаРегистрации("РегистрацияОбработки", УровеньЖурналаРегистрации.Ошибка,,,
"Ошибка записи разделов: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Для того чтобы пользователю не приходилось совершать первый запуск вручную для настройки интерфейса, мы можем использовать штатный механизм регламентных заданий БСП. Выясним причину, почему это удобно: БСП позволяет регистрировать команды внешних обработок с видом ВызовСерверногоМетода и настраивать для них расписание запуска.
Мы можем прописать в СведенияОВнешнейОбработке() команду, которая будет выполняться по расписанию (например, один раз в день или сразу после регистрации). Внутри этой команды мы выполняем тот же самый код привязки разделов, после чего программно отключаем расписание этой команды или саму команду, чтобы она больше не нагружала сервер.
Проанализируем структуру описания такой команды в модуле объекта внешней обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("3.0.1.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Наименование = "Автоматическая обработка документов";
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Важно для модификации справочника БСП!
// Описание команды автоматической настройки
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Автоматическая настройка разделов при регистрации";
НоваяКоманда.Идентификатор = "АвтоНастройкаРазделов";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипЗапускаВызовСерверногоМетода();
НоваяКоманда.ПоказыватьОповещение = Истина;
// Настраиваем однократное расписание выполнения команды
// В типовых БСП это позволит создать регламентное задание автоматически
// Для этого используется механизм создания расписания БСП
Возврат ПараметрыРегистрации;
КонецФункции
// Метод, который вызывается БСП при выполнении команды
Процедура ВыполнитьКоманду(ИдентификаторКоманды, СопутствующиеПараметры) Экспорт
Если ИдентификаторКоманды = "АвтоНастройкаРазделов" Тогда
АвтоматическиНастроитьРазделы();
// Дополнительно можно отключить регламентное задание для этой команды,
// чтобы оно не выполнялось повторно.
ОтключитьТекущееРегламентноеЗадание();
КонецЕсли;
КонецПроцедуры
Если вам нужно массово зарегистрировать десятки обработок в сотнях баз данных, самым чистым и архитектурно правильным подходом будет использование специальной обработки-установщика (или административного скрипта).
Этот паттерн часто применяется крупными интеграторами и системными администраторами. Сценарий работы выглядит следующим образом:
ДополнительныеОтчетыИОбработки, заполняет реквизиты, загружает бинарные данные файлов и самостоятельно прописывает любые необходимые разделы в табличной части.Разберем пример кода такой внешней обработки-установщика:
Процедура ЗагрузитьИНастроитьОбработку(ПутьКФайлу, МассивИменРазделов)
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// Создаем новый элемент справочника БСП напрямую
НоваяОбработка = Справочники.ДополнительныеОтчетыИОбработки.СоздатьЭлемент();
НоваяОбработка.Наименование = "Моя рабочая обработка";
НоваяОбработка.ИмяФайла = "MyProcessing.epf";
НоваяОбработка.ХранилищеОбработки = Новый ХранилищеЗначения(ДвоичныеДанныеФайла, Новый СжатиеДанных(9));
НоваяОбработка.ИмяОбъекта = "МояРабочаяОбработка";
НоваяОбработка.Вид = Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительнаяОбработка;
НоваяОбработка.Публикация = Перечисления.ВариантыПубликацииДополнительныхОтчетовИОбработок.Используется;
// Программно заполняем разделы публикации
Для Каждого ИмяРаздела Из МассивИменРазделов Цикл
СсылкаНаРаздел = Справочники.ИдентификаторыОбъектовМетаданных.НайтиПоРеквизиту("ПолноеИмя", ИмяРаздела);
Если ЗначениеЗаполнено(СсылкаНаРаздел) Тогда
НоваяСтрока = НоваяОбработка.Разделы.Добавить();
НоваяСтрока.Раздел = СсылкаНаРаздел;
КонецЕсли;
КонецЦикла;
Попытка
НоваяОбработка.Записать();
Сообщить("Обработка успешно загружена и опубликована в выбранных разделах!");
Исключение
Сообщить("Ошибка при регистрации: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Преимущество этого паттерна в том, что целевые рабочие обработки могут продолжать функционировать в строгом безопасном режиме платформы 1С. Им больше не нужны повышенные привилегии для самозаписи, так как всю подготовительную работу выполняет внешняя обработка-установщик, запускаемая администратором с полными правами.
При использовании любого из предложенных вариантов автоматизации важно придерживаться правил хорошего тона в программировании, чтобы не нарушить работу пользователей информационной системы:
Разделы. Если администратор базы данных осознанно перенес команду обработки из раздела "Продажи" в раздел "Склад", повторная автоматическая регистрация (например, при обновлении версии файла обработки) не должна сбрасывать эти настройки на первоначальные, если только это не требуется по условиям задачи.ИдентификаторыОбъектовМетаданных вернет пустую ссылку. Код должен корректно обрабатывать такие ситуации и не вызывать аварийного завершения работы.ЖурналРегистрации. Это позволит администраторам быстро локализовать проблему, если у пользователей внезапно пропадет доступ к командам обработки в интерфейсе.Мы детально разобрали, как решить проблему отсутствия штатной настройки разделов интерфейса во внешних обработках БСП. Применяйте наиболее подходящий под ваши задачи паттерн — саморегистрацию через безопасный режим или внешний установщик — и автоматизируйте рутинную работу администраторов 1С.