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

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

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

Способ 1. Использование дополнительных реквизитов (Счетчик)

Самый простой и быстрый способ, предложенный в обсуждении, — добавить в сам документ служебные реквизиты. Это решение подходит, если нам нужно видеть информацию непосредственно в форме документа, использовать ее в простых запросах или формировать отчет об истории изменений за выбранный период.

Для реализации можно хранить изменения реквизитов во внешнем расширении или добавить в объект два реквизита:

  1. СчетчикПроведений (Тип: Число) — будет хранить количество успешных проведений.
  2. БылВПроведении (Тип: Булево) — флаг, который устанавливается в Истину при первом проведении и никогда не сбрасывается.

Логику заполнения лучше всего разместить в событии ПередЗаписью модуля объекта. Нам необходимо проанализировать режим записи и текущее состояние документа.


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Если документ записывается в режиме проведения
    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        // Увеличиваем счетчик
        СчетчикПроведений = СчетчикПроведений + 1;
        
        // Фиксируем исторический факт, что документ был проведен хотя бы раз
        БылВПроведении = Истина;
        
    КонецЕсли;

КонецПроцедуры

Важно понимать особенность транзакций: если в процессе проведения возникнет ошибка и транзакция откатится, значение счетчика также вернется к прежнему состоянию. Таким образом, этот метод считает только успешные проведения.

Способ 2. Определение типа действия (Первичное, Перепроведение, Отмена)

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

Разберем логику определения состояния в процедуре ПередЗаписью:


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

    ЭтоНовыйДокумент = ЭтоНовый();
    // Получаем статус проведения, который сейчас записан в базе
    // Для нового документа он всегда Ложь
    УжеПроведенВБазе = ?(ЭтоНовыйДокумент, Ложь, Ссылка.Проведен);

    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        Если НЕ УжеПроведенВБазе Тогда
            // Это ПЕРВИЧНОЕ проведение
            // Можно зафиксировать дату первого проведения
        Иначе
            // Это ПЕРЕПРОВЕДЕНИЕ
            // Можно увеличить счетчик изменений
        КонецЕсли;
        
    ИначеЕсли РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения Тогда
        
        // Это ОТМЕНА проведения
        // Здесь можно залогировать факт отмены
        
    КонецЕсли;

КонецПроцедуры

Способ 3. Использование независимого регистра сведений

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

В этом случае при каждом значимом событии мы будем создавать запись в регистре. Это позволит нам:

  1. Знать, кто и когда менял статус.
  2. Видеть всю цепочку: Проведен -> Отмена -> Проведен.
  3. Не блокировать таблицу документа лишними данными.

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

Способ 4. Использование штатных механизмов платформы

Не стоит забывать про встроенные возможности платформы 1С, которые могут решить задачу без написания кода.

1. Журнал регистрации (ЖР)
В ЖР автоматически фиксируются события «Проведение» и «Отмена проведения».
Плюсы: не нужно программировать, фиксирует все попытки.
Минусы: сложно программно анализировать «на лету» (чтение журнала — медленная операция), журнал может быть очищен администратором.

2. История данных (Версионирование)
В современных конфигурациях (БСП) или на уровне платформы (История данных) можно включить хранение версий объектов. С помощью метода ИсторияДанных.ПолучитьВерсии() можно программно узнать количество версий объекта. Однако, это ресурсоемкая операция, и использовать ее при каждом проведении не рекомендуется.

Рекомендации по безопасности и производительности

При внедрении счетчиков или логирования обратите внимание на следующие моменты:

  1. Групповое перепроведение: Если вы добавите сложную логику проверки (например, "платное перепроведение" или запрет на изменение более 3 раз), это может сломать регламентные операции закрытия месяца. Обязательно проверяйте, проводится документ интерактивно пользователем или фоновым заданием.
  2. Блокировки: Избегайте чтения больших объемов данных (например, сканирования Журнала регистрации) внутри транзакции записи документа. Это приведет к замедлению работы всей системы.
← На главную