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