В процессе настройки согласования в 1С:Документооборот часто возникает потребность в гибком подборе исполнителей. Типовые автоподстановки позволяют выбрать всех руководителей или только непосредственного начальника, но бизнес-логика иногда требует исключить из цепочки «самого главного» — например, руководителя службы или директора предприятия, чтобы не отвлекать их от рутинных задач. В этой статье мы подробно разберем, как написать и внедрить собственную автоподстановку «Все руководители автора, кроме последнего».
Представим структуру: Контролер — Заместитель старшего контролера — Старший контролер — Руководитель службы качества. Нам нужно, чтобы документ прошел согласование по всей цепочке вверх, но остановился на Старшем контролере, не попадая к Руководителю службы. Для реализации этого функционала нам потребуется внести изменения в общий модуль ШаблоныБизнесПроцессовПереопределяемый. Именно этот модуль предназначен для расширения списка функций автоподстановки без вмешательства в ядро системы.
Чтобы система «увидела» нашу функцию в адресной книге или в шаблоне процесса, ее нужно зарегистрировать в функции ПолучитьСписокДоступныхФункций. Рассмотрим, как правильно дополнить этот список, чтобы не нарушить работу существующих механизмов.
Проанализируем пример кода для регистрации:
Функция ПолучитьСписокДоступныхФункций(ИменаПредметовДляФункций) Экспорт
ДоступныеФункции = Новый СписокЗначений;
// Регистрируем функцию для автора самого процесса
ДоступныеФункции.Добавить("ШаблоныБизнесПроцессовПереопределяемый.ВсеРуководителиАвтораБизнесПроцессаКромеПоследнего(Объект)",
"Все руководители автора бизнес процесса кроме последнего");
Если ИменаПредметовДляФункций <> Неопределено Тогда
Если ИменаПредметовДляФункций.Количество() > 0 Тогда
Для Каждого ИмяПредмета Из ИменаПредметовДляФункций Цикл
// Регистрируем функцию для конкретного предмета (документа)
ДоступныеФункции.Добавить("ШаблоныБизнесПроцессовПереопределяемый.ВсеРуководителиАвтораДокументаКромеПоследнего(Объект, ИмяПредмета)",
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = '%1.Все руководители автора документа кроме последнего'"), Строка(ИмяПредмета)));
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат ДоступныеФункции;
КонецФункции
Важный нюанс: при редактировании этого модуля убедитесь, что вы не дублируете функцию ПолучитьСписокДоступныхФункций, если она уже создана. Нужно просто дописать свои строки в существующее тело функции. Также обратите внимание на Возврат ДоступныеФункции — он должен стоять в самом конце, вне цикла, иначе регистрация прервется на первом же предмете.
Теперь разберем алгоритм поиска. Нам нужно двигаться от подразделения автора вверх к родительским подразделениям, собирать их руководителей и остановиться за шаг до «вершины». Выясним причину, по которой мы используем цикл Пока: структура предприятия может иметь неограниченную вложенность.
Рассмотрим код основной функции:
Функция ВсеРуководителиАвтораДокументаКромеПоследнего(БизнесПроцессОбъект, ИмяПредмета) Экспорт
// 1. Поиск предмета в процессе
СтрокаПредмета = БизнесПроцессОбъект.Предметы.Найти(ИмяПредмета, "ИмяПредмета");
Если СтрокаПредмета = Неопределено Тогда
// Если предмет не найден по имени, попробуем взять основной (индекс 0)
Если БизнесПроцессОбъект.Предметы.Количество() > 0 Тогда
СтрокаПредмета = БизнесПроцессОбъект.Предметы[0];
Иначе
Возврат Новый Массив;
КонецЕсли;
КонецЕсли;
// 2. Определение автора документа
АвторДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СтрокаПредмета.Предмет, "Подготовил");
МассивРуководителей = Новый Массив;
// 3. Получение подразделения автора через регистр сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СведенияОПользователях.Подразделение КАК Подразделение
|ИЗ
| РегистрСведений.СведенияОПользователяхДокументооборот КАК СведенияОПользователях
|ГДЕ
| СведенияОПользователях.Пользователь = &Пользователь";
Запрос.УстановитьПараметр("Пользователь", АвторДокумента);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат МассивРуководителей;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Подразделение = Выборка.Подразделение;
// 4. Цикл по иерархии подразделений
Пока ЗначениеЗаполнено(Подразделение) Цикл
// Проверяем, есть ли у текущего подразделения вышестоящее (Родитель)
// Если родителя нет, значит это "последнее" подразделение, и его руководителя мы не берем
Если Не ЗначениеЗаполнено(Подразделение.Родитель) Тогда
Прервать;
КонецЕсли;
РеквизитыПодразделения = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Подразделение,
"Руководитель, Руководитель.Недействителен, Родитель");
Руководитель = РеквизитыПодразделения.Руководитель;
Если ЗначениеЗаполнено(Руководитель) И Руководитель <> АвторДокумента Тогда
Если НЕ РеквизитыПодразделения.РуководительНедействителен Тогда
МассивРуководителей.Добавить(Руководитель);
КонецЕсли;
КонецЕсли;
Подразделение = РеквизитыПодразделения.Родитель;
КонецЦикла;
Возврат МассивРуководителей;
КонецФункции
Проанализируем ситуацию, описанную пользователями на практике: что произойдет, если у сотрудника всего один руководитель (он же последний)? В этом случае функция вернет пустой массив. Система 1С:Документооборот при попытке старта процесса выдаст критическую ошибку: Не найдены исполнители для автоподстановки.
Для решения этой проблемы рассмотрим два подхода:
МассивРуководителей.Количество() = 0, можно возвращать технического пользователя (например, администратора) или самого автора, чтобы процесс не «падал», но это требует согласования с бизнес-заказчиком.После того как код написан и конфигурация обновлена, новые пункты не всегда сразу появляются в списке выбора. Выясним, как принудительно обновить кэш системы:
Только после этого действия система перечитает содержимое модуля ШаблоныБизнесПроцессовПереопределяемый и добавит ваши функции в список доступных.
При использовании в комплексных процессах может возникнуть ошибка Не найден предмет процесса. Это происходит потому, что в комплексном процессе предметы могут называться иначе, чем в простых задачах (например, «Документ» вместо «Основной предмет»). Чтобы код был универсальным, мы добавили проверку: если ИмяПредмета не найдено в коллекции, берется первый доступный предмет. Это гарантирует стабильную работу автоподстановки даже при нетипичных настройках шаблона.
Совет: Если вы планируете использовать эту логику в 1С:Документооборот версии 3.0, помните, что там работа с автоподстановками может быть реализована через скрипты в правилах обработки документов, что позволяет избежать изменения конфигурации в ряде случаев.