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