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