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