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