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

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

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

Использование свойства Модифицированность

Самый простой и быстрый способ — это проверка свойства формы Модифицированность. Платформа автоматически устанавливает этот флаг в значение Истина, если пользователь начал редактировать данные на форме. Рассмотрим, как это можно реализовать в модуле формы документа в обработчике ПередЗаписью.

Проанализируем пример кода:


&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    Если Модифицированность Тогда
        Объект.ПоследнийРедактор = ПараметрыСеанса.ТекущийПользователь;
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Этот метод имеет существенный недостаток. Флаг Модифицированность может стать истинным, даже если пользователь не менял данные вручную. Например, если в коде формы (в обработчиках ПриОткрытии или ПриИзменении других реквизитов) программно меняются какие-то значения, платформа посчитает объект измененным. Более того, если пользователь просто ввел то же самое значение, которое уже было в поле, флаг все равно может взвестись.

Сравнение текущих данных со Ссылкой

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

Разберем алгоритм по шагам:

  1. В обработчике ПередЗаписью проверяем, не является ли объект новым (через ЭтоНовый()).
  2. Если объект уже существует, считываем его текущее состояние из базы по ссылке.
  3. Сравниваем нужные нам реквизиты.

Пример реализации в модуле объекта:


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

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

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

Использование версионирования объектов (БСП)

Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), то наиболее правильным и профессиональным подходом будет использование подсистемы «Версионирование объектов». Рассмотрим преимущества этого метода:

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

Метод контрольных сумм через JSON или XML

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

Посмотрим на пример логики работы:

  1. В серверном обработчике ПриЧтенииНаСервере мы преобразуем текущий объект в строку JSON и сохраняем эту строку в реквизит формы или временное хранилище.
  2. В обработчике ПередЗаписьюНаСервере мы снова переводим текущие данные формы в строку JSON.
  3. Сравниваем две строки. Если они идентичны — пользователь не изменил ни одного значимого байта данных.

Пример кода для преобразования:


&НаСервере
Функция ПолучитьХешОбъекта(ОбъектДанных)
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, ДанныеФормыВЗначение(ОбъектДанных, Тип("ДокументОбъект.РеализацияТоваровУслуг")));
    Возврат ЗаписьJSON.Закрыть();
КонецФункции

Этот метод гарантирует отсутствие «ложных срабатываний», так как сравнивается фактическое содержание всех полей объекта.

Разграничение интерактивных и программных изменений

Иногда важно понимать, изменил ли документ человек через форму или же это сделала какая-то обработка (например, групповое перепроведение). Для этого удобно использовать свойство ДополнительныеСвойства.

Выясним, как это работает:

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

Резюмируем: Выбор метода зависит от ваших целей. Если нужно простое уведомление — достаточно Модифицированности. Если важна юридическая значимость изменений — используйте Версионирование БСП. Если же вы оптимизируете производительность и хотите избежать лишних записей в базу — используйте сравнение через сериализацию в JSON.

← На главную