Как автоматически перенести участников Рабочей группы документа в Исполнители процесса в 1С:Документооборот?

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

В практике автоматизации документооборота часто возникает задача синхронизации прав доступа и ответственности. Например, если у нас есть "Внутренний документ" (Докладная записка), в котором уже сформирована Рабочая группа (список тех, кто имеет доступ к документу), логично предположить, что при отправке этого документа на процесс "Исполнение", исполнителями должны стать те же самые люди.

Разберем подробно, как реализовать этот механизм правильно, избежав распространенных ошибок с типами данных и производительностью, а также рассмотрим, как вывести этот список в печатную форму (шаблон).

Постановка задачи

Имеется конфигурация 1С:Документооборот КОРП версии 2.1. Требуется:

  1. При создании процесса "Исполнение" на основании документа автоматически заполнить табличную часть "Исполнители" пользователями из "Рабочей группы" этого документа. Аналогично может потребоваться автоматическое заполнение вспомогательных процессов в комплексном процессе по связям.
  2. В печатной форме документа (или шаблоне файла) вывести список этих участников с должностями.

Вариант 1: Прямое заполнение при создании (Опасный метод)

Рассмотрим подход, который часто приходит в голову в первую очередь: перехватить момент создания процесса и скопировать данные кодом. Обычно для этого используют обработчики заполнения или события формы создания бизнес-процесса.

Пример кода, который пытается перенести участников:


// Получаем рабочую группу документа
РабочаяГруппа = Документ.РабочаяГруппа;

// Очищаем текущих исполнителей процесса, если нужно
Процесс.Участники.Очистить();

// Переносим участников
Для каждого Элемент из РабочаяГруппа Цикл
    НовыйИсполнитель = Процесс.Участники.Добавить();
    НовыйИсполнитель.Роль = Элемент.Роль; // Здесь возможна ошибка, если Элемент - это просто Пользователь
    НовыйИсполнитель.Сотрудник = Элемент.Сотрудник;
КонецЦикла;

Почему этот метод не рекомендуется?

  1. Составной тип данных: В 1С:Документооборот регистр сведений РабочиеГруппы (или табличная часть в старых версиях) имеет измерение Участник (или Пользователь), которое является составным типом. Там могут быть не только Справочник.Пользователи, но и Справочник.РолиИсполнителей, Справочник.СтруктураПредприятия (подразделения) и Справочник.РабочиеГруппы. Простой перенос "один в один" вызовет ошибку или некорректное поведение, если в рабочей группе указано целое подразделение.
  2. Поддержка: При обновлении конфигурации или изменении логики процесса код придется переписывать.

Вариант 2: Использование механизма Автоподстановок (Рекомендуемый метод)

В 1С:Документооборот существует штатный механизм адресации задач — Автоподстановки. Это наиболее архитектурно верный способ решения задачи. Вместо жесткого кодирования в модуле формы, мы создаем скрипт адресации.

Алгоритм действий:

  1. Перейдем в раздел Настройка и администрирование -> Методы адресации (или Скрипты автоподстановок, в зависимости от релиза).
  2. Создадим новую автоподстановку (скрипт), назовем её "Участники рабочей группы документа". Существует сравнительно простой способ добавить пользовательские автоподстановки без сложного программирования.
  3. В шаблоне процесса "Исполнение" в поле "Исполнитель" выберем эту автоподстановку вместо конкретного пользователя. В дальнейшем вы сможете формировать отчеты для получения шаблонов процессов по автоподстановке.

В теле скрипта автоподстановки необходимо написать алгоритм, который вернет массив пользователей. Разберем правильный код для этого скрипта, учитывающий нюансы регистра сведений РабочиеГруппы.


// Скрипт автоподстановки
// Параметры: Предмет (Ссылка на документ), Объект (Процесс)

Результат = Новый Массив;

Если ТипЗнч(Предмет) <> Тип("СправочникСсылка.ВнутренниеДокументы") Тогда
    Возврат Результат; // Если процесс запущен не по документу
КонецЕсли;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   РабочиеГруппы.Участник КАК Участник
    |ИЗ
    |   РегистрСведений.РабочиеГруппы КАК РабочиеГруппы
    |ГДЕ
    |   РабочиеГруппы.Объект = &Предмет";

Запрос.УстановитьПараметр("Предмет", Предмет);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Участник = Выборка.Участник;
    
    // Обработка разных типов участников
    Если ТипЗнч(Участник) = Тип("СправочникСсылка.Пользователи") Тогда
        Результат.Добавить(Участник);
        
    ИначеЕсли ТипЗнч(Участник) = Тип("СправочникСсылка.ПолныеРоли") Тогда
        // Если это роль, добавляем её как объект адресации
        Результат.Добавить(Участник);
        
    ИначеЕсли ТипЗнч(Участник) = Тип("СправочникСсылка.СтруктураПредприятия") Тогда
        // ВНИМАНИЕ: Если в группе подразделение, нужно решить:
        // отправлять руководителю или всем сотрудникам?
        // Обычно для исполнения нужен конкретный человек.
        // Здесь можно использовать функцию получения руководителя подразделения.
        
    КонецЕсли;
КонецЦикла;

Возврат Результат;

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

Задача 2: Вывод списка участников в печатную форму

Вторая часть задачи — вывести список этих людей в шаблон документа (например, в файл Word) с указанием должностей. Рассмотрим, как это сделать оптимально.

Распространенная ошибка: Запрос в цикле

Часто разработчики пишут код следующим образом: сначала получают список пользователей, а потом в цикле для каждого вызывают функции вроде РаботаСПользователями.ПолучитьДолжность(Пользователь). Это создает высокую нагрузку на базу (проблема N+1 запросов).

Правильное решение: Единый запрос

Оптимизируем получение данных, используя соединение таблиц (JOIN) прямо в запросе. Это позволит получить ФИО, должность и подразделение за одно обращение к базе данных.

Разберем пример кода для вставки в обработчик печати:


РезультатОбработки = "";
Запрос = Новый Запрос;

// Используем ЛЕВОЕ СОЕДИНЕНИЕ для получения данных пользователя
// Учитываем, что Участник может быть не только Пользователем (используем ВЫРАЗИТЬ или проверку)
Запрос.Текст =
    "ВЫБРАТЬ
    |   ВнутренниеДокументы.Ссылка КАК Ссылка,
    |   ПРЕДСТАВЛЕНИЕ(РабочиеГруппы.Участник) КАК УчастникПредставление,
    |   Пользователи.Ссылка КАК ПользовательСсылка,
    |   ЕСТЬNULL(Пользователи.Должность, """") КАК Должность,
    |   ЕСТЬNULL(Пользователи.Подразделение, """") КАК Подразделение
    |ИЗ
    |   Справочник.ВнутренниеДокументы КАК ВнутренниеДокументы
    |       ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РабочиеГруппы КАК РабочиеГруппы
    |       ПО ВнутренниеДокументы.Ссылка = РабочиеГруппы.Объект
    |       ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК Пользователи
    |       ПО РабочиеГруппы.Участник = Пользователи.Ссылка
    |ГДЕ
    |   ВнутренниеДокументы.Ссылка = &Ссылка
    |   И РабочиеГруппы.Участник ССЫЛКА Справочник.Пользователи"; // Фильтруем только пользователей

Запрос.УстановитьПараметр("Ссылка", Файл.ВладелецФайла); // Или ссылка на документ

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

Пока Выборка.Следующий() Цикл
    // Формируем строку: Должность Подразделение ФИО
    СтрокаУчастника = Строка(Выборка.Должность) + " " + 
                      Строка(Выборка.Подразделение) + " " + 
                      Выборка.УчастникПредставление;
                      
    // Добавляем перенос строки (Символы.ПС) для красивого вывода в Word
    РезультатОбработки = РезультатОбработки + СтрокаУчастника + Символы.ПС;
КонецЦикла;

Ключевые моменты реализации

При внедрении данного решения обратите внимание на следующие нюансы:

  1. Бизнес-логика: Не всегда верно автоматически делать всех читателей (Рабочая группа) исполнителями. Часто в рабочую группу включают наблюдателей. Возможно, стоит создать отдельную роль "Исполнители документа" или использовать дополнительный реквизит.
  2. Метаданные ДО 2.1: В версиях КОРП часто используется справочник Сотрудники, а не просто Пользователи. Если у вас ведется учет по сотрудникам, в запросе выше замените Справочник.Пользователи на Справочник.Сотрудники (или таблицу сведений о сотрудниках), чтобы получить актуальные должности.
  3. Права доступа: Убедитесь, что у процесса достаточно прав для чтения состава рабочей группы документа. В привилегированном режиме (в автоподстановке) это обычно не проблема.

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

← На главную