Как получить дополнительные реквизиты объекта и динамически назначить исполнителей в бизнес-процесс 1С:Документооборот?

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

Рассмотрим частую задачу разработчиков при внедрении конфигурации «1С:Документооборот»: создание дополнительного обработчика, который автоматически запускает процесс ознакомления после согласования документа. При этом список адресатов должен формироваться динамически на основе дополнительных реквизитов документа (например, свойств «Адресат 2», «Адресат 3» и так далее).

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

Проблема 1: Как правильно получить дополнительные реквизиты?

В типовых конфигурациях 1С дополнительные реквизиты хранятся в специальных табличных частях объектов. Начинающие разработчики часто пытаются извлечь их с помощью прямых запросов к базе данных, отбирая записи по строковому наименованию свойства (например, ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Адресат 2")).

Проанализируем ситуацию: это плохая практика. Пользователь с правами настройки НСИ может в любой момент переименовать реквизит в режиме предприятия (например, назвать его «Второй адресат»), и наш программный код моментально перестанет работать. Кроме того, прямые запросы к табличным частям требуют тщательного контроля прав доступа и параметров.

Правильным и надежным подходом является использование программного интерфейса БСП — общего модуля УправлениеСвойствами. Рассмотрим подробнее методы, которые там доступны:

  1. УправлениеСвойствами.ПолучитьСписокСвойств() — возвращает все доступные свойства для переданного объекта.
  2. УправлениеСвойствами.ПолучитьЗначенияСвойств() — возвращает таблицу значений с заполненными данными по этим свойствам.
  3. УправлениеСвойствами.ЗначениеСвойства(СсылкаНаОбъект, СсылкаНаДопРеквизит) — позволяет получить значение конкретного реквизита.

Важный совет: В актуальных версиях БСП и «1С:Документооборот» у дополнительных реквизитов есть поле «Имя (для разработчиков)». Настоятельно рекомендуем задавать там уникальный латинский идентификатор (например, Addressee2) и обращаться к реквизиту именно по нему, а не по строковому представлению.

Проблема 2: Как извлечь пользователей из подразделения или рабочей группы?

Допустим, мы получили значение дополнительного реквизита. У него составной тип данных: это может быть конкретный СправочникСсылка.Пользователи, либо СправочникСсылка.СтруктураПредприятия (подразделение), либо СправочникСсылка.РабочиеГруппы.

Если мы просто попытаемся добавить ссылку на подразделение в табличную часть Исполнители создаваемого бизнес-процесса, платформа выдаст ошибку несоответствия типов. Бизнес-процессу нужны конкретные исполнители. Значит, нам нужно «развернуть» эти объекты-контейнеры до списка конкретных сотрудников.

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

  1. Для подразделений: Справочники.СтруктураПредприятия.СоставКонтейнераПользователей(СсылкаНаПодразделение)
  2. Для рабочих групп: Справочники.РабочиеГруппы.СоставКонтейнераПользователей(СсылкаНаГруппу)

Обе функции возвращают массив или таблицу пользователей, которых мы можем простым циклом добавить в маршрут нашего бизнес-процесса.

Полный пример рабочего кода для дополнительного обработчика

Посмотрим на итоговый рабочий пример кода для дополнительного обработчика бизнес-события. Код отрабатывает при успешном завершении процесса согласования, собирает адресатов из доп. реквизитов и запускает новый процесс ознакомления:


БизнесПроцесс = Событие.Источник;

Если ТипЗнч(БизнесПроцесс) = Тип("БизнесПроцессСсылка.Согласование") 
     И (БизнесПроцесс.РезультатСогласования = Перечисления.РезультатыСогласования.Согласовано 
     ИЛИ БизнесПроцесс.РезультатСогласования = Перечисления.РезультатыСогласования.СогласованоСЗамечаниями) Тогда
    
    ТипыДокументов = Новый Массив;
    ТипыДокументов.Добавить(Тип("СправочникСсылка.ВнутренниеДокументы"));
    
    ВидыДокументов = Новый Массив;
    ВидыДокументов.Добавить(Справочники.ВидыВнутреннихДокументов.НайтиПоНаименованию("_Служебная записка"));
    
    // Получаем предмет согласования
    ОсновныеПредметы = МультипредметностьКлиентСервер.ПолучитьМассивПредметовОбъекта(БизнесПроцесс, ТипыДокументов, Истина);
    
    Для Каждого Предмет ИЗ ОсновныеПредметы Цикл
        
        Если ВидыДокументов.Найти(Предмет.ВидДокумента) <> Неопределено Тогда
            
            ШаблонПроцесса = Справочники.ШаблоныОзнакомления.НайтиПоНаименованию("Ознакомление адресата");
            Если ШаблонПроцесса <> Неопределено Тогда
                
                Процесс = БизнесПроцессы.Ознакомление.СоздатьБизнесПроцесс();
                Процесс.Заполнить(Новый Структура("Предметы, Шаблон", Предмет, ШаблонПроцесса));
                Процесс.Автор = Предмет.Подготовил;
                
                // Получаем доп. свойства предмета
                СписокСвойств = УправлениеСвойствами.ПолучитьСписокСвойств(Предмет);
                СписокЗначений = УправлениеСвойствами.ПолучитьЗначенияСвойств(Предмет);
                
                Для Каждого Свойство ИЗ СписокСвойств Цикл
                    // Ищем нужные доп. реквизиты (рекомендуется переделать на поиск по Имени для разработчиков)
                    Если Лев(Свойство.Заголовок, 8) = "Адресат " Тогда
                        
                        ДопАдресатЗначение = СписокЗначений.Найти(Свойство.Ссылка, "Свойство").Значение;
                        
                        Если ЗначениеЗаполнено(ДопАдресатЗначение) Тогда
                            
                            // Обрабатываем конкретного пользователя
                            Если ТипЗнч(ДопАдресатЗначение) = Тип("СправочникСсылка.Пользователи") Тогда
                                Строка = Процесс.Исполнители.Добавить();
                                Строка.Исполнитель = ДопАдресатЗначение;
                                
                            // Обрабатываем подразделение
                            ИначеЕсли ТипЗнч(ДопАдресатЗначение) = Тип("СправочникСсылка.СтруктураПредприятия") Тогда
                                ПользователиПодразделения = Справочники.СтруктураПредприятия.СоставКонтейнераПользователей(ДопАдресатЗначение);
                                Для Каждого Пользователь ИЗ ПользователиПодразделения Цикл
                                    Строка = Процесс.Исполнители.Добавить();
                                    Строка.Исполнитель = Пользователь;
                                КонецЦикла;
                                
                            // Обрабатываем рабочую группу
                            ИначеЕсли ТипЗнч(ДопАдресатЗначение) = Тип("СправочникСсылка.РабочиеГруппы") Тогда
                                ПользователиРабочейГруппы = Справочники.РабочиеГруппы.СоставКонтейнераПользователей(ДопАдресатЗначение);
                                Для Каждого Пользователь ИЗ ПользователиРабочейГруппы Цикл
                                    Строка = Процесс.Исполнители.Добавить();
                                    Строка.Исполнитель = Пользователь;
                                КонецЦикла;
                            КонецЕсли;
                            
                        КонецЕсли;
                    КонецЕсли;
                КонецЦикла;
                
                Процесс.Дата = ТекущаяДата();
                Процесс.Записать();
                Процесс.Старт();
                
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Добавление исполнителей в запущенный бизнес-процесс

Выясним причину, почему нельзя просто добавить новую строку кода вида БизнесПроцесс.Исполнители.Добавить() в уже стартовавший процесс. Архитектура движка платформы 1С устроена так, что она считывает табличную часть адресатов/исполнителей исключительно в момент старта процесса или при переходе маршрута на соответствующую точку действия.

Чтобы добавить исполнителя в процесс программно «на лету», недостаточно записать измененный бизнес-процесс. Потребуется обращаться к серверному API 1С:ДО для генерации физического объекта ЗадачаИсполнителя и корректной привязки к нужной точке маршрута. Гораздо проще и правильнее в типовых механизмах использовать пользовательский режим: вкладки «Визы» или «Процессы и задачи» в карточке документа имеют специальную кнопку «Добавить в процесс», которая выполнит всю служебную работу за пользователя.

Настройка видимости задач руководителем (без доработки кода)

Разберем еще один смежный вопрос: что делать, если руководитель хочет видеть все задачи, падающие на его заместителя (например, по исходящим письмам)? Писать код и создавать дубликаты задач на ознакомление — избыточно и вредно для базы.

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

  1. Делегирование и замещение. Можно настроить права через функционал «Замещающие и помощники», предоставив руководителю доступ к просмотру задач своего заместителя.
  2. Механизм контроля. При настройке шаблонов процессов укажите руководителя в роли контролера на определенных этапах. Задачи не будут дублироваться, но руководитель увидит всё в удобном рабочем месте «На контроле».
  3. Автоподстановки в шаблонах. Если руководитель все же должен быть в листе согласования или ознакомления, воспользуйтесь стандартными автоподстановками (например, «Все руководители исполнителя» или «Линейный руководитель»). Программа сама рассчитает иерархию и добавит нужных лиц на основе организационной структуры.
← На главную