Как определить, выполняется отмена проведения документа пользователем или программно?

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

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

Почему это важно и в чем заключается проблема

Когда вы создаете алгоритмы, автоматически меняющие состояние документов (например, при отмене проведения одного документа нужно автоматически распровести связанные с ним), вы рискуете создать бесконечную рекурсию. Если Документ1 распроводит Документ2, а тот, в свою очередь, пытается распровести Документ1, система входит в замкнутый круг. Чтобы этого избежать, нам нужно точно знать, вызвано ли действие текущим пользователем или это результат автоматического процесса.

Решение через ДополнительныеСвойства

Наиболее архитектурно правильным и универсальным способом в 1С является использование свойства ДополнительныеСвойства. Это штатный механизм платформы, позволяющий передавать произвольные данные в контексте текущего сеанса или процесса обработки объекта. Давайте рассмотрим, как это реализовать на практике.

Шаг 1: Передача признака интерактивности из формы

В модуле формы документа, в событии, которое срабатывает при нажатии кнопки пользователем, мы должны явно «пометить» объект, чтобы в модуле объекта мы могли считать эту метку. Для этого используем ДополнительныеСвойства.


// В модуле формы документа
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    // Помечаем, что запись происходит интерактивно
    Объект.ДополнительныеСвойства.Вставить("РучноеПроведение", Истина);
КонецПроцедуры

Шаг 2: Анализ признака в модуле объекта

Теперь, находясь в модуле объекта, в обработчике ОбработкаПроведения или ОбработкаУдаленияПроведения, мы можем проверить наличие этого ключа. Если ключ присутствует — значит, пользователь нажал кнопку в интерфейсе. Если ключа нет — значит, проведение было вызвано программно.


// В модуле объекта документа
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    Если ДополнительныеСвойства.Свойство("РучноеПроведение") Тогда
        // Код, выполняемый только при нажатии пользователем
    Иначе
        // Код для программного вызова
    КонецЕсли;
КонецПроцедуры

Решение проблемы цикличности при пакетной обработке

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

Рекомендуем применить подход с «семафором» или передачей списка уже распроведенных документов:

  1. Создайте массив или список ссылок документов, которые уже были распроведены в текущем цикле.
  2. Добавьте этот список в ДополнительныеСвойства перед вызовом метода Записать для следующего документа в цепочке.
  3. В начале процедуры распроведения проверяйте: если текущий документ уже есть в списке, немедленно завершайте выполнение (return).

Чего стоит избегать: работа с экспортными переменными

Иногда начинающие разработчики пытаются объявить в модуле объекта экспортную переменную, например Перем ИнтерактивнаяРабота Экспорт;, и устанавливать ее значение из формы. Мы настоятельно не рекомендуем этот подход. Вот почему:

Итоги и рекомендации

Для надежного определения источника действия следуйте этим правилам:

Применяя эти методы, вы сделаете код своей конфигурации чище, предсказуемее и защищенным от ошибок при массовых операциях с документами.

← На главную