Как при записи документа отличить интерактивное действие пользователя от групповой или программной обработки

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

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

В платформе 1С прямого встроенного флага «ЗаписаноИнтерактивно» в событии ПриЗаписи объекта нет. Рассмотрим подробнее основные архитектурные подходы, которые позволяют красиво и глобально решить эту задачу.

Способ 1. Использование подписки на событие «ОбработкаПроверкиЗаполнения»

Событие ОбработкаПроверкиЗаполнения вызывается расширением формы, когда пользователь интерактивно записывает или проводит документ из формы (а также при явном вызове метода ПроверитьЗаполнение()). Это делает его удобной точкой для выполнения действий, предназначенных исключительно для интерактивного режима.

Разберем, как настраивается подписка на это событие:

  1. Создадим подписку на событие в дереве метаданных.
  2. В качестве источника выберем необходимые документы.
  3. В качестве события укажем ОбработкаПроверкиЗаполнения.
  4. В обработчике подписки пропишем требуемую логику изменения реквизита.

Посмотрим на пример кода в общем модуле:


Процедура ПодпискаОбработкаПроверкиЗаполнения(Источник, Отказ, ПроверяемыеРеквизиты) Экспорт
    
    // Меняем ответственного только при интерактивном действии
    Источник.Ответственный = Пользователи.ТекущийПользователь();
    
КонецПроцедуры

Нюансы метода:

Проанализируем особенности поведения этого события:

  1. Если у документа свойство Проведение установлено в значение Разрешить, данное событие вызывается только при проведении документа. При нажатии кнопки «Записать» без проведения проверка заполнения и данный обработчик вызваны не будут.
  2. Если системный код внешних обработок явно содержит вызов Объект.ПроверитьЗаполнение(), событие сработает и при таком программном вызове.

Способ 2. Инверсия логики с использованием «ДополнительныеСвойства»

Если нам нужно отлавливать запись именно в событии ПередЗаписью или ПриЗаписи, стандартным механизмом платформы является структура ДополнительныеСвойства объекта.

Чтобы не вносить изменения в форму каждого документа, заменим подходы: будем считать любую запись по умолчанию интерактивной, а при выполнении групповых обработок или программного проведения будем явно передавать признак групповой записи.

Разберем по шагам реализацию этой схемы:

Шаг 1. В коде групповой обработки перед вызовом метода Записать() добавляем флаг в дополнительные свойства объекта:


ДокументОбъект = СсылкаНаДок.ПолучитьОбъект();
ДокументОбъект.ДополнительныеСвойства.Вставить("ГрупповаяОбработка", Истина);
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

Шаг 2. В подписке на событие ПриЗаписи или ПередЗаписью проверяем наличие этого флага:


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

Способ 3. Анализ контекста выполнения через «ИмяПриложения()»

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

Выясним, как проверить контекст выполнения в обработчике события:


Процедура ПодпискаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    ТекущееПриложение = ИмяПриложения();
    
    // Проверяем, что запись идет из тонкого, толстого или веб-клиента
    ИнтерактивныйРежим = (ТекущееПриложение = "1CV8") 
                      Или (ТекущееПриложение = "1CV8C") 
                      Или (ТекущееПриложение = "WebClient");
                      
    Если ИнтерактивныйРежим Тогда
        // Запись выполняется пользователем из клиента
    КонецЕсли;
    
КонецПроцедуры

Альтернативные архитектурные варианты

Если требуется хранить подробные данные о том, кто и как менял документ, без постоянной перезаписи основного реквизита Ответственный, рассмотрим следующие решения:

  1. Подсистема «Версионирование объектов» из БСП: позволяет фиксировать историю всех изменений документов с подробной информацией о пользователе, времени и изменившихся реквизитах.
  2. Отдельный регистр сведений: ведение истории смены ответственных или авторов изменений в регистре сведений. В этом случае подписка фиксирует факт изменения в независимом регистре, не затрагивая сам документ.
← На главную